diff options
177 files changed, 5497 insertions, 1661 deletions
diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 28c6bb3679..df727518e5 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -23,6 +23,6 @@ jobs: with: submodules: recursive - name: Install dependencies - run: pip3 install -r requirements.txt + run: pip3 install -r requirements-dev.txt - name: Run tests run: bin/qmk pytest diff --git a/.gitignore b/.gitignore index ec04818547..06632a144a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.eep *.elf *.hex +*.uf2 *.qmk !util/bootloader.hex !quantum/tools/eeprom_reset.hex @@ -29,6 +29,13 @@ $(info QMK Firmware $(QMK_VERSION)) endif endif +# Determine which qmk cli to use +ifeq (,$(shell which qmk)) + QMK_BIN = bin/qmk +else + QMK_BIN = qmk +endif + # avoid 'Entering|Leaving directory' messages MAKEFLAGS += --no-print-directory @@ -86,8 +93,8 @@ clean: .PHONY: distclean distclean: clean - echo -n 'Deleting *.bin and *.hex ... ' - rm -f *.bin *.hex + echo -n 'Deleting *.bin, *.hex, and *.uf2 ... ' + rm -f *.bin *.hex *.uf2 echo 'done.' #Compatibility with the old make variables, anything you specify directly on the command line @@ -396,7 +403,7 @@ define PARSE_KEYMAP # Format it in bold KB_SP := $(BOLD)$$(KB_SP)$(NO_COLOR) # Specify the variables that we are passing forward to submake - MAKE_VARS := KEYBOARD=$$(CURRENT_KB) KEYMAP=$$(CURRENT_KM) REQUIRE_PLATFORM_KEY=$$(REQUIRE_PLATFORM_KEY) + MAKE_VARS := KEYBOARD=$$(CURRENT_KB) KEYMAP=$$(CURRENT_KM) REQUIRE_PLATFORM_KEY=$$(REQUIRE_PLATFORM_KEY) QMK_BIN=$$(QMK_BIN) # And the first part of the make command MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f build_keyboard.mk $$(MAKE_TARGET) # The message to display @@ -513,8 +520,8 @@ endef %: # Check if we have the CMP tool installed cmp $(ROOT_DIR)/Makefile $(ROOT_DIR)/Makefile >/dev/null 2>&1; if [ $$? -gt 0 ]; then printf "$(MSG_NO_CMP)"; exit 1; fi; - # Ensure that bin/qmk works. - if ! bin/qmk hello 1> /dev/null 2>&1; then printf "$(MSG_PYTHON_MISSING)"; exit 1; fi + # Ensure that $(QMK_BIN) works. + if ! $(QMK_BIN) hello 1> /dev/null 2>&1; then printf "$(MSG_PYTHON_MISSING)"; exit 1; fi # Check if the submodules are dirty, and display a warning if they are ifndef SKIP_GIT if [ ! -e lib/chibios ]; then git submodule sync lib/chibios && git submodule update --depth 50 --init lib/chibios; fi @@ -29,9 +29,13 @@ def main(): """ # Change to the root of our checkout os.environ['ORIG_CWD'] = os.getcwd() + os.environ['DEPRECATED_BIN_QMK'] = '1' os.chdir(qmk_dir) + print('Warning: The bin/qmk script is being deprecated. Please install the QMK CLI: python3 -m pip install qmk', file=sys.stderr) + # Import the subcommands + import milc.subcommand.config # noqa import qmk.cli # noqa # Execute diff --git a/bootloader.mk b/bootloader.mk index fd76446e99..4f2d69d998 100644 --- a/bootloader.mk +++ b/bootloader.mk @@ -89,11 +89,17 @@ ifeq ($(strip $(BOOTLOADER)), USBasp) BOOTLOADER_SIZE = 4096 endif ifeq ($(strip $(BOOTLOADER)), lufa-ms) - # DO NOT USE THIS BOOTLOADER IN NEW PROJECTS! - # It is extremely prone to bricking, and is only included to support existing boards. OPT_DEFS += -DBOOTLOADER_MS - BOOTLOADER_SIZE = 6144 + BOOTLOADER_SIZE ?= 8192 FIRMWARE_FORMAT = bin +cpfirmware: lufa_warning +.INTERMEDIATE: lufa_warning +lufa_warning: $(FIRMWARE_FORMAT) + $(info @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) + $(info LUFA MASS STORAGE Bootloader selected) + $(info DO NOT USE THIS BOOTLOADER IN NEW PROJECTS!) + $(info It is extremely prone to bricking, and is only included to support existing boards.) + $(info @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) endif ifdef BOOTLOADER_SIZE OPT_DEFS += -DBOOTLOADER_SIZE=$(strip $(BOOTLOADER_SIZE)) @@ -137,3 +143,6 @@ ifeq ($(strip $(BOOTLOADER)), stm32duino) DFU_ARGS = -d 1EAF:0003 -a 2 -R DFU_SUFFIX_ARGS = -v 1EAF -p 0003 endif +ifeq ($(strip $(BOOTLOADER)), tinyuf2) + OPT_DEFS += -DBOOTLOADER_TINYUF2 +endif diff --git a/build_json.mk b/build_json.mk index 6e2f9c4c8f..8822be6a12 100644 --- a/build_json.mk +++ b/build_json.mk @@ -28,4 +28,4 @@ endif # Generate the keymap.c $(KEYBOARD_OUTPUT)/src/keymap.c: $(KEYMAP_JSON) - bin/qmk json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON) + $(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON) diff --git a/build_keyboard.mk b/build_keyboard.mk index ec6b026c50..91a6c23b71 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -12,6 +12,9 @@ endif include common.mk +# Set the qmk cli to use +QMK_BIN ?= qmk + # Set the filename for the final firmware binary KEYBOARD_FILESAFE := $(subst /,_,$(KEYBOARD)) TARGET ?= $(KEYBOARD_FILESAFE)_$(KEYMAP) @@ -97,7 +100,7 @@ MAIN_KEYMAP_PATH_4 := $(KEYBOARD_PATH_4)/keymaps/$(KEYMAP) MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP) # Pull in rules from info.json -INFO_RULES_MK = $(shell bin/qmk generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/rules.mk) +INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/rules.mk) include $(INFO_RULES_MK) # Check for keymap.json first, so we can regenerate keymap.c @@ -295,13 +298,13 @@ endif CONFIG_H += $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/layouts.h $(KEYBOARD_OUTPUT)/src/info_config.h: $(INFO_JSON_FILES) - bin/qmk generate-config-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_config.h + $(QMK_BIN) generate-config-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/default_keyboard.h: $(INFO_JSON_FILES) - bin/qmk generate-keyboard-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/default_keyboard.h + $(QMK_BIN) generate-keyboard-h --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/default_keyboard.h $(KEYBOARD_OUTPUT)/src/layouts.h: $(INFO_JSON_FILES) - bin/qmk generate-layouts --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/layouts.h + $(QMK_BIN) generate-layouts --quiet --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/layouts.h generated-files: $(KEYBOARD_OUTPUT)/src/info_config.h $(KEYBOARD_OUTPUT)/src/default_keyboard.h $(KEYBOARD_OUTPUT)/src/layouts.h diff --git a/common_features.mk b/common_features.mk index 74b8c1046b..2789a3620c 100644 --- a/common_features.mk +++ b/common_features.mk @@ -203,14 +203,17 @@ VALID_LED_MATRIX_TYPES := IS31FL3731 custom ifeq ($(strip $(LED_MATRIX_ENABLE)), yes) ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),) - $(error LED_MATRIX_DRIVER="$(LED_MATRIX_DRIVER)" is not a valid matrix type) - else - BACKLIGHT_ENABLE = yes - BACKLIGHT_DRIVER = custom - OPT_DEFS += -DLED_MATRIX_ENABLE - SRC += $(QUANTUM_DIR)/led_matrix.c - SRC += $(QUANTUM_DIR)/led_matrix_drivers.c + $(error "$(LED_MATRIX_DRIVER)" is not a valid matrix type) endif + OPT_DEFS += -DLED_MATRIX_ENABLE +ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162)) + # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines + OPT_DEFS += -DLIB8_ATTINY +endif + SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c + SRC += $(QUANTUM_DIR)/led_matrix.c + SRC += $(QUANTUM_DIR)/led_matrix_drivers.c + CIE1931_CURVE := yes ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731) OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE @@ -327,7 +330,11 @@ endif VALID_BACKLIGHT_TYPES := pwm timer software custom BACKLIGHT_ENABLE ?= no -BACKLIGHT_DRIVER ?= pwm +ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes) + BACKLIGHT_DRIVER ?= software +else + BACKLIGHT_DRIVER ?= pwm +endif ifeq ($(strip $(BACKLIGHT_ENABLE)), yes) ifeq ($(filter $(BACKLIGHT_DRIVER),$(VALID_BACKLIGHT_TYPES)),) $(error BACKLIGHT_DRIVER="$(BACKLIGHT_DRIVER)" is not a valid backlight type) @@ -402,10 +409,6 @@ ifeq ($(strip $(TERMINAL_ENABLE)), yes) OPT_DEFS += -DUSER_PRINT endif -ifeq ($(strip $(USB_HID_ENABLE)), yes) - include $(TMK_DIR)/protocol/usb_hid.mk -endif - ifeq ($(strip $(WPM_ENABLE)), yes) SRC += $(QUANTUM_DIR)/wpm.c OPT_DEFS += -DWPM_ENABLE @@ -445,6 +448,23 @@ ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes) SRC += $(QUANTUM_DIR)/dip_switch.c endif +VALID_MAGIC_TYPES := yes full lite +BOOTMAGIC_ENABLE ?= no +ifneq ($(strip $(BOOTMAGIC_ENABLE)), no) + ifeq ($(filter $(BOOTMAGIC_ENABLE),$(VALID_MAGIC_TYPES)),) + $(error BOOTMAGIC_ENABLE="$(BOOTMAGIC_ENABLE)" is not a valid type of magic) + endif + ifneq ($(strip $(BOOTMAGIC_ENABLE)), full) + OPT_DEFS += -DBOOTMAGIC_LITE + QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/bootmagic_lite.c + else + OPT_DEFS += -DBOOTMAGIC_ENABLE + QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/bootmagic_full.c + endif +endif +COMMON_VPATH += $(QUANTUM_DIR)/bootmagic +QUANTUM_SRC += $(QUANTUM_DIR)/bootmagic/magic.c + VALID_CUSTOM_MATRIX_TYPES:= yes lite no CUSTOM_MATRIX ?= no diff --git a/data/mappings/keyboard_aliases.json b/data/mappings/keyboard_aliases.json index 5a2f7e3ae8..c205b5e13e 100644 --- a/data/mappings/keyboard_aliases.json +++ b/data/mappings/keyboard_aliases.json @@ -59,8 +59,11 @@ 'cmm_studio/saka68': { target: 'cmm_studio/saka68/solder' }, - 'crkbd/rev1': { - target: 'crkbd/rev1/legacy' + 'crkbd/rev1/legacy': { + target: 'crkbd/rev1' + }, + 'crkbd/rev1/common': { + target: 'crkbd/rev1' }, 'doro67/multi': { layouts: { diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema index ec03a8828b..c335f49d52 100644 --- a/data/schemas/keyboard.jsonschema +++ b/data/schemas/keyboard.jsonschema @@ -25,7 +25,7 @@ }, "processor": { "type": "string", - "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F411", "STM32G431", "STM32G474", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"] + "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66F18", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L433", "STM32L443", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"] }, "board": { "type": "string", @@ -34,7 +34,7 @@ }, "bootloader": { "type": "string", - "enum": ["atmel-dfu", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "stm32-dfu", "stm32duino", "unknown", "USBasp"] + "enum": ["atmel-dfu", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "stm32-dfu", "stm32duino", "unknown", "USBasp", "tinyuf2"] }, "diode_direction": { "type": "string", diff --git a/drivers/avr/spi_master.c b/drivers/avr/spi_master.c index 19ca0ced44..4e8fd3bcdf 100644 --- a/drivers/avr/spi_master.c +++ b/drivers/avr/spi_master.c @@ -14,10 +14,8 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#include <avr/io.h> - #include "spi_master.h" -#include "quantum.h" + #include "timer.h" #if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) diff --git a/drivers/avr/spi_master.h b/drivers/avr/spi_master.h index 9203698dd5..8a30f47ae4 100644 --- a/drivers/avr/spi_master.h +++ b/drivers/avr/spi_master.h @@ -16,7 +16,9 @@ #pragma once -#include "quantum.h" +#include <stdbool.h> + +#include "gpio.h" typedef int16_t spi_status_t; diff --git a/drivers/chibios/analog.c b/drivers/chibios/analog.c index 2b3872afbb..8c476fcac2 100644 --- a/drivers/chibios/analog.c +++ b/drivers/chibios/analog.c @@ -101,7 +101,11 @@ // Options are 12, 10, 8, and 6 bit. #ifndef ADC_RESOLUTION -# define ADC_RESOLUTION ADC_CFGR1_RES_10BIT +# ifdef ADC_CFGR_RES_10BITS // ADCv3, ADCv4 +# define ADC_RESOLUTION ADC_CFGR_RES_10BITS +# else // ADCv1, ADCv5, or the bodge for ADCv2 above +# define ADC_RESOLUTION ADC_CFGR1_RES_10BIT +# endif #endif static ADCConfig adcCfg = {}; @@ -119,7 +123,7 @@ static ADCConversionGroup adcConversionGroup = { .smpr = ADC_SAMPLING_RATE, #elif defined(USE_ADCV2) # if !defined(STM32F1XX) - .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without... + .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without... # endif .smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE), .smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE), @@ -161,8 +165,8 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) { case B0: return TO_MUX( ADC_CHANNEL_IN12, 2 ); case B1: return TO_MUX( ADC_CHANNEL_IN1, 2 ); case B2: return TO_MUX( ADC_CHANNEL_IN12, 1 ); - case B12: return TO_MUX( ADC_CHANNEL_IN2, 3 ); - case B13: return TO_MUX( ADC_CHANNEL_IN3, 3 ); + case B12: return TO_MUX( ADC_CHANNEL_IN3, 3 ); + case B13: return TO_MUX( ADC_CHANNEL_IN5, 2 ); case B14: return TO_MUX( ADC_CHANNEL_IN4, 3 ); case B15: return TO_MUX( ADC_CHANNEL_IN5, 3 ); case C0: return TO_MUX( ADC_CHANNEL_IN6, 0 ); // Can also be ADC2 @@ -189,11 +193,52 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) { case E15: return TO_MUX( ADC_CHANNEL_IN2, 3 ); case F2: return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2 case F4: return TO_MUX( ADC_CHANNEL_IN5, 0 ); -#elif defined(STM32F4XX) // TODO: add all pins +#elif defined(STM32F4XX) case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 ); - //case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 ); -#elif defined(STM32F1XX) // TODO: add all pins + case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 ); + case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 ); + case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 ); + case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 ); + case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 ); + case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 ); + case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 ); + case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 ); + case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 ); + case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 ); + case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 ); + case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 ); + case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 ); + case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 ); + case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 ); +# if STM32_ADC_USE_ADC3 + case F3: return TO_MUX( ADC_CHANNEL_IN9, 2 ); + case F4: return TO_MUX( ADC_CHANNEL_IN14, 2 ); + case F5: return TO_MUX( ADC_CHANNEL_IN15, 2 ); + case F6: return TO_MUX( ADC_CHANNEL_IN4, 2 ); + case F7: return TO_MUX( ADC_CHANNEL_IN5, 2 ); + case F8: return TO_MUX( ADC_CHANNEL_IN6, 2 ); + case F9: return TO_MUX( ADC_CHANNEL_IN7, 2 ); + case F10: return TO_MUX( ADC_CHANNEL_IN8, 2 ); +# endif +#elif defined(STM32F1XX) case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 ); + case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 ); + case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 ); + case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 ); + case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 ); + case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 ); + case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 ); + case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 ); + case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 ); + case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 ); + case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 ); + case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 ); + case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 ); + case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 ); + case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 ); + case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 ); + // STM32F103x[C-G] in 144-pin packages also have analog inputs on F6...F10, but they are on ADC3, and the + // ChibiOS ADC driver for STM32F1xx currently supports only ADC1, therefore these pins are not usable. #endif } diff --git a/drivers/chibios/serial_usart.c b/drivers/chibios/serial_usart.c index fb95ec56bd..63ba83a801 100644 --- a/drivers/chibios/serial_usart.c +++ b/drivers/chibios/serial_usart.c @@ -1,13 +1,20 @@ -#include "quantum.h" -#include "serial.h" -#include "print.h" - -#include <ch.h> -#include <hal.h> +/* 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ -#ifndef USART_CR1_M0 -# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so -#endif +#include "serial_usart.h" #ifndef USE_GPIOV1 // The default PAL alternate modes are used to signal that the pins are used for USART @@ -20,50 +27,10 @@ # define SERIAL_USART_DRIVER SD1 #endif -#ifndef SERIAL_USART_CR1 -# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length -#endif - -#ifndef SERIAL_USART_CR2 -# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits -#endif - -#ifndef SERIAL_USART_CR3 -# define SERIAL_USART_CR3 0 -#endif - #ifdef SOFT_SERIAL_PIN # define SERIAL_USART_TX_PIN SOFT_SERIAL_PIN #endif -#ifndef SELECT_SOFT_SERIAL_SPEED -# define SELECT_SOFT_SERIAL_SPEED 1 -#endif - -#ifdef SERIAL_USART_SPEED -// Allow advanced users to directly set SERIAL_USART_SPEED -#elif SELECT_SOFT_SERIAL_SPEED == 0 -# define SERIAL_USART_SPEED 460800 -#elif SELECT_SOFT_SERIAL_SPEED == 1 -# define SERIAL_USART_SPEED 230400 -#elif SELECT_SOFT_SERIAL_SPEED == 2 -# define SERIAL_USART_SPEED 115200 -#elif SELECT_SOFT_SERIAL_SPEED == 3 -# define SERIAL_USART_SPEED 57600 -#elif SELECT_SOFT_SERIAL_SPEED == 4 -# define SERIAL_USART_SPEED 38400 -#elif SELECT_SOFT_SERIAL_SPEED == 5 -# define SERIAL_USART_SPEED 19200 -#else -# error invalid SELECT_SOFT_SERIAL_SPEED value -#endif - -#ifndef SERIAL_USART_TIMEOUT -# define SERIAL_USART_TIMEOUT 100 -#endif - -#define HANDSHAKE_MAGIC 7 - static inline msg_t sdWriteHalfDuplex(SerialDriver* driver, uint8_t* data, uint8_t size) { msg_t ret = sdWrite(driver, data, size); @@ -123,6 +90,10 @@ __attribute__((weak)) void usart_init(void) { #else palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); #endif + +#if defined(USART_REMAP) + USART_REMAP; +#endif } void usart_master_init(void) { diff --git a/drivers/chibios/serial_usart.h b/drivers/chibios/serial_usart.h new file mode 100644 index 0000000000..fee7b4d159 --- /dev/null +++ b/drivers/chibios/serial_usart.h @@ -0,0 +1,90 @@ +/* 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "quantum.h" +#include "serial.h" +#include "printf.h" + +#include <ch.h> +#include <hal.h> + +#ifndef USART_CR1_M0 +# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so +#endif + +#ifndef SERIAL_USART_CR1 +# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length +#endif + +#ifndef SERIAL_USART_CR2 +# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits +#endif + +#ifndef SERIAL_USART_CR3 +# define SERIAL_USART_CR3 0 +#endif + +#if defined(USART1_REMAP) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \ + } while (0) +#elif defined(USART2_REMAP) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \ + } while (0) +#elif defined(USART3_PARTIALREMAP) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \ + } while (0) +#elif defined(USART3_FULLREMAP) +# define USART_REMAP \ + do { \ + (AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \ + } while (0) +#endif + +#ifndef SELECT_SOFT_SERIAL_SPEED +# define SELECT_SOFT_SERIAL_SPEED 1 +#endif + +#ifdef SERIAL_USART_SPEED +// Allow advanced users to directly set SERIAL_USART_SPEED +#elif SELECT_SOFT_SERIAL_SPEED == 0 +# define SERIAL_USART_SPEED 460800 +#elif SELECT_SOFT_SERIAL_SPEED == 1 +# define SERIAL_USART_SPEED 230400 +#elif SELECT_SOFT_SERIAL_SPEED == 2 +# define SERIAL_USART_SPEED 115200 +#elif SELECT_SOFT_SERIAL_SPEED == 3 +# define SERIAL_USART_SPEED 57600 +#elif SELECT_SOFT_SERIAL_SPEED == 4 +# define SERIAL_USART_SPEED 38400 +#elif SELECT_SOFT_SERIAL_SPEED == 5 +# define SERIAL_USART_SPEED 19200 +#else +# error invalid SELECT_SOFT_SERIAL_SPEED value +#endif + +#ifndef SERIAL_USART_TIMEOUT +# define SERIAL_USART_TIMEOUT 100 +#endif + +#define HANDSHAKE_MAGIC 7 diff --git a/drivers/chibios/serial_usart_duplex.c b/drivers/chibios/serial_usart_duplex.c new file mode 100644 index 0000000000..cc9b889ac2 --- /dev/null +++ b/drivers/chibios/serial_usart_duplex.c @@ -0,0 +1,261 @@ +/* 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 3 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 "serial_usart.h" + +#include <stdatomic.h> + +#if !defined(USE_GPIOV1) +// The default PAL alternate modes are used to signal that the pins are used for USART +# if !defined(SERIAL_USART_TX_PAL_MODE) +# define SERIAL_USART_TX_PAL_MODE 7 +# endif +# if !defined(SERIAL_USART_RX_PAL_MODE) +# define SERIAL_USART_RX_PAL_MODE 7 +# endif +#endif + +#if !defined(SERIAL_USART_DRIVER) +# define SERIAL_USART_DRIVER UARTD1 +#endif + +#if !defined(SERIAL_USART_TX_PIN) +# define SERIAL_USART_TX_PIN A9 +#endif + +#if !defined(SERIAL_USART_RX_PIN) +# define SERIAL_USART_RX_PIN A10 +#endif + +#define SIGNAL_HANDSHAKE_RECEIVED 0x1 + +void handle_transactions_slave(uint8_t sstd_index); +static void receive_transaction_handshake(UARTDriver* uartp, uint16_t received_handshake); + +/* + * UART driver configuration structure. We use the blocking DMA enabled API and + * the rxchar callback to receive handshake tokens but only on the slave halve. + */ +// clang-format off +static UARTConfig uart_config = { + .txend1_cb = NULL, + .txend2_cb = NULL, + .rxend_cb = NULL, + .rxchar_cb = NULL, + .rxerr_cb = NULL, + .timeout_cb = NULL, + .speed = (SERIAL_USART_SPEED), + .cr1 = (SERIAL_USART_CR1), + .cr2 = (SERIAL_USART_CR2), + .cr3 = (SERIAL_USART_CR3) +}; +// clang-format on + +static SSTD_t* Transaction_table = NULL; +static uint8_t Transaction_table_size = 0; +static atomic_uint_least8_t handshake = 0xFF; +static thread_reference_t tp_target = NULL; + +/* + * This callback is invoked when a character is received but the application + * was not ready to receive it, the character is passed as parameter. + * Receive transaction table index from initiator, which doubles as basic handshake token. */ +static void receive_transaction_handshake(UARTDriver* uartp, uint16_t received_handshake) { + /* Check if received handshake is not a valid transaction id. + * Please note that we can still catch a seemingly valid handshake + * i.e. a byte from a ongoing transfer which is in the allowed range. + * So this check mainly prevents any obviously wrong handshakes and + * subsequent wakeups of the receiving thread, which is a costly operation. */ + if (received_handshake > Transaction_table_size) { + return; + } + + handshake = (uint8_t)received_handshake; + chSysLockFromISR(); + /* Wakeup receiving thread to start a transaction. */ + chEvtSignalI(tp_target, (eventmask_t)SIGNAL_HANDSHAKE_RECEIVED); + chSysUnlockFromISR(); +} + +__attribute__((weak)) void usart_init(void) { +#if defined(USE_GPIOV1) + palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL); + palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT); +#else + palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); + palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_RX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); +#endif +} + +/* + * This thread runs on the slave half and reacts to transactions initiated from the master. + */ +static THD_WORKING_AREA(waSlaveThread, 1024); +static THD_FUNCTION(SlaveThread, arg) { + (void)arg; + chRegSetThreadName("slave_usart_tx_rx"); + + while (true) { + /* We sleep as long as there is no handshake waiting for us. */ + chEvtWaitAny((eventmask_t)SIGNAL_HANDSHAKE_RECEIVED); + handle_transactions_slave(handshake); + } +} + +void soft_serial_target_init(SSTD_t* const sstd_table, int sstd_table_size) { + Transaction_table = sstd_table; + Transaction_table_size = (uint8_t)sstd_table_size; + usart_init(); + +#if defined(USART_REMAP) + USART_REMAP; +#endif + + tp_target = chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL); + + // Start receiving handshake tokens on slave halve + uart_config.rxchar_cb = receive_transaction_handshake; + uartStart(&SERIAL_USART_DRIVER, &uart_config); +} + +/** + * @brief React to transactions started by the master. + * This version uses duplex send and receive usart pheriphals and DMA backed transfers. + */ +void inline handle_transactions_slave(uint8_t sstd_index) { + size_t buffer_size = 0; + msg_t msg = 0; + SSTD_t* trans = &Transaction_table[sstd_index]; + + /* Send back the handshake which is XORed as a simple checksum, + to signal that the slave is ready to receive possible transaction buffers */ + sstd_index ^= HANDSHAKE_MAGIC; + buffer_size = (size_t)sizeof(sstd_index); + msg = uartSendTimeout(&SERIAL_USART_DRIVER, &buffer_size, &sstd_index, TIME_MS2I(SERIAL_USART_TIMEOUT)); + + if (msg != MSG_OK) { + if (trans->status) { + *trans->status = TRANSACTION_NO_RESPONSE; + } + return; + } + + /* Receive transaction buffer from the master. If this transaction requires it.*/ + buffer_size = (size_t)trans->initiator2target_buffer_size; + if (buffer_size) { + msg = uartReceiveTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->initiator2target_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT)); + if (msg != MSG_OK) { + if (trans->status) { + *trans->status = TRANSACTION_NO_RESPONSE; + } + return; + } + } + + /* Send transaction buffer to the master. If this transaction requires it. */ + buffer_size = (size_t)trans->target2initiator_buffer_size; + if (buffer_size) { + msg = uartSendFullTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->target2initiator_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT)); + if (msg != MSG_OK) { + if (trans->status) { + *trans->status = TRANSACTION_NO_RESPONSE; + } + return; + } + } + + if (trans->status) { + *trans->status = TRANSACTION_ACCEPTED; + } +} + +void soft_serial_initiator_init(SSTD_t* const sstd_table, int sstd_table_size) { + Transaction_table = sstd_table; + Transaction_table_size = (uint8_t)sstd_table_size; + usart_init(); + +#if defined(SERIAL_USART_PIN_SWAP) + uart_config.cr2 |= USART_CR2_SWAP; // master has swapped TX/RX pins +#endif + +#if defined(USART_REMAP) + USART_REMAP; +#endif + + uartStart(&SERIAL_USART_DRIVER, &uart_config); +} + +/** + * @brief Start transaction from the master to the slave. + * This version uses duplex send and receive usart pheriphals and DMA backed transfers. + * + * @param index Transaction Table index of the transaction to start. + * @return int TRANSACTION_NO_RESPONSE in case of Timeout. + * TRANSACTION_TYPE_ERROR in case of invalid transaction index. + * TRANSACTION_END in case of success. + */ +#if !defined(SERIAL_USE_MULTI_TRANSACTION) +int soft_serial_transaction(void) { + uint8_t sstd_index = 0; +#else +int soft_serial_transaction(int index) { + uint8_t sstd_index = index; +#endif + + if (sstd_index > Transaction_table_size) { + return TRANSACTION_TYPE_ERROR; + } + + SSTD_t* const trans = &Transaction_table[sstd_index]; + msg_t msg = 0; + size_t buffer_size = (size_t)sizeof(sstd_index); + + /* Send transaction table index to the slave, which doubles as basic handshake token. */ + uartSendFullTimeout(&SERIAL_USART_DRIVER, &buffer_size, &sstd_index, TIME_MS2I(SERIAL_USART_TIMEOUT)); + + uint8_t sstd_index_shake = 0xFF; + buffer_size = (size_t)sizeof(sstd_index_shake); + + /* Receive the handshake token from the slave. The token was XORed by the slave as a simple checksum. + If the tokens match, the master will start to send and receive possible transaction buffers. */ + msg = uartReceiveTimeout(&SERIAL_USART_DRIVER, &buffer_size, &sstd_index_shake, TIME_MS2I(SERIAL_USART_TIMEOUT)); + if (msg != MSG_OK || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) { + dprintln("USART: Handshake Failed"); + return TRANSACTION_NO_RESPONSE; + } + + /* Send transaction buffer to the slave. If this transaction requires it. */ + buffer_size = (size_t)trans->initiator2target_buffer_size; + if (buffer_size) { + msg = uartSendFullTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->initiator2target_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT)); + if (msg != MSG_OK) { + dprintln("USART: Send Failed"); + return TRANSACTION_NO_RESPONSE; + } + } + + /* Receive transaction buffer from the slave. If this transaction requires it. */ + buffer_size = (size_t)trans->target2initiator_buffer_size; + if (buffer_size) { + msg = uartReceiveTimeout(&SERIAL_USART_DRIVER, &buffer_size, trans->target2initiator_buffer, TIME_MS2I(SERIAL_USART_TIMEOUT)); + if (msg != MSG_OK) { + dprintln("USART: Receive Failed"); + return TRANSACTION_NO_RESPONSE; + } + } + + return TRANSACTION_END; +} diff --git a/drivers/chibios/spi_master.c b/drivers/chibios/spi_master.c index 8341b59a53..4852a6eba4 100644 --- a/drivers/chibios/spi_master.c +++ b/drivers/chibios/spi_master.c @@ -15,7 +15,7 @@ */ #include "spi_master.h" -#include "quantum.h" + #include "timer.h" static pin_t currentSlavePin = NO_PIN; diff --git a/drivers/chibios/spi_master.h b/drivers/chibios/spi_master.h index 5953bef77f..e93580e319 100644 --- a/drivers/chibios/spi_master.h +++ b/drivers/chibios/spi_master.h @@ -18,7 +18,9 @@ #include <ch.h> #include <hal.h> -#include "quantum.h" +#include <stdbool.h> + +#include "gpio.h" #ifndef SPI_DRIVER # define SPI_DRIVER SPID2 diff --git a/drivers/chibios/ws2812_pwm.c b/drivers/chibios/ws2812_pwm.c index 140120d488..e6af55b6b3 100644 --- a/drivers/chibios/ws2812_pwm.c +++ b/drivers/chibios/ws2812_pwm.c @@ -27,6 +27,15 @@ # error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_DMAMUX_ID STM32_DMAMUX1_TIM?_UP" #endif +#ifndef WS2812_PWM_COMPLEMENTARY_OUTPUT +# define WS2812_PWM_OUTPUT_MODE PWM_OUTPUT_ACTIVE_HIGH +#else +# if !STM32_PWM_USE_ADVANCED +# error "WS2812_PWM_COMPLEMENTARY_OUTPUT requires STM32_PWM_USE_ADVANCED == TRUE" +# endif +# define WS2812_PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH +#endif + // Push Pull or Open Drain Configuration // Default Push Pull #ifndef WS2812_EXTERNAL_PULLUP @@ -247,7 +256,7 @@ void ws2812_init(void) { .channels = { [0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled - [WS2812_PWM_CHANNEL - 1] = {.mode = PWM_OUTPUT_ACTIVE_HIGH, .callback = NULL}, // Turn on the channel we care about + [WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL}, // Turn on the channel we care about }, .cr2 = 0, .dier = TIM_DIER_UDE, // DMA on update event for next period diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index 89df2987b5..377a929b94 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -16,22 +16,63 @@ # define WS2812_SPI_MOSI_PAL_MODE 5 #endif +#ifndef WS2812_SPI_SCK_PAL_MODE +# define WS2812_SPI_SCK_PAL_MODE 5 +#endif + // Push Pull or Open Drain Configuration // Default Push Pull #ifndef WS2812_EXTERNAL_PULLUP # if defined(USE_GPIOV1) -# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL +# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL # else -# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL +# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL # endif #else # if defined(USE_GPIOV1) -# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN +# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN # else -# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN +# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN # endif #endif +// Define SPI config speed +// baudrate should target 3.2MHz +// F072 fpclk = 48MHz +// 48/16 = 3Mhz +#if WS2812_SPI_DIVISOR == 2 +# define WS2812_SPI_DIVISOR (0) +#elif WS2812_SPI_DIVISOR == 4 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 8 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1) +#elif WS2812_SPI_DIVISOR == 16 // same as default +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 32 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2) +#elif WS2812_SPI_DIVISOR == 64 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 128 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1) +#elif WS2812_SPI_DIVISOR == 256 +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) +#else +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) // default +#endif + +// Use SPI circular buffer +#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER +# define WS2812_SPI_BUFFER_MODE 1 // circular buffer +#else +# define WS2812_SPI_BUFFER_MODE 0 // normal buffer +#endif + +#if defined(USE_GPIOV1) +# define WS2812_SCK_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL +#else +# define WS2812_SCK_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL +#endif + #define BYTES_FOR_LED_BYTE 4 #define NB_COLORS 3 #define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) @@ -78,17 +119,21 @@ static void set_led_color_rgb(LED_TYPE color, int pos) { } void ws2812_init(void) { - palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE); + palSetLineMode(RGB_DI_PIN, WS2812_MOSI_OUTPUT_MODE); + +#ifdef WS2812_SPI_SCK_PIN + palSetLineMode(WS2812_SPI_SCK_PIN, WS2812_SCK_OUTPUT_MODE); +#endif // WS2812_SPI_SCK_PIN // TODO: more dynamic baudrate - static const SPIConfig spicfg = { - 0, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), - SPI_CR1_BR_1 | SPI_CR1_BR_0 // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz) - }; + static const SPIConfig spicfg = {WS2812_SPI_BUFFER_MODE, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), WS2812_SPI_DIVISOR}; spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */ spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters. */ spiSelect(&WS2812_SPI); /* Slave Select assertion. */ +#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER + spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +#endif } void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { @@ -104,9 +149,11 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { // Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues. // Instead spiSend can be used to send synchronously (or the thread logic can be added back). -#ifdef WS2812_SPI_SYNC +#ifndef WS2812_SPI_USE_CIRCULAR_BUFFER +# ifdef WS2812_SPI_SYNC spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); -#else +# else spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +# endif #endif } diff --git a/drivers/issi/is31fl3733.c b/drivers/issi/is31fl3733.c index dddf0cb734..d99e5339c9 100644 --- a/drivers/issi/is31fl3733.c +++ b/drivers/issi/is31fl3733.c @@ -68,7 +68,7 @@ uint8_t g_twi_transfer_buffer[20]; uint8_t g_pwm_buffer[DRIVER_COUNT][192]; bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false}; -uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}, {0}}; +uint8_t g_led_control_registers[DRIVER_COUNT][24] = {0}; bool g_led_control_registers_update_required[DRIVER_COUNT] = {false}; bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) { diff --git a/drivers/oled/glcdfont.c b/drivers/oled/glcdfont.c index de58960189..0e201d71ee 100644 --- a/drivers/oled/glcdfont.c +++ b/drivers/oled/glcdfont.c @@ -4,7 +4,7 @@ // Online editor: http://teripom.x0.com/ static const unsigned char font[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00, 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x00, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, 0x00, 0x18, 0x3C, 0x18, 0x00, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x00, 0x18, 0x24, 0x18, 0x00, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x00, 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x00, 0x26, 0x29, 0x79, 0x29, 0x26, 0x00, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x00, 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x00, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x00, 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x00, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00, 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x00, 0x66, 0x89, 0x95, 0x6A, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00, 0x08, 0x04, 0x7E, 0x04, 0x08, 0x00, + 0x07, 0x08, 0x7F, 0x08, 0x07, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00, 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x00, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, 0x00, 0x18, 0x3C, 0x18, 0x00, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x00, 0x18, 0x24, 0x18, 0x00, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x00, 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x00, 0x26, 0x29, 0x79, 0x29, 0x26, 0x00, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x00, 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x00, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x00, 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x00, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00, 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x00, 0x66, 0x89, 0x95, 0x6A, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00, 0x08, 0x04, 0x7E, 0x04, 0x08, 0x00, 0x10, 0x20, 0x7E, 0x20, 0x10, 0x00, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x00, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x00, 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x00, 0x30, 0x38, 0x3E, 0x38, 0x30, 0x00, 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x80, 0x70, 0x30, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, 0x72, 0x49, 0x49, 0x49, 0x46, 0x00, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00, 0x41, 0x21, 0x11, 0x09, 0x07, 0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x00, 0x02, 0x01, 0x59, 0x09, 0x06, 0x00, 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x03, 0x07, 0x08, 0x00, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x00, 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00, 0x38, 0x44, 0x44, 0x44, 0x28, 0x00, diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c index 92c64399e2..8e5ed5f070 100644 --- a/drivers/oled/oled_driver.c +++ b/drivers/oled/oled_driver.c @@ -24,6 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "progmem.h" +#include "keyboard.h" + // Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf // for SH1106: https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf @@ -71,6 +73,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define PRE_CHARGE_PERIOD 0xD9 #define VCOM_DETECT 0xDB +// Advance Graphic Commands +#define FADE_BLINK 0x23 +#define ENABLE_FADE 0x20 +#define ENABLE_BLINK 0x30 + // Charge Pump Commands #define CHARGE_PUMP 0x8D @@ -108,7 +115,7 @@ bool oled_initialized = false; bool oled_active = false; bool oled_scrolling = false; uint8_t oled_brightness = OLED_BRIGHTNESS; -uint8_t oled_rotation = 0; +oled_rotation_t oled_rotation = 0; uint8_t oled_rotation_width = 0; uint8_t oled_scroll_speed = 0; // this holds the speed after being remapped to ssd1306 internal values uint8_t oled_scroll_start = 0; @@ -151,7 +158,13 @@ static void InvertCharacter(uint8_t *cursor) { } } -bool oled_init(uint8_t rotation) { +bool oled_init(oled_rotation_t rotation) { +#if defined(USE_I2C) && defined(SPLIT_KEYBOARD) + if (!is_keyboard_master()) { + return true; + } +#endif + oled_rotation = oled_init_user(rotation); if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { oled_rotation_width = OLED_DISPLAY_WIDTH; @@ -478,8 +491,9 @@ void oled_write_raw(const char *data, uint16_t size) { uint16_t cursor_start_index = oled_cursor - &oled_buffer[0]; if ((size + cursor_start_index) > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE - cursor_start_index; for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) { - if (oled_buffer[i] == data[i]) continue; - oled_buffer[i] = data[i]; + uint8_t c = *data++; + if (oled_buffer[i] == c) continue; + oled_buffer[i] = c; oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE)); } } @@ -539,7 +553,13 @@ bool oled_on(void) { oled_timeout = timer_read32() + OLED_TIMEOUT; #endif - static const uint8_t PROGMEM display_on[] = {I2C_CMD, DISPLAY_ON}; + static const uint8_t PROGMEM display_on[] = +#ifdef OLED_FADE_OUT + {I2C_CMD, FADE_BLINK, 0x00}; +#else + {I2C_CMD, DISPLAY_ON}; +#endif + if (!oled_active) { if (I2C_TRANSMIT_P(display_on) != I2C_STATUS_SUCCESS) { print("oled_on cmd failed\n"); @@ -555,7 +575,13 @@ bool oled_off(void) { return !oled_active; } - static const uint8_t PROGMEM display_off[] = {I2C_CMD, DISPLAY_OFF}; + static const uint8_t PROGMEM display_off[] = +#ifdef OLED_FADE_OUT + {I2C_CMD, FADE_BLINK, ENABLE_FADE | OLED_FADE_OUT_INTERVAL}; +#else + {I2C_CMD, DISPLAY_OFF}; +#endif + if (oled_active) { if (I2C_TRANSMIT_P(display_off) != I2C_STATUS_SUCCESS) { print("oled_off cmd failed\n"); diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h index 72ab21247d..a6b85f37e6 100644 --- a/drivers/oled/oled_driver.h +++ b/drivers/oled/oled_driver.h @@ -154,10 +154,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # endif #endif +#if !defined(OLED_FADE_OUT_INTERVAL) +# define OLED_FADE_OUT_INTERVAL 0x00 +#endif + +#if OLED_FADE_OUT_INTERVAL > 0x0F || OLED_FADE_OUT_INTERVAL < 0x00 +# error OLED_FADE_OUT_INTERVAL must be between 0x00 and 0x0F +#endif + #if !defined(OLED_I2C_TIMEOUT) # define OLED_I2C_TIMEOUT 100 #endif +#if !defined(OLED_UPDATE_INTERVAL) && defined(SPLIT_KEYBOARD) +# define OLED_UPDATE_INTERVAL 50 +#endif + typedef struct __attribute__((__packed__)) { uint8_t *current_element; uint16_t remaining_element_count; @@ -214,13 +226,17 @@ void oled_write(const char *data, bool invert); void oled_write_ln(const char *data, bool invert); // Pans the buffer to the right (or left by passing true) by moving contents of the buffer +// Useful for moving the screen in preparation for new drawing void oled_pan(bool left); // Returns a pointer to the requested start index in the buffer plus remaining // buffer length as struct oled_buffer_reader_t oled_read_raw(uint16_t start_index); +// Writes a string to the buffer at current cursor position void oled_write_raw(const char *data, uint16_t size); + +// Writes a single byte into the buffer at the specified index void oled_write_raw_byte(const char data, uint16_t index); // Sets a specific pixel on or off @@ -239,17 +255,11 @@ void oled_write_P(const char *data, bool invert); // Remapped to call 'void oled_write_ln(const char *data, bool invert);' on ARM void oled_write_ln_P(const char *data, bool invert); +// Writes a PROGMEM string to the buffer at current cursor position void oled_write_raw_P(const char *data, uint16_t size); #else -// Writes a string to the buffer at current cursor position -// Advances the cursor while writing, inverts the pixels if true # define oled_write_P(data, invert) oled_write(data, invert) - -// Writes a string to the buffer at current cursor position -// Advances the cursor while writing, inverts the pixels if true -// Advances the cursor to the next page, wiring ' ' to the remainder of the current page # define oled_write_ln_P(data, invert) oled_write(data, invert) - # define oled_write_raw_P(data, size) oled_write_raw(data, size) #endif // defined(__AVR__) diff --git a/keyboards/ergodox_ez/ergodox_ez.c b/keyboards/ergodox_ez/ergodox_ez.c index 315ed98b5e..28a6fc9670 100644 --- a/keyboards/ergodox_ez/ergodox_ez.c +++ b/keyboards/ergodox_ez/ergodox_ez.c @@ -222,7 +222,7 @@ uint8_t ergodox_left_leds_update(void) { #ifdef SWAP_HANDS_ENABLE __attribute__ ((weak)) // swap-hands action needs a matrix to define the swap -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{0,13}, {1,13}, {2,13}, {3,13}, {4,13}, {5,13}}, {{0,12}, {1,12}, {2,12}, {3,12}, {4,12}, {5,12}}, diff --git a/keyboards/moonlander/moonlander.c b/keyboards/moonlander/moonlander.c index efc7de85bb..0746d279c9 100644 --- a/keyboards/moonlander/moonlander.c +++ b/keyboards/moonlander/moonlander.c @@ -386,7 +386,7 @@ bool music_mask_kb(uint16_t keycode) { #ifdef SWAP_HANDS_ENABLE // swap-hands action needs a matrix to define the swap // clang-format off -const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { /* Left hand, matrix positions */ {{6,6}, {5,6}, {4,6}, {3,6}, {2,6}, {1,6},{0,6}}, {{6,7}, {5,7}, {4,7}, {3,7}, {2,7}, {1,7},{0,7}}, diff --git a/keyboards/moonlander/rules.mk b/keyboards/moonlander/rules.mk index ffd415d78d..16822cb504 100644 --- a/keyboards/moonlander/rules.mk +++ b/keyboards/moonlander/rules.mk @@ -2,6 +2,9 @@ MCU = STM32F303 BOARD = QMK_PROTON_C +# Bootloader selection +BOOTLOADER = stm32-dfu + # Build Options # change yes to no to disable # @@ -23,7 +26,6 @@ DEBOUNCE_TYPE = custom SWAP_HANDS_ENABLE = yes RGB_MATRIX_ENABLE = yes RGB_MATRIX_DRIVER = IS31FL3731 -#SERIAL_LINK_ENABLE = yes EEPROM_DRIVER = i2c MOUSE_SHARED_EP = no diff --git a/keyboards/planck/ez/ez.h b/keyboards/planck/ez/ez.h index 144734a885..e3b5077bbb 100644 --- a/keyboards/planck/ez/ez.h +++ b/keyboards/planck/ez/ez.h @@ -55,7 +55,6 @@ { k37, k38, k39, k33, k34, k35 } \ } -#define KEYMAP LAYOUT_ortho_4x12 #define LAYOUT_planck_mit LAYOUT_planck_1x2uC #define LAYOUT_planck_grid LAYOUT_ortho_4x12 diff --git a/keyboards/planck/ez/glow/keymaps/glow/keymap.c b/keyboards/planck/ez/glow/keymaps/glow/keymap.c index 03cc0049e4..2cb68dfe95 100644 --- a/keyboards/planck/ez/glow/keymaps/glow/keymap.c +++ b/keyboards/planck/ez/glow/keymaps/glow/keymap.c @@ -256,7 +256,7 @@ uint16_t muse_counter = 0; uint8_t muse_offset = 70; uint16_t muse_tempo = 50; -void encoder_update(bool clockwise) { +bool encoder_update(bool clockwise) { if (muse_mode) { if (IS_LAYER_ON(_RAISE)) { if (clockwise) { @@ -290,6 +290,7 @@ void encoder_update(bool clockwise) { #endif } } + return true; } void dip_update(uint8_t index, bool active) { diff --git a/keyboards/planck/ez/rules.mk b/keyboards/planck/ez/rules.mk index cf95578b65..23f2aaa313 100755 --- a/keyboards/planck/ez/rules.mk +++ b/keyboards/planck/ez/rules.mk @@ -2,12 +2,15 @@ MCU = STM32F303 BOARD = QMK_PROTON_C +# Bootloader selection +BOOTLOADER = stm32-dfu + # Build Options # change to "no" to disable the options, or define them in the Makefile in # the appropriate keymap folder that will get included automatically # -BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration +BOOTMAGIC_ENABLE = full # Virtual DIP switch configuration MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = no # Console for debug @@ -22,7 +25,6 @@ ENCODER_ENABLE = yes SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend #SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend -# SERIAL_LINK_ENABLE = yes ENCODER_ENABLE = yes RGB_MATRIX_DRIVER = IS31FL3737 diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index 22ff24c92b..304d320b69 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -256,7 +256,7 @@ uint16_t muse_counter = 0; uint8_t muse_offset = 70; uint16_t muse_tempo = 50; -void encoder_update(bool clockwise) { +bool encoder_update(bool clockwise) { if (muse_mode) { if (IS_LAYER_ON(_RAISE)) { if (clockwise) { @@ -286,6 +286,7 @@ void encoder_update(bool clockwise) { #endif } } + return true; } void dip_switch_update_user(uint8_t index, bool active) { diff --git a/keyboards/planck/keymaps/oryx/keymap.c b/keyboards/planck/keymaps/oryx/keymap.c index 79cbf2f6c5..64a77eb3d9 100644 --- a/keyboards/planck/keymaps/oryx/keymap.c +++ b/keyboards/planck/keymaps/oryx/keymap.c @@ -322,7 +322,7 @@ uint16_t muse_counter = 0; uint8_t muse_offset = 70; uint16_t muse_tempo = 50; -void encoder_update(bool clockwise) { +bool encoder_update(bool clockwise) { if (muse_mode) { if (IS_LAYER_ON(_RAISE)) { if (clockwise) { @@ -356,6 +356,7 @@ void encoder_update(bool clockwise) { #endif } } + return true; } void matrix_scan_user(void) { diff --git a/lib/python/qmk/c_parse.py b/lib/python/qmk/c_parse.py index d4f39c8839..991373d569 100644 --- a/lib/python/qmk/c_parse.py +++ b/lib/python/qmk/c_parse.py @@ -8,7 +8,7 @@ from milc import cli from qmk.comment_remover import comment_remover default_key_entry = {'x': -1, 'y': 0, 'w': 1} -single_comment_regex = re.compile(r' */[/*].*$') +single_comment_regex = re.compile(r'\s+/[/*].*$') multi_comment_regex = re.compile(r'/\*(.|\n)*?\*/', re.MULTILINE) diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py index d07790d118..32da1a9b52 100644 --- a/lib/python/qmk/cli/__init__.py +++ b/lib/python/qmk/cli/__init__.py @@ -12,6 +12,56 @@ from subprocess import run from milc import cli, __VERSION__ from milc.questions import yesno +import_names = { + # A mapping of package name to importable name + 'pep8-naming': 'pep8ext_naming', + 'pyusb': 'usb.core', +} + +safe_commands = [ + # A list of subcommands we always run, even when the module imports fail + 'clone', + 'config', + 'env', + 'setup', +] + +subcommands = [ + 'qmk.cli.bux', + 'qmk.cli.c2json', + 'qmk.cli.cformat', + 'qmk.cli.chibios.confmigrate', + 'qmk.cli.clean', + 'qmk.cli.compile', + 'qmk.cli.console', + 'qmk.cli.docs', + 'qmk.cli.doctor', + 'qmk.cli.fileformat', + 'qmk.cli.flash', + 'qmk.cli.format.json', + 'qmk.cli.generate.api', + 'qmk.cli.generate.config_h', + 'qmk.cli.generate.dfu_header', + 'qmk.cli.generate.docs', + 'qmk.cli.generate.info_json', + 'qmk.cli.generate.keyboard_h', + 'qmk.cli.generate.layouts', + 'qmk.cli.generate.rgb_breathe_table', + 'qmk.cli.generate.rules_mk', + 'qmk.cli.hello', + 'qmk.cli.info', + 'qmk.cli.json2c', + 'qmk.cli.lint', + 'qmk.cli.list.keyboards', + 'qmk.cli.list.keymaps', + 'qmk.cli.kle2json', + 'qmk.cli.multibuild', + 'qmk.cli.new.keyboard', + 'qmk.cli.new.keymap', + 'qmk.cli.pyformat', + 'qmk.cli.pytest', +] + def _run_cmd(*command): """Run a command in a subshell. @@ -50,8 +100,8 @@ def _find_broken_requirements(requirements): module_import = module_name.replace('-', '_') # Not every module is importable by its own name. - if module_name == "pep8-naming": - module_import = "pep8ext_naming" + if module_name in import_names: + module_import = import_names[module_name] if not find_spec(module_import): broken_modules.append(module_name) @@ -99,7 +149,7 @@ if sys.version_info[0] != 3 or sys.version_info[1] < 7: milc_version = __VERSION__.split('.') -if int(milc_version[0]) < 2 and int(milc_version[1]) < 3: +if int(milc_version[0]) < 2 and int(milc_version[1]) < 4: requirements = Path('requirements.txt').resolve() print(f'Your MILC library is too old! Please upgrade: python3 -m pip install -U -r {str(requirements)}') @@ -107,54 +157,41 @@ if int(milc_version[0]) < 2 and int(milc_version[1]) < 3: # Check to make sure we have all our dependencies msg_install = 'Please run `python3 -m pip install -r %s` to install required python dependencies.' - -if _broken_module_imports('requirements.txt'): - if yesno('Would you like to install the required Python modules?'): - _run_cmd(sys.executable, '-m', 'pip', 'install', '-r', 'requirements.txt') - else: - print() - print(msg_install % (str(Path('requirements.txt').resolve()),)) - print() - exit(1) - -if cli.config.user.developer: - args = sys.argv[1:] - while args and args[0][0] == '-': - del args[0] - if not args or args[0] != 'config': - if _broken_module_imports('requirements-dev.txt'): - if yesno('Would you like to install the required developer Python modules?'): - _run_cmd(sys.executable, '-m', 'pip', 'install', '-r', 'requirements-dev.txt') - elif yesno('Would you like to disable developer mode?'): - _run_cmd(sys.argv[0], 'config', 'user.developer=None') - else: - print() - print(msg_install % (str(Path('requirements-dev.txt').resolve()),)) - print('You can also turn off developer mode: qmk config user.developer=None') - print() - exit(1) +args = sys.argv[1:] +while args and args[0][0] == '-': + del args[0] + +safe_command = args and args[0] in safe_commands + +if not safe_command: + if _broken_module_imports('requirements.txt'): + if yesno('Would you like to install the required Python modules?'): + _run_cmd(sys.executable, '-m', 'pip', 'install', '-r', 'requirements.txt') + else: + print() + print(msg_install % (str(Path('requirements.txt').resolve()),)) + print() + exit(1) + + if cli.config.user.developer and _broken_module_imports('requirements-dev.txt'): + if yesno('Would you like to install the required developer Python modules?'): + _run_cmd(sys.executable, '-m', 'pip', 'install', '-r', 'requirements-dev.txt') + elif yesno('Would you like to disable developer mode?'): + _run_cmd(sys.argv[0], 'config', 'user.developer=None') + else: + print() + print(msg_install % (str(Path('requirements-dev.txt').resolve()),)) + print('You can also turn off developer mode: qmk config user.developer=None') + print() + exit(1) # Import our subcommands -from . import bux # noqa -from . import c2json # noqa -from . import cformat # noqa -from . import chibios # noqa -from . import clean # noqa -from . import compile # noqa -from milc.subcommand import config # noqa -from . import docs # noqa -from . import doctor # noqa -from . import fileformat # noqa -from . import flash # noqa -from . import format # noqa -from . import generate # noqa -from . import hello # noqa -from . import info # noqa -from . import json2c # noqa -from . import lint # noqa -from . import list # noqa -from . import kle2json # noqa -from . import multibuild # noqa -from . import new # noqa -from . import pyformat # noqa -from . import pytest # noqa +for subcommand in subcommands: + try: + __import__(subcommand) + + except ModuleNotFoundError as e: + if safe_command: + print(f'Warning: Could not import {subcommand}: {e.__class__.__name__}, {e}') + else: + raise diff --git a/lib/python/qmk/cli/chibios/__init__.py b/lib/python/qmk/cli/chibios/__init__.py index 4301837def..e69de29bb2 100644 --- a/lib/python/qmk/cli/chibios/__init__.py +++ b/lib/python/qmk/cli/chibios/__init__.py @@ -1 +0,0 @@ -from . import confmigrate diff --git a/lib/python/qmk/cli/console.py b/lib/python/qmk/cli/console.py new file mode 100644 index 0000000000..45ff0c8bee --- /dev/null +++ b/lib/python/qmk/cli/console.py @@ -0,0 +1,302 @@ +"""Acquire debugging information from usb hid devices + +cli implementation of https://www.pjrc.com/teensy/hid_listen.html +""" +from pathlib import Path +from threading import Thread +from time import sleep, strftime + +import hid +import usb.core + +from milc import cli + +LOG_COLOR = { + 'next': 0, + 'colors': [ + '{fg_blue}', + '{fg_cyan}', + '{fg_green}', + '{fg_magenta}', + '{fg_red}', + '{fg_yellow}', + ], +} + +KNOWN_BOOTLOADERS = { + # VID , PID + ('03EB', '2FEF'): 'atmel-dfu: ATmega16U2', + ('03EB', '2FF0'): 'atmel-dfu: ATmega32U2', + ('03EB', '2FF3'): 'atmel-dfu: ATmega16U4', + ('03EB', '2FF4'): 'atmel-dfu: ATmega32U4', + ('03EB', '2FF9'): 'atmel-dfu: AT90USB64', + ('03EB', '2FFA'): 'atmel-dfu: AT90USB162', + ('03EB', '2FFB'): 'atmel-dfu: AT90USB128', + ('03EB', '6124'): 'Microchip SAM-BA', + ('0483', 'DF11'): 'stm32-dfu: STM32 BOOTLOADER', + ('16C0', '05DC'): 'USBasp: USBaspLoader', + ('16C0', '05DF'): 'bootloadHID: HIDBoot', + ('16C0', '0478'): 'halfkay: Teensy Halfkay', + ('1B4F', '9203'): 'caterina: Pro Micro 3.3V', + ('1B4F', '9205'): 'caterina: Pro Micro 5V', + ('1B4F', '9207'): 'caterina: LilyPadUSB', + ('1C11', 'B007'): 'kiibohd: Kiibohd DFU Bootloader', + ('1EAF', '0003'): 'stm32duino: Maple 003', + ('1FFB', '0101'): 'caterina: Polou A-Star 32U4 Bootloader', + ('2341', '0036'): 'caterina: Arduino Leonardo', + ('2341', '0037'): 'caterina: Arduino Micro', + ('239A', '000C'): 'caterina: Adafruit Feather 32U4', + ('239A', '000D'): 'caterina: Adafruit ItsyBitsy 32U4 3v', + ('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v', + ('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v', + ('2A03', '0036'): 'caterina: Arduino Leonardo', + ('2A03', '0037'): 'caterina: Arduino Micro', + ('314B', '0106'): 'apm32-dfu: APM32 DFU ISP Mode' +} + + +class MonitorDevice(object): + def __init__(self, hid_device, numeric): + self.hid_device = hid_device + self.numeric = numeric + self.device = hid.Device(path=hid_device['path']) + self.current_line = '' + + cli.log.info('Console Connected: %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s%(vendor_id)04X:%(product_id)04X:%(index)d{style_reset_all})', hid_device) + + def read(self, size, encoding='ascii', timeout=1): + """Read size bytes from the device. + """ + return self.device.read(size, timeout).decode(encoding) + + def read_line(self): + """Read from the device's console until we get a \n. + """ + while '\n' not in self.current_line: + self.current_line += self.read(32).replace('\x00', '') + + lines = self.current_line.split('\n', 1) + self.current_line = lines[1] + + return lines[0] + + def run_forever(self): + while True: + try: + message = {**self.hid_device, 'text': self.read_line()} + identifier = (int2hex(message['vendor_id']), int2hex(message['product_id'])) if self.numeric else (message['manufacturer_string'], message['product_string']) + message['identifier'] = ':'.join(identifier) + message['ts'] = '{style_dim}{fg_green}%s{style_reset_all} ' % (strftime(cli.config.general.datetime_fmt),) if cli.args.timestamp else '' + + cli.echo('%(ts)s%(color)s%(identifier)s:%(index)d{style_reset_all}: %(text)s' % message) + + except hid.HIDException: + break + + +class FindDevices(object): + def __init__(self, vid, pid, index, numeric): + self.vid = vid + self.pid = pid + self.index = index + self.numeric = numeric + + def run_forever(self): + """Process messages from our queue in a loop. + """ + live_devices = {} + live_bootloaders = {} + + while True: + try: + for device in list(live_devices): + if not live_devices[device]['thread'].is_alive(): + cli.log.info('Console Disconnected: %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s%(vendor_id)04X:%(product_id)04X:%(index)d{style_reset_all})', live_devices[device]) + del live_devices[device] + + for device in self.find_devices(): + if device['path'] not in live_devices: + device['color'] = LOG_COLOR['colors'][LOG_COLOR['next']] + LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors']) + live_devices[device['path']] = device + + try: + monitor = MonitorDevice(device, self.numeric) + device['thread'] = Thread(target=monitor.run_forever, daemon=True) + + device['thread'].start() + except Exception as e: + device['e'] = e + device['e_name'] = e.__class__.__name__ + cli.log.error("Could not connect to %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s:%(vendor_id)04X:%(product_id)04X:%(index)d): %(e_name)s: %(e)s", device) + if cli.config.general.verbose: + cli.log.exception(e) + del live_devices[device['path']] + + if cli.args.bootloaders: + for device in self.find_bootloaders(): + if device.address in live_bootloaders: + live_bootloaders[device.address]._qmk_found = True + else: + name = KNOWN_BOOTLOADERS[(int2hex(device.idVendor), int2hex(device.idProduct))] + cli.log.info('Bootloader Connected: {style_bright}{fg_magenta}%s', name) + device._qmk_found = True + live_bootloaders[device.address] = device + + for device in list(live_bootloaders): + if live_bootloaders[device]._qmk_found: + live_bootloaders[device]._qmk_found = False + else: + name = KNOWN_BOOTLOADERS[(int2hex(live_bootloaders[device].idVendor), int2hex(live_bootloaders[device].idProduct))] + cli.log.info('Bootloader Disconnected: {style_bright}{fg_magenta}%s', name) + del live_bootloaders[device] + + sleep(.1) + + except KeyboardInterrupt: + break + + def is_bootloader(self, hid_device): + """Returns true if the device in question matches a known bootloader vid/pid. + """ + return (int2hex(hid_device.idVendor), int2hex(hid_device.idProduct)) in KNOWN_BOOTLOADERS + + def is_console_hid(self, hid_device): + """Returns true when the usage page indicates it's a teensy-style console. + """ + return hid_device['usage_page'] == 0xFF31 and hid_device['usage'] == 0x0074 + + def is_filtered_device(self, hid_device): + """Returns True if the device should be included in the list of available consoles. + """ + return int2hex(hid_device['vendor_id']) == self.vid and int2hex(hid_device['product_id']) == self.pid + + def find_devices_by_report(self, hid_devices): + """Returns a list of available teensy-style consoles by doing a brute-force search. + + Some versions of linux don't report usage and usage_page. In that case we fallback to reading the report (possibly inaccurately) ourselves. + """ + devices = [] + + for device in hid_devices: + path = device['path'].decode('utf-8') + + if path.startswith('/dev/hidraw'): + number = path[11:] + report = Path(f'/sys/class/hidraw/hidraw{number}/device/report_descriptor') + + if report.exists(): + rp = report.read_bytes() + + if rp[1] == 0x31 and rp[3] == 0x09: + devices.append(device) + + return devices + + def find_bootloaders(self): + """Returns a list of available bootloader devices. + """ + return list(filter(self.is_bootloader, usb.core.find(find_all=True))) + + def find_devices(self): + """Returns a list of available teensy-style consoles. + """ + hid_devices = hid.enumerate() + devices = list(filter(self.is_console_hid, hid_devices)) + + if not devices: + devices = self.find_devices_by_report(hid_devices) + + if self.vid and self.pid: + devices = list(filter(self.is_filtered_device, devices)) + + # Add index numbers + device_index = {} + for device in devices: + id = ':'.join((int2hex(device['vendor_id']), int2hex(device['product_id']))) + + if id not in device_index: + device_index[id] = 0 + + device_index[id] += 1 + device['index'] = device_index[id] + + return devices + + +def int2hex(number): + """Returns a string representation of the number as hex. + """ + return "%04X" % number + + +def list_devices(device_finder): + """Show the user a nicely formatted list of devices. + """ + devices = device_finder.find_devices() + + if devices: + cli.log.info('Available devices:') + for dev in devices: + color = LOG_COLOR['colors'][LOG_COLOR['next']] + LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors']) + cli.log.info("\t%s%s:%s:%d{style_reset_all}\t%s %s", color, int2hex(dev['vendor_id']), int2hex(dev['product_id']), dev['index'], dev['manufacturer_string'], dev['product_string']) + + if cli.args.bootloaders: + bootloaders = device_finder.find_bootloaders() + + if bootloaders: + cli.log.info('Available Bootloaders:') + + for dev in bootloaders: + cli.log.info("\t%s:%s\t%s", int2hex(dev.idVendor), int2hex(dev.idProduct), KNOWN_BOOTLOADERS[(int2hex(dev.idVendor), int2hex(dev.idProduct))]) + + +@cli.argument('--bootloaders', arg_only=True, default=True, action='store_boolean', help='displaying bootloaders.') +@cli.argument('-d', '--device', help='Device to select - uses format <pid>:<vid>[:<index>].') +@cli.argument('-l', '--list', arg_only=True, action='store_true', help='List available hid_listen devices.') +@cli.argument('-n', '--numeric', arg_only=True, action='store_true', help='Show VID/PID instead of names.') +@cli.argument('-t', '--timestamp', arg_only=True, action='store_true', help='Print the timestamp for received messages as well.') +@cli.argument('-w', '--wait', type=int, default=1, help="How many seconds to wait between checks (Default: 1)") +@cli.subcommand('Acquire debugging information from usb hid devices.', hidden=False if cli.config.user.developer else True) +def console(cli): + """Acquire debugging information from usb hid devices + """ + vid = None + pid = None + index = 1 + + if cli.config.console.device: + device = cli.config.console.device.split(':') + + if len(device) == 2: + vid, pid = device + + elif len(device) == 3: + vid, pid, index = device + + if not index.isdigit(): + cli.log.error('Device index must be a number! Got "%s" instead.', index) + exit(1) + + index = int(index) + + if index < 1: + cli.log.error('Device index must be greater than 0! Got %s', index) + exit(1) + + else: + cli.log.error('Invalid format for device, expected "<pid>:<vid>[:<index>]" but got "%s".', cli.config.console.device) + cli.print_help() + exit(1) + + vid = vid.upper() + pid = pid.upper() + + device_finder = FindDevices(vid, pid, index, cli.args.numeric) + + if cli.args.list: + return list_devices(device_finder) + + print('Looking for devices...', flush=True) + device_finder.run_forever() diff --git a/lib/python/qmk/cli/format/__init__.py b/lib/python/qmk/cli/format/__init__.py index 741ec778b1..e69de29bb2 100644 --- a/lib/python/qmk/cli/format/__init__.py +++ b/lib/python/qmk/cli/format/__init__.py @@ -1 +0,0 @@ -from . import json diff --git a/lib/python/qmk/cli/generate/__init__.py b/lib/python/qmk/cli/generate/__init__.py index 0efca0022d..e69de29bb2 100644 --- a/lib/python/qmk/cli/generate/__init__.py +++ b/lib/python/qmk/cli/generate/__init__.py @@ -1,9 +0,0 @@ -from . import api -from . import config_h -from . import dfu_header -from . import docs -from . import info_json -from . import keyboard_h -from . import layouts -from . import rgb_breathe_table -from . import rules_mk diff --git a/lib/python/qmk/cli/generate/layouts.py b/lib/python/qmk/cli/generate/layouts.py index ad6946d6cf..4de982f822 100755 --- a/lib/python/qmk/cli/generate/layouts.py +++ b/lib/python/qmk/cli/generate/layouts.py @@ -85,7 +85,9 @@ def generate_layouts(cli): for alias, target in kb_info_json.get('layout_aliases', {}).items(): layouts_h_lines.append('') - layouts_h_lines.append('#define %s %s' % (alias, target)) + layouts_h_lines.append(f'#ifndef {alias}') + layouts_h_lines.append(f'# define {alias} {target}') + layouts_h_lines.append('#endif') # Show the results layouts_h = '\n'.join(layouts_h_lines) + '\n' diff --git a/lib/python/qmk/cli/list/__init__.py b/lib/python/qmk/cli/list/__init__.py index d83cd20b5b..e69de29bb2 100644 --- a/lib/python/qmk/cli/list/__init__.py +++ b/lib/python/qmk/cli/list/__init__.py @@ -1,2 +0,0 @@ -from . import keyboards -from . import keymaps diff --git a/lib/python/qmk/cli/multibuild.py b/lib/python/qmk/cli/multibuild.py index 46594c0997..bdb0b493c8 100755 --- a/lib/python/qmk/cli/multibuild.py +++ b/lib/python/qmk/cli/multibuild.py @@ -2,6 +2,7 @@ This will compile everything in parallel, for testing purposes. """ +import os import re from pathlib import Path from subprocess import DEVNULL @@ -11,6 +12,7 @@ from milc import cli from qmk.constants import QMK_FIRMWARE from qmk.commands import _find_make import qmk.keyboard +import qmk.keymap def _make_rules_mk_filter(key, value): @@ -29,6 +31,7 @@ def _is_split(keyboard_name): @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs to run.") @cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.") @cli.argument('-f', '--filter', arg_only=True, action='append', default=[], help="Filter the list of keyboards based on the supplied value in rules.mk. Supported format is 'SPLIT_KEYBOARD=yes'. May be passed multiple times.") +@cli.argument('-km', '--keymap', type=str, default='default', help="The keymap name to build. Default is 'default'.") @cli.subcommand('Compile QMK Firmware for all keyboards.', hidden=False if cli.config.user.developer else True) def multibuild(cli): """Compile QMK Firmware against all keyboards. @@ -57,23 +60,29 @@ def multibuild(cli): builddir.mkdir(parents=True, exist_ok=True) with open(makefile, "w") as f: for keyboard_name in keyboard_list: - keyboard_safe = keyboard_name.replace('/', '_') - # yapf: disable - f.write( - f"""\ + if qmk.keymap.locate_keymap(keyboard_name, cli.args.keymap) is not None: + keyboard_safe = keyboard_name.replace('/', '_') + # yapf: disable + f.write( + f"""\ all: {keyboard_safe}_binary {keyboard_safe}_binary: @rm -f "{QMK_FIRMWARE}/.build/failed.log.{keyboard_safe}" || true - +@$(MAKE) -C "{QMK_FIRMWARE}" -f "{QMK_FIRMWARE}/build_keyboard.mk" KEYBOARD="{keyboard_name}" KEYMAP="default" REQUIRE_PLATFORM_KEY= COLOR=true SILENT=false \\ - >>"{QMK_FIRMWARE}/.build/build.log.{keyboard_safe}" 2>&1 \\ - || cp "{QMK_FIRMWARE}/.build/build.log.{keyboard_safe}" "{QMK_FIRMWARE}/.build/failed.log.{keyboard_safe}" - @{{ grep '\[ERRORS\]' "{QMK_FIRMWARE}/.build/build.log.{keyboard_safe}" >/dev/null 2>&1 && printf "Build %-64s \e[1;31m[ERRORS]\e[0m\\n" "{keyboard_name}:default" ; }} \\ - || {{ grep '\[WARNINGS\]' "{QMK_FIRMWARE}/.build/build.log.{keyboard_safe}" >/dev/null 2>&1 && printf "Build %-64s \e[1;33m[WARNINGS]\e[0m\\n" "{keyboard_name}:default" ; }} \\ - || printf "Build %-64s \e[1;32m[OK]\e[0m\\n" "{keyboard_name}:default" - @rm -f "{QMK_FIRMWARE}/.build/build.log.{keyboard_safe}" || true + +@$(MAKE) -C "{QMK_FIRMWARE}" -f "{QMK_FIRMWARE}/build_keyboard.mk" KEYBOARD="{keyboard_name}" KEYMAP="{cli.args.keymap}" REQUIRE_PLATFORM_KEY= COLOR=true SILENT=false \\ + >>"{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}" 2>&1 \\ + || cp "{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}" "{QMK_FIRMWARE}/.build/failed.log.{os.getpid()}.{keyboard_safe}" + @{{ grep '\[ERRORS\]' "{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}" >/dev/null 2>&1 && printf "Build %-64s \e[1;31m[ERRORS]\e[0m\\n" "{keyboard_name}:{cli.args.keymap}" ; }} \\ + || {{ grep '\[WARNINGS\]' "{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}" >/dev/null 2>&1 && printf "Build %-64s \e[1;33m[WARNINGS]\e[0m\\n" "{keyboard_name}:{cli.args.keymap}" ; }} \\ + || printf "Build %-64s \e[1;32m[OK]\e[0m\\n" "{keyboard_name}:{cli.args.keymap}" + @rm -f "{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}" || true """# noqa - ) - # yapf: enable + ) + # yapf: enable - cli.run([make_cmd, '-j', str(cli.args.parallel), '-f', makefile, 'all'], capture_output=False, stdin=DEVNULL) + cli.run([make_cmd, '-j', str(cli.args.parallel), '-f', makefile.as_posix(), 'all'], capture_output=False, stdin=DEVNULL) + + # Check for failures + failures = [f for f in builddir.glob(f'failed.log.{os.getpid()}.*')] + if len(failures) > 0: + return False diff --git a/lib/python/qmk/cli/new/__init__.py b/lib/python/qmk/cli/new/__init__.py index fe5d6fe483..e69de29bb2 100644 --- a/lib/python/qmk/cli/new/__init__.py +++ b/lib/python/qmk/cli/new/__init__.py @@ -1,2 +0,0 @@ -from . import keyboard -from . import keymap diff --git a/lib/python/qmk/commands.py b/lib/python/qmk/commands.py index ee049e8af7..3a35c11031 100644 --- a/lib/python/qmk/commands.py +++ b/lib/python/qmk/commands.py @@ -201,6 +201,7 @@ def compile_configurator_json(user_keymap, bootloader=None, parallel=1, **env_va f'VERBOSE={verbose}', f'COLOR={color}', 'SILENT=false', + f'QMK_BIN={"bin/qmk" if "DEPRECATED_BIN_QMK" in os.environ else "qmk"}', ]) return make_command diff --git a/lib/python/qmk/constants.py b/lib/python/qmk/constants.py index 3ed69f3bf9..49e5e0eb42 100644 --- a/lib/python/qmk/constants.py +++ b/lib/python/qmk/constants.py @@ -10,7 +10,7 @@ QMK_FIRMWARE = Path.cwd() MAX_KEYBOARD_SUBFOLDERS = 5 # Supported processor types -CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F411', 'STM32G431', 'STM32G474' +CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66F18', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32L433', 'STM32L443' LUFA_PROCESSORS = 'at90usb162', 'atmega16u2', 'atmega32u2', 'atmega16u4', 'atmega32u4', 'at90usb646', 'at90usb647', 'at90usb1286', 'at90usb1287', None VUSB_PROCESSORS = 'atmega32a', 'atmega328p', 'atmega328', 'attiny85' diff --git a/lib/python/qmk/decorators.py b/lib/python/qmk/decorators.py index 8d43ae980f..f6270990b9 100644 --- a/lib/python/qmk/decorators.py +++ b/lib/python/qmk/decorators.py @@ -17,12 +17,12 @@ def automagic_keyboard(func): @functools.wraps(func) def wrapper(*args, **kwargs): # Ensure that `--keyboard` was not passed and CWD is under `qmk_firmware/keyboards` - if cli.config_source[cli._entrypoint.__name__]['keyboard'] != 'argument': + if cli.config_source[cli._subcommand.__name__]['keyboard'] != 'argument': keyboard = find_keyboard_from_dir() if keyboard: - cli.config[cli._entrypoint.__name__]['keyboard'] = keyboard - cli.config_source[cli._entrypoint.__name__]['keyboard'] = 'keyboard_directory' + cli.config[cli._subcommand.__name__]['keyboard'] = keyboard + cli.config_source[cli._subcommand.__name__]['keyboard'] = 'keyboard_directory' return func(*args, **kwargs) @@ -37,12 +37,12 @@ def automagic_keymap(func): @functools.wraps(func) def wrapper(*args, **kwargs): # Ensure that `--keymap` was not passed and that we're under `qmk_firmware` - if cli.config_source[cli._entrypoint.__name__]['keymap'] != 'argument': + if cli.config_source[cli._subcommand.__name__]['keymap'] != 'argument': keymap_name, keymap_type = find_keymap_from_dir() if keymap_name: - cli.config[cli._entrypoint.__name__]['keymap'] = keymap_name - cli.config_source[cli._entrypoint.__name__]['keymap'] = keymap_type + cli.config[cli._subcommand.__name__]['keymap'] = keymap_name + cli.config_source[cli._subcommand.__name__]['keymap'] = keymap_type return func(*args, **kwargs) diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py index a7b70a7d99..afdbc81429 100644 --- a/lib/python/qmk/tests/test_cli_commands.py +++ b/lib/python/qmk/tests/test_cli_commands.py @@ -7,7 +7,7 @@ is_windows = 'windows' in platform.platform().lower() def check_subcommand(command, *args): - cmd = ['bin/qmk', command, *args] + cmd = ['qmk', command, *args] result = cli.run(cmd, stdin=DEVNULL, combined_output=True) return result @@ -16,7 +16,7 @@ def check_subcommand_stdin(file_to_read, command, *args): """Pipe content of a file to a command and return output. """ with open(file_to_read, encoding='utf-8') as my_file: - cmd = ['bin/qmk', command, *args] + cmd = ['qmk', command, *args] result = cli.run(cmd, stdin=my_file, combined_output=True) return result diff --git a/message.mk b/message.mk index 3240c041b9..da5f9fb9e3 100644 --- a/message.mk +++ b/message.mk @@ -47,10 +47,12 @@ MSG_SIZE_AFTER = Size after: MSG_COFF = Converting to AVR COFF: MSG_EXTENDED_COFF = Converting to AVR Extended COFF: MSG_FLASH = Creating load file for flashing: +MSG_UF2 = Creating UF2 file for deployment: MSG_EEPROM = Creating load file for EEPROM: MSG_BIN = Creating binary load file for flashing: MSG_EXTENDED_LISTING = Creating Extended Listing: MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_EXECUTING = Executing: MSG_LINKING = Linking: MSG_COMPILING = Compiling: MSG_COMPILING_CXX = Compiling: @@ -86,8 +88,10 @@ MSG_FILE_TOO_BIG = $(ERROR_COLOR)The firmware is too large!$(NO_COLOR) $(CURRENT MSG_FILE_TOO_SMALL = The firmware is too small! $(CURRENT_SIZE)/$(MAX_SIZE)\n MSG_FILE_JUST_RIGHT = The firmware size is fine - $(CURRENT_SIZE)/$(MAX_SIZE) ($(PERCENT_SIZE)%%, $(FREE_SIZE) bytes free)\n MSG_FILE_NEAR_LIMIT = The firmware size is approaching the maximum - $(CURRENT_SIZE)/$(MAX_SIZE) ($(PERCENT_SIZE)%%, $(FREE_SIZE) bytes free)\n -MSG_PYTHON_MISSING = $(ERROR_COLOR)ERROR:$(NO_COLOR) Can not run bin/qmk!\n\n\ +MSG_PYTHON_MISSING = $(ERROR_COLOR)ERROR:$(NO_COLOR) Can not run \"qmk\" command!\n\n\ Please run $(BOLD)util/qmk_install.sh$(NO_COLOR) to install all the dependencies QMK requires.\n\n MSG_FLASH_BOOTLOADER = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's bootloader is not specified or is not supported by the \":flash\" target at this time.\n\n MSG_FLASH_ARCH = $(WARN_COLOR)WARNING:$(NO_COLOR) This board's architecture is not supported by the \":flash\" target at this time.\n\n MSG_BOOTLOADER_NOT_FOUND = $(ERROR_COLOR)ERROR:$(NO_COLOR) Bootloader not found. Trying again in 5s.\n +BOOTLOADER_RETRY_TIME ?= 0.5 +MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY = Bootloader not found. Trying again every $(BOOTLOADER_RETRY_TIME)s diff --git a/nix/poetry.lock b/nix/poetry.lock index 74d6e7dd58..1a1aefe21a 100644 --- a/nix/poetry.lock +++ b/nix/poetry.lock @@ -8,7 +8,7 @@ python-versions = "*" [[package]] name = "argcomplete" -version = "1.12.2" +version = "1.12.3" description = "Bash tab completion for argparse" category = "main" optional = false @@ -19,17 +19,17 @@ test = ["coverage", "flake8", "pexpect", "wheel"] [[package]] name = "attrs" -version = "20.3.0" +version = "21.2.0" description = "Classes Without Boilerplate" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "furo", "sphinx", "pre-commit"] -docs = ["furo", "sphinx", "zope.interface"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] [[package]] name = "colorama" @@ -43,7 +43,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" name = "coverage" version = "5.5" description = "Code coverage measurement for Python" -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" @@ -63,9 +63,9 @@ setuptools_scm = "*" [[package]] name = "flake8" -version = "3.9.0" +version = "3.9.2" description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" @@ -86,6 +86,32 @@ python-versions = "*" flake8 = "*" [[package]] +name = "halo" +version = "0.0.31" +description = "Beautiful terminal spinners in Python" +category = "main" +optional = false +python-versions = ">=3.4" + +[package.dependencies] +colorama = ">=0.3.9" +log-symbols = ">=0.0.14" +six = ">=1.12.0" +spinners = ">=0.0.24" +termcolor = ">=1.1.0" + +[package.extras] +ipython = ["IPython (==5.7.0)", "ipywidgets (==7.1.0)"] + +[[package]] +name = "hid" +version = "1.0.4" +description = "ctypes bindings for hidapi" +category = "main" +optional = false +python-versions = "*" + +[[package]] name = "hjson" version = "3.0.2" description = "Hjson, a user interface for JSON." @@ -111,16 +137,27 @@ format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] [[package]] +name = "log-symbols" +version = "0.0.14" +description = "Colored symbols for various log levels for Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +colorama = ">=0.3.9" + +[[package]] name = "mccabe" version = "0.6.1" description = "McCabe checker, plugin for flake8" -category = "dev" +category = "main" optional = false python-versions = "*" [[package]] name = "milc" -version = "1.3.0" +version = "1.4.2" description = "Opinionated Batteries-Included Python 3 CLI Framework." category = "main" optional = false @@ -130,12 +167,14 @@ python-versions = "*" appdirs = "*" argcomplete = "*" colorama = "*" +halo = "*" +spinners = "*" [[package]] name = "nose2" version = "0.10.0" description = "unittest2 with plugins, the succesor to nose" -category = "dev" +category = "main" optional = false python-versions = "*" @@ -162,7 +201,7 @@ flake8-polyfill = ">=1.0.2,<2" name = "pycodestyle" version = "2.7.0" description = "Python style guide checker" -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" @@ -170,13 +209,13 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" name = "pyflakes" version = "2.3.1" description = "passive checker of Python programs" -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pygments" -version = "2.8.1" +version = "2.9.0" description = "Pygments is a syntax highlighting package written in Python." category = "main" optional = false @@ -191,6 +230,34 @@ optional = false python-versions = ">=3.5" [[package]] +name = "pyusb" +version = "1.1.1" +description = "Python USB access module" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "qmk" +version = "0.0.51" +description = "A program to help users work with QMK Firmware." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +dotty-dict = "*" +flake8 = "*" +hid = "*" +hjson = "*" +jsonschema = ">=3" +milc = ">=1.4.0" +nose2 = "*" +pygments = "*" +pyusb = "*" +yapf = "*" + +[[package]] name = "setuptools-scm" version = "6.0.1" description = "the blessed package to manage your versions by scm tags" @@ -203,17 +270,25 @@ toml = ["toml"] [[package]] name = "six" -version = "1.15.0" +version = "1.16.0" description = "Python 2 and 3 compatibility utilities" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] -name = "wave" -version = "0.0.2" -description = "Whole Architecture Verification" -category = "dev" +name = "spinners" +version = "0.0.24" +description = "Spinners for terminals" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "termcolor" +version = "1.1.0" +description = "ANSII Color formatting for output in terminal." +category = "main" optional = false python-versions = "*" @@ -221,14 +296,14 @@ python-versions = "*" name = "yapf" version = "0.30.0" description = "A formatter for Python code." -category = "dev" +category = "main" optional = false python-versions = "*" [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "6adb87c61d9eacf55e4e80bc6c73325e4e4854a792e3881ff448b6ee1cb75091" +content-hash = "5e181d51536240d08c74ba6a46bd0988ee4ca72ac3d5b388965ca8023e9b9a99" [metadata.files] appdirs = [ @@ -236,12 +311,12 @@ appdirs = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] argcomplete = [ - {file = "argcomplete-1.12.2-py2.py3-none-any.whl", hash = "sha256:17f01a9b9b9ece3e6b07058eae737ad6e10de8b4e149105f84614783913aba71"}, - {file = "argcomplete-1.12.2.tar.gz", hash = "sha256:de0e1282330940d52ea92a80fea2e4b9e0da1932aaa570f84d268939d1897b04"}, + {file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81"}, + {file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445"}, ] attrs = [ - {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, - {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, + {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, + {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -305,13 +380,21 @@ dotty-dict = [ {file = "dotty_dict-1.3.0.tar.gz", hash = "sha256:eb0035a3629ecd84397a68f1f42f1e94abd1c34577a19cd3eacad331ee7cbaf0"}, ] flake8 = [ - {file = "flake8-3.9.0-py2.py3-none-any.whl", hash = "sha256:12d05ab02614b6aee8df7c36b97d1a3b2372761222b19b58621355e82acddcff"}, - {file = "flake8-3.9.0.tar.gz", hash = "sha256:78873e372b12b093da7b5e5ed302e8ad9e988b38b063b61ad937f26ca58fc5f0"}, + {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, + {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, ] flake8-polyfill = [ {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, ] +halo = [ + {file = "halo-0.0.31-py2-none-any.whl", hash = "sha256:5350488fb7d2aa7c31a1344120cee67a872901ce8858f60da7946cef96c208ab"}, + {file = "halo-0.0.31.tar.gz", hash = "sha256:7b67a3521ee91d53b7152d4ee3452811e1d2a6321975137762eb3d70063cc9d6"}, +] +hid = [ + {file = "hid-1.0.4-py2-none-any.whl", hash = "sha256:fba9913f07030b01059b822b24c83b370ca3f444e9e6443bd662f9f1aa3f0780"}, + {file = "hid-1.0.4.tar.gz", hash = "sha256:f61b0382f37a334bc8ba8604bc84b94875ee4f594fbbaf82b2c3b3e827883fc1"}, +] hjson = [ {file = "hjson-3.0.2-py3-none-any.whl", hash = "sha256:5546438bf4e1b52bc964c6a47c4ed10fa5fba8a1b264e22efa893e333baad2db"}, {file = "hjson-3.0.2.tar.gz", hash = "sha256:2838fd7200e5839ea4516ece953f3a19892c41089f0d933ba3f68e596aacfcd5"}, @@ -320,13 +403,17 @@ jsonschema = [ {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, ] +log-symbols = [ + {file = "log_symbols-0.0.14-py3-none-any.whl", hash = "sha256:4952106ff8b605ab7d5081dd2c7e6ca7374584eff7086f499c06edd1ce56dcca"}, + {file = "log_symbols-0.0.14.tar.gz", hash = "sha256:cf0bbc6fe1a8e53f0d174a716bc625c4f87043cc21eb55dd8a740cfe22680556"}, +] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] milc = [ - {file = "milc-1.3.0-py2.py3-none-any.whl", hash = "sha256:a4dd8ce77f1d4ac5e08311eecc6954c349d4032d7ed4e0335822e09740514f22"}, - {file = "milc-1.3.0.tar.gz", hash = "sha256:a9d0299aaaef7a3f00010589c3c0d0669798467e397580620a68e9290b36cdda"}, + {file = "milc-1.4.2-py2.py3-none-any.whl", hash = "sha256:65ee004caa769b1ee144b15be7908d1f623920ab6f356e5c5c95be9457aa15d8"}, + {file = "milc-1.4.2.tar.gz", hash = "sha256:c6b2f19e3196b00a0060f8c883533e356f2054a9f81692b7b97ccee0d01626fd"}, ] nose2 = [ {file = "nose2-0.10.0-py2.py3-none-any.whl", hash = "sha256:aa620e759f2c5018d9ba041340391913e282ecebd3c392027f1575847b093ec6"}, @@ -345,23 +432,34 @@ pyflakes = [ {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, ] pygments = [ - {file = "Pygments-2.8.1-py3-none-any.whl", hash = "sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8"}, - {file = "Pygments-2.8.1.tar.gz", hash = "sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94"}, + {file = "Pygments-2.9.0-py3-none-any.whl", hash = "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"}, + {file = "Pygments-2.9.0.tar.gz", hash = "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f"}, ] pyrsistent = [ {file = "pyrsistent-0.17.3.tar.gz", hash = "sha256:2e636185d9eb976a18a8a8e96efce62f2905fea90041958d8cc2a189756ebf3e"}, ] +pyusb = [ + {file = "pyusb-1.1.1-py3-none-any.whl", hash = "sha256:f18eb813d3a1439918071234589162c2f209a19adbeffeb1377ce078a4aebc70"}, + {file = "pyusb-1.1.1.tar.gz", hash = "sha256:7d449ad916ce58aff60b89aae0b65ac130f289c24d6a5b7b317742eccffafc38"}, +] +qmk = [ + {file = "qmk-0.0.51-py2.py3-none-any.whl", hash = "sha256:5f676f389b2450b0956d7eb8e7e378d2e6690d5859a887c91876da0a5faf75ed"}, + {file = "qmk-0.0.51.tar.gz", hash = "sha256:efeef209cde1df92b9823db686d9684962cd00aae9f45ba5e3d494aa5b3c6b9a"}, +] setuptools-scm = [ {file = "setuptools_scm-6.0.1-py3-none-any.whl", hash = "sha256:c3bd5f701c8def44a5c0bfe8d407bef3f80342217ef3492b951f3777bd2d915c"}, {file = "setuptools_scm-6.0.1.tar.gz", hash = "sha256:d1925a69cb07e9b29416a275b9fadb009a23c148ace905b2fb220649a6c18e92"}, ] six = [ - {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, - {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +spinners = [ + {file = "spinners-0.0.24-py3-none-any.whl", hash = "sha256:2fa30d0b72c9650ad12bbe031c9943b8d441e41b4f5602b0ec977a19f3290e98"}, + {file = "spinners-0.0.24.tar.gz", hash = "sha256:1eb6aeb4781d72ab42ed8a01dcf20f3002bf50740d7154d12fb8c9769bf9e27f"}, ] -wave = [ - {file = "Wave-0.0.2.tar.gz", hash = "sha256:5a895bb85e04e38c82dba90d66a5ae8f488b50c58f3fc4df868a5bcdcabb8632"}, - {file = "Wave-0.0.2.zip", hash = "sha256:5187f49497287d218cc83d4cd1e5299dc31485ab3ed32abbaa9e95d8f73c4095"}, +termcolor = [ + {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"}, ] yapf = [ {file = "yapf-0.30.0-py2.py3-none-any.whl", hash = "sha256:3abf61ba67cf603069710d30acbc88cfe565d907e16ad81429ae90ce9651e0c9"}, diff --git a/nix/pyproject.toml b/nix/pyproject.toml index 62d49fad59..a813361893 100644 --- a/nix/pyproject.toml +++ b/nix/pyproject.toml @@ -2,7 +2,7 @@ # It is particularly required by the Nix environment (see shell.nix). To update versions, # normally one would run "poetry update --lock" [tool.poetry] -name = "qmk" +name = "qmk_firmware" version = "0.1.0" description = "" authors = [] @@ -12,18 +12,20 @@ python = "^3.8" appdirs = "^1.4.4" argcomplete = "^1.12.2" colorama = "^0.4.4" -hjson = "^3.0.2" -milc = "^1.1.0" -Pygments = "^2.8.0" dotty-dict = "^1.3.0" +hjson = "^3.0.2" jsonschema = "^3.2.0" +milc = "^1.3.0" +Pygments = "^2.8.0" +qmk = "*" [tool.poetry.dev-dependencies] nose2 = "^0.10.0" flake8 = "^3.8.4" +hid = "^1.0.4" pep8-naming = "^0.11.1" +pyusb = "^1.1.1" yapf = "^0.30.0" -Wave = "^0.0.2" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/nix/sources.json b/nix/sources.json index 7afca37073..caf5cb7d29 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -22,5 +22,17 @@ "type": "tarball", "url": "https://github.com/NixOS/nixpkgs/archive/c0e881852006b132236cbf0301bd1939bb50867e.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" + }, + "poetry2nix": { + "branch": "master", + "description": "Convert poetry projects to nix automagically [maintainer=@adisbladis] ", + "homepage": "", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "2d27d44397242b28c3f0081e0432e4f6c951f3a1", + "sha256": "06syfg150r59m4kksj5547b5kwxjxjaif5hiljcq966kb9hxsvmv", + "type": "tarball", + "url": "https://github.com/nix-community/poetry2nix/archive/2d27d44397242b28c3f0081e0432e4f6c951f3a1.tar.gz", + "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" } } diff --git a/platforms/chibios/BLACKPILL_STM32_F401/configs/bootloader_defs.h b/platforms/chibios/BLACKPILL_STM32_F401/configs/bootloader_defs.h new file mode 100644 index 0000000000..4da3d39a32 --- /dev/null +++ b/platforms/chibios/BLACKPILL_STM32_F401/configs/bootloader_defs.h @@ -0,0 +1,5 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/BLACKPILL_STM32_F411/configs/bootloader_defs.h b/platforms/chibios/BLACKPILL_STM32_F411/configs/bootloader_defs.h new file mode 100644 index 0000000000..4da3d39a32 --- /dev/null +++ b/platforms/chibios/BLACKPILL_STM32_F411/configs/bootloader_defs.h @@ -0,0 +1,5 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 diff --git a/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld new file mode 100644 index 0000000000..82253d3de5 --- /dev/null +++ b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xC_tinyuf2.ld @@ -0,0 +1,89 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * STM32F411xC memory setup. + */ +MEMORY +{ + flash0 (rx) : org = 0x08000000 + 64k, len = 256k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */ + flash1 (rx) : org = 0x00000000, len = 0 + flash2 (rx) : org = 0x00000000, len = 0 + flash3 (rx) : org = 0x00000000, len = 0 + flash4 (rx) : org = 0x00000000, len = 0 + flash5 (rx) : org = 0x00000000, len = 0 + flash6 (rx) : org = 0x00000000, len = 0 + flash7 (rx) : org = 0x00000000, len = 0 + ram0 (wx) : org = 0x20000000, len = 128k + ram1 (wx) : org = 0x00000000, len = 0 + ram2 (wx) : org = 0x00000000, len = 0 + ram3 (wx) : org = 0x00000000, len = 0 + ram4 (wx) : org = 0x00000000, len = 0 + ram5 (wx) : org = 0x00000000, len = 0 + ram6 (wx) : org = 0x00000000, len = 0 + ram7 (wx) : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld + +/* TinyUF2 bootloader reset support */ +_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */ + diff --git a/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld new file mode 100644 index 0000000000..1656c67bf7 --- /dev/null +++ b/platforms/chibios/BLACKPILL_STM32_F411/ld/STM32F411xE_tinyuf2.ld @@ -0,0 +1,89 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * STM32F411xE memory setup. + */ +MEMORY +{ + flash0 (rx) : org = 0x08000000 + 64k, len = 512k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */ + flash1 (rx) : org = 0x00000000, len = 0 + flash2 (rx) : org = 0x00000000, len = 0 + flash3 (rx) : org = 0x00000000, len = 0 + flash4 (rx) : org = 0x00000000, len = 0 + flash5 (rx) : org = 0x00000000, len = 0 + flash6 (rx) : org = 0x00000000, len = 0 + flash7 (rx) : org = 0x00000000, len = 0 + ram0 (wx) : org = 0x20000000, len = 128k + ram1 (wx) : org = 0x00000000, len = 0 + ram2 (wx) : org = 0x00000000, len = 0 + ram3 (wx) : org = 0x00000000, len = 0 + ram4 (wx) : org = 0x00000000, len = 0 + ram5 (wx) : org = 0x00000000, len = 0 + ram6 (wx) : org = 0x00000000, len = 0 + ram7 (wx) : org = 0x00000000, len = 0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld + +/* TinyUF2 bootloader reset support */ +_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */ + diff --git a/platforms/chibios/GENERIC_STM32_F446XE/board/board.mk b/platforms/chibios/GENERIC_STM32_F446XE/board/board.mk new file mode 100644 index 0000000000..57897941ca --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_F446XE/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F446RE/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F446RE + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_F446XE/configs/board.h b/platforms/chibios/GENERIC_STM32_F446XE/configs/board.h new file mode 100644 index 0000000000..80dfcffa99 --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_F446XE/configs/board.h @@ -0,0 +1,24 @@ +/* Copyright 2020 Nick Brassel (tzarc) + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ +#pragma once + +#define STM32_HSECLK 16000000 +// The following is required to disable the pull-down on PA9, when PA9 is used for the keyboard matrix: +#define BOARD_OTG_NOVBUSSENS + +#include_next "board.h" + +#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/GENERIC_STM32_F446XE/configs/config.h b/platforms/chibios/GENERIC_STM32_F446XE/configs/config.h new file mode 100644 index 0000000000..cc52a953ed --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_F446XE/configs/config.h @@ -0,0 +1,23 @@ +/* Copyright 2021 Andrei Purdea + * + * 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/>. + */ + +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/GENERIC_STM32_F446XE/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_F446XE/configs/mcuconf.h new file mode 100644 index 0000000000..d2de75590e --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_F446XE/configs/mcuconf.h @@ -0,0 +1,361 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 180 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SM_VALUE 8 +#define STM32_PLLI2SR_VALUE 4 +#define STM32_PLLI2SP_VALUE 4 +#define STM32_PLLI2SQ_VALUE 4 +#define STM32_PLLSAIN_VALUE 192 +#define STM32_PLLSAIM_VALUE 8 +#define STM32_PLLSAIP_VALUE 8 +#define STM32_PLLSAIQ_VALUE 4 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSE +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_PLLI2S +#define STM32_MCO2PRE STM32_MCO2PRE_DIV1 +#define STM32_I2SSRC STM32_I2SSRC_PLLI2S +#define STM32_SAI1SEL STM32_SAI2SEL_PLLR +#define STM32_SAI2SEL STM32_SAI2SEL_PLLR +#define STM32_CK48MSEL STM32_CK48MSEL_PLLALT +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_PRIORITY 15 +#define STM32_IRQ_EXTI22_PRIORITY 15 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 1000 +#define STM32_SDC_READ_TIMEOUT_MS 1000 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USE_UART7 FALSE +#define STM32_SERIAL_USE_UART8 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 +#define STM32_SERIAL_UART7_PRIORITY 12 +#define STM32_SERIAL_UART8_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_USE_SPI4 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/GENERIC_STM32_L433XC/board/board.mk b/platforms/chibios/GENERIC_STM32_L433XC/board/board.mk new file mode 100644 index 0000000000..1250385eb8 --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_L433XC/board/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC/board.c + +# Required include directories +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/platforms/chibios/GENERIC_STM32_L433XC/configs/board.h b/platforms/chibios/GENERIC_STM32_L433XC/configs/board.h new file mode 100644 index 0000000000..51f9724f94 --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_L433XC/configs/board.h @@ -0,0 +1,24 @@ +/* Copyright 2018-2021 Harrison Chan (@Xelus) + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ +#pragma once + +#include_next "board.h" + +#undef STM32L432xx + +// Pretend that we're an L443xx as the ChibiOS definitions for L432/L433 mistakenly don't enable GPIOH, I2C2, or SPI2. +// Until ChibiOS upstream is fixed, this should be kept at L443, as nothing in QMK currently utilises the crypto peripheral on the L443. +#define STM32L443xx diff --git a/platforms/chibios/GENERIC_STM32_L433XC/configs/config.h b/platforms/chibios/GENERIC_STM32_L433XC/configs/config.h new file mode 100644 index 0000000000..c27c61b19a --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_L433XC/configs/config.h @@ -0,0 +1,26 @@ +/* Copyright 2018-2021 Harrison Chan (@Xelus) + * + * 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/>. + */ + +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606. + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000 + +#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH + +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/GENERIC_STM32_L433XC/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_L433XC/configs/mcuconf.h new file mode 100644 index 0000000000..948c740f6e --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_L433XC/configs/mcuconf.h @@ -0,0 +1,292 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * STM32L4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#ifndef MCUCONF_H +#define MCUCONF_H + +#define STM32L4xx_MCUCONF +#define STM32L443_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_VOS STM32_VOS_RANGE1 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI16_ENABLED TRUE +#define STM32_HSI48_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSE_ENABLED FALSE +#define STM32_MSIPLL_ENABLED FALSE +#define STM32_MSIRANGE STM32_MSIRANGE_4M +#define STM32_MSISRANGE STM32_MSISRANGE_4M +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI16 +#define STM32_PLLM_VALUE 1 +#define STM32_PLLN_VALUE 10 +#define STM32_PLLPDIV_VALUE 0 +#define STM32_PLLP_VALUE 7 +#define STM32_PLLQ_VALUE 2 +#define STM32_PLLR_VALUE 2 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV1 +#define STM32_PPRE2 STM32_PPRE2_DIV1 +#define STM32_STOPWUCK STM32_STOPWUCK_MSI +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_MCOPRE STM32_MCOPRE_DIV1 +#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK +#define STM32_PLLSAI1N_VALUE 24 +#define STM32_PLLSAI1PDIV_VALUE 0 +#define STM32_PLLSAI1P_VALUE 7 +#define STM32_PLLSAI1Q_VALUE 2 +#define STM32_PLLSAI1R_VALUE 2 + +/* + * Peripherals clock sources. + */ +#define STM32_USART1SEL STM32_USART1SEL_SYSCLK +#define STM32_USART2SEL STM32_USART2SEL_SYSCLK +#define STM32_USART3SEL STM32_USART3SEL_SYSCLK +#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK +#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK +#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK +#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK +#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1 +#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1 +#define STM32_SAI1SEL STM32_SAI1SEL_OFF +#define STM32_CLK48SEL STM32_CLK48SEL_HSI48 +#define STM32_ADCSEL STM32_ADCSEL_SYSCLK +#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1 +#define STM32_RTCSEL STM32_RTCSEL_LSI + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI1635_38_PRIORITY 6 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 6 +#define STM32_IRQ_EXTI20_PRIORITY 6 +#define STM32_IRQ_EXTI21_22_PRIORITY 15 + +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#define STM32_IRQ_TIM1_CC_PRIORITY 7 +#define STM32_IRQ_TIM2_PRIORITY 7 +#define STM32_IRQ_TIM6_PRIORITY 7 +#define STM32_IRQ_TIM7_PRIORITY 7 + +#define STM32_IRQ_USART1_PRIORITY 12 +#define STM32_IRQ_USART2_PRIORITY 12 +#define STM32_IRQ_USART3_PRIORITY 12 +#define STM32_IRQ_LPUART1_PRIORITY 12 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_COMPACT_SAMPLES FALSE +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM15 FALSE +#define STM32_GPT_USE_TIM16 FALSE + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM15 FALSE +#define STM32_ICU_USE_TIM16 FALSE + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM15 FALSE +#define STM32_PWM_USE_TIM16 FALSE + +/* + * RTC driver system settings. + */ +#define STM32_RTC_PRESA_VALUE 32 +#define STM32_RTC_PRESS_VALUE 1024 +#define STM32_RTC_CR_INIT 0 +#define STM32_RTC_TAMPCR_INIT 0 + +/* + * SDMMC drive system settings. + */ +#define STM32_SDC_USE_SDMMC1 FALSE +#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000 +#define STM32_SDC_SDMMC_READ_TIMEOUT 1000 +#define STM32_SDC_SDMMC_CLOCK_DELAY 10 +#define STM32_SDC_SDMMC1_DMA_PRIORITY 3 +#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9 +#define STM32_SDC_SDMMC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_LPUART1 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_LPUART1_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * TRNG driver system settings. + */ +#define STM32_TRNG_USE_RNG1 FALSE + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +/* + * WSPI driver system settings. + */ +#define STM32_WSPI_USE_QUADSPI1 FALSE +#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) + +#endif /* MCUCONF_H */ diff --git a/platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk b/platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk index 3fa73a96e0..0618154678 100644 --- a/platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk +++ b/platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk @@ -2,11 +2,9 @@ TARGET := $(TARGET)_proton_c MCU := STM32F303 BOARD := QMK_PROTON_C +BOOTLOADER := stm32-dfu OPT_DEFS += -DCONVERT_TO_PROTON_C # These are defaults based on what has been implemented for ARM boards -AUDIO_ENABLE = yes -WS2812_DRIVER = bitbang - -# Force task driven PWM until ARM can provide automatic configuration -BACKLIGHT_DRIVER = software
\ No newline at end of file +AUDIO_ENABLE ?= yes +WS2812_DRIVER ?= bitbang diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c index 113beb832f..dfb98419e6 100644 --- a/quantum/backlight/backlight.c +++ b/quantum/backlight/backlight.c @@ -17,11 +17,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "quantum.h" #include "backlight.h" +#include "eeprom.h" #include "eeconfig.h" #include "debug.h" backlight_config_t backlight_config; +#ifndef BACKLIGHT_DEFAULT_LEVEL +# define BACKLIGHT_DEFAULT_LEVEL BACKLIGHT_LEVELS +#endif + #ifdef BACKLIGHT_BREATHING // TODO: migrate to backlight_config_t static uint8_t breathing_period = BREATHING_PERIOD; @@ -35,6 +40,7 @@ void backlight_init(void) { /* check signature */ if (!eeconfig_is_enabled()) { eeconfig_init(); + eeconfig_update_backlight_default(); } backlight_config.raw = eeconfig_read_backlight(); if (backlight_config.level > BACKLIGHT_LEVELS) { @@ -152,11 +158,23 @@ void backlight_level(uint8_t level) { eeconfig_update_backlight(backlight_config.raw); } -/** \brief Update current backlight state to EEPROM - * - */ +uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); } + +void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); } + void eeconfig_update_backlight_current(void) { eeconfig_update_backlight(backlight_config.raw); } +void eeconfig_update_backlight_default(void) { + backlight_config.enable = 1; +#ifdef BACKLIGHT_DEFAULT_BREATHING + backlight_config.breathing = 1; +#else + backlight_config.breathing = 0; +#endif + backlight_config.level = BACKLIGHT_DEFAULT_LEVEL; + eeconfig_update_backlight(backlight_config.raw); +} + /** \brief Get backlight level * * FIXME: needs doc diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h index 3e506737d4..c30c70fd62 100644 --- a/quantum/backlight/backlight.h +++ b/quantum/backlight/backlight.h @@ -55,7 +55,11 @@ void backlight_decrease(void); void backlight_level_noeeprom(uint8_t level); void backlight_level(uint8_t level); uint8_t get_backlight_level(void); + +uint8_t eeconfig_read_backlight(void); +void eeconfig_update_backlight(uint8_t val); void eeconfig_update_backlight_current(void); +void eeconfig_update_backlight_default(void); // implementation specific void backlight_init_ports(void); diff --git a/quantum/bootmagic/bootmagic.h b/quantum/bootmagic/bootmagic.h new file mode 100644 index 0000000000..959750178d --- /dev/null +++ b/quantum/bootmagic/bootmagic.h @@ -0,0 +1,24 @@ +/* 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 3 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(BOOTMAGIC_ENABLE) +# include "bootmagic_full.h" +#elif defined(BOOTMAGIC_LITE) +# include "bootmagic_lite.h" +#endif + +void bootmagic(void); diff --git a/tmk_core/common/bootmagic.c b/quantum/bootmagic/bootmagic_full.c index c1b3adf94d..a7a0dcfcb2 100644 --- a/tmk_core/common/bootmagic.c +++ b/quantum/bootmagic/bootmagic_full.c @@ -1,3 +1,18 @@ +/* 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 3 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 <stdbool.h> #include "wait.h" @@ -10,18 +25,35 @@ #include "eeconfig.h" #include "bootmagic.h" -keymap_config_t keymap_config; - -/** \brief Bootmagic +/** \brief Scan Keycode * * FIXME: needs doc */ -void bootmagic(void) { - /* check signature */ - if (!eeconfig_is_enabled()) { - eeconfig_init(); +static bool scan_keycode(uint8_t keycode) { + for (uint8_t r = 0; r < MATRIX_ROWS; r++) { + matrix_row_t matrix_row = matrix_get_row(r); + for (uint8_t c = 0; c < MATRIX_COLS; c++) { + if (matrix_row & ((matrix_row_t)1 << c)) { + if (keycode == keymap_key_to_keycode(0, (keypos_t){.row = r, .col = c})) { + return true; + } + } + } } + return false; +} + +/** \brief Bootmagic Scan Keycode + * + * FIXME: needs doc + */ +static bool bootmagic_scan_keycode(uint8_t keycode) { + if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false; + + return scan_keycode(keycode); +} +void bootmagic(void) { /* do scans in case of bounce */ print("bootmagic scan: ... "); uint8_t scan = 100; @@ -46,8 +78,6 @@ void bootmagic(void) { bootloader_jump(); } - /* debug enable */ - debug_config.raw = eeconfig_read_debug(); if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) { if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) { debug_config.matrix = !debug_config.matrix; @@ -61,8 +91,6 @@ void bootmagic(void) { } eeconfig_update_debug(debug_config.raw); - /* keymap config */ - keymap_config.raw = eeconfig_read_keymap(); if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) { keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock; } @@ -93,71 +121,27 @@ void bootmagic(void) { uint8_t default_layer = 0; if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { default_layer |= (1 << 0); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { + } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { default_layer |= (1 << 1); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { + } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { default_layer |= (1 << 2); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { + } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { default_layer |= (1 << 3); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { + } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { default_layer |= (1 << 4); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { + } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { default_layer |= (1 << 5); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { + } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { default_layer |= (1 << 6); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { + } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { default_layer |= (1 << 7); } - if (default_layer) { - eeconfig_update_default_layer(default_layer); - default_layer_set((layer_state_t)default_layer); - } else { - default_layer = eeconfig_read_default_layer(); - default_layer_set((layer_state_t)default_layer); - } - /* Also initialize layer state to trigger callback functions for layer_state */ - layer_state_set_kb((layer_state_t)layer_state); + eeconfig_update_default_layer(default_layer); /* EE_HANDS handedness */ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_LEFT)) { eeconfig_update_handedness(true); - } - if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_RIGHT)) { + } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_RIGHT)) { eeconfig_update_handedness(false); } } - -/** \brief Scan Keycode - * - * FIXME: needs doc - */ -static bool scan_keycode(uint8_t keycode) { - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - matrix_row_t matrix_row = matrix_get_row(r); - for (uint8_t c = 0; c < MATRIX_COLS; c++) { - if (matrix_row & ((matrix_row_t)1 << c)) { - if (keycode == keymap_key_to_keycode(0, (keypos_t){.row = r, .col = c})) { - return true; - } - } - } - } - return false; -} - -/** \brief Bootmagic Scan Keycode - * - * FIXME: needs doc - */ -bool bootmagic_scan_keycode(uint8_t keycode) { - if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false; - - return scan_keycode(keycode); -} diff --git a/tmk_core/common/bootmagic.h b/quantum/bootmagic/bootmagic_full.h index 8209d0194f..28f914c1b6 100644 --- a/tmk_core/common/bootmagic.h +++ b/quantum/bootmagic/bootmagic_full.h @@ -1,3 +1,19 @@ +/* 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 3 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 /* FIXME: Add special doxygen comments for defines here. */ @@ -96,7 +112,4 @@ #endif #ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_7 # define BOOTMAGIC_KEY_DEFAULT_LAYER_7 KC_7 -#endif - -void bootmagic(void); -bool bootmagic_scan_keycode(uint8_t keycode); +#endif
\ No newline at end of file diff --git a/tmk_core/common/bootmagic_lite.c b/quantum/bootmagic/bootmagic_lite.c index cbf756a175..9cbdcb0bbd 100644 --- a/tmk_core/common/bootmagic_lite.c +++ b/quantum/bootmagic/bootmagic_lite.c @@ -1,3 +1,18 @@ +/* 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 3 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 "quantum.h" /** \brief Reset eeprom @@ -47,3 +62,5 @@ __attribute__((weak)) void bootmagic_lite(void) { bootloader_jump(); } } + +void bootmagic(void) { bootmagic_lite(); } diff --git a/quantum/bootmagic/bootmagic_lite.h b/quantum/bootmagic/bootmagic_lite.h new file mode 100644 index 0000000000..17777e6b4a --- /dev/null +++ b/quantum/bootmagic/bootmagic_lite.h @@ -0,0 +1,25 @@ +/* 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 3 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 BOOTMAGIC_LITE_COLUMN +# define BOOTMAGIC_LITE_COLUMN 0 +#endif +#ifndef BOOTMAGIC_LITE_ROW +# define BOOTMAGIC_LITE_ROW 0 +#endif + +void bootmagic_lite(void); diff --git a/quantum/bootmagic/magic.c b/quantum/bootmagic/magic.c new file mode 100644 index 0000000000..f1cb11c395 --- /dev/null +++ b/quantum/bootmagic/magic.c @@ -0,0 +1,54 @@ +/* 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 3 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 <stdbool.h> +#include "wait.h" +#include "matrix.h" +#include "bootloader.h" +#include "debug.h" +#include "keymap.h" +#include "host.h" +#include "action_layer.h" +#include "eeconfig.h" +#include "bootmagic.h" + +keymap_config_t keymap_config; + +__attribute__((weak)) void bootmagic(void) {} + +/** \brief Magic + * + * FIXME: Needs doc + */ +void magic(void) { + /* check signature */ + if (!eeconfig_is_enabled()) { + eeconfig_init(); + } + + /* init globals */ + debug_config.raw = eeconfig_read_debug(); + keymap_config.raw = eeconfig_read_keymap(); + + bootmagic(); + + /* read here just incase bootmagic process changed its value */ + layer_state_t default_layer = (layer_state_t)eeconfig_read_default_layer(); + default_layer_set(default_layer); + + /* Also initialize layer state to trigger callback functions for layer_state */ + layer_state_set_kb((layer_state_t)layer_state); +} diff --git a/quantum/bootmagic/magic.h b/quantum/bootmagic/magic.h new file mode 100644 index 0000000000..2c3969b85c --- /dev/null +++ b/quantum/bootmagic/magic.h @@ -0,0 +1,18 @@ +/* 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 3 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 + +void magic(void); diff --git a/quantum/config_common.h b/quantum/config_common.h index d93477b27e..661609ef2a 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -24,4 +24,7 @@ #define COL2ROW 0 #define ROW2COL 1 +// Deprecated alias - avoid using +#define KEYMAP LAYOUT + #include "song_list.h" diff --git a/quantum/encoder.c b/quantum/encoder.c index 2ed64c1e30..c30bf01cb2 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -59,9 +59,9 @@ static uint8_t thisHand, thatHand; static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0}; #endif -__attribute__((weak)) void encoder_update_user(int8_t index, bool clockwise) {} +__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; } -__attribute__((weak)) void encoder_update_kb(int8_t index, bool clockwise) { encoder_update_user(index, clockwise); } +__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); } void encoder_init(void) { #if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT) @@ -94,14 +94,14 @@ void encoder_init(void) { #endif } -static bool encoder_update(int8_t index, uint8_t state) { +static bool encoder_update(uint8_t index, uint8_t state) { bool changed = false; uint8_t i = index; #ifdef ENCODER_RESOLUTIONS - int8_t resolution = encoder_resolutions[i]; + uint8_t resolution = encoder_resolutions[i]; #else - int8_t resolution = ENCODER_RESOLUTION; + uint8_t resolution = ENCODER_RESOLUTION; #endif #ifdef SPLIT_KEYBOARD diff --git a/quantum/encoder.h b/quantum/encoder.h index db6f220da4..25dc77721d 100644 --- a/quantum/encoder.h +++ b/quantum/encoder.h @@ -22,8 +22,8 @@ void encoder_init(void); bool encoder_read(void); -void encoder_update_kb(int8_t index, bool clockwise); -void encoder_update_user(int8_t index, bool clockwise); +bool encoder_update_kb(uint8_t index, bool clockwise); +bool encoder_update_user(uint8_t index, bool clockwise); #ifdef SPLIT_KEYBOARD void encoder_state_raw(uint8_t* slave_state); diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h index f878168c5f..d7e334fdc8 100644 --- a/quantum/keycode_config.h +++ b/quantum/keycode_config.h @@ -37,6 +37,7 @@ typedef union { bool nkro : 1; bool swap_lctl_lgui : 1; bool swap_rctl_rgui : 1; + bool oneshot_disable : 1; }; } keymap_config_t; diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c index 4f1f06c7ac..7e0fdf896a 100644 --- a/quantum/led_matrix.c +++ b/quantum/led_matrix.c @@ -17,79 +17,143 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <stdint.h> -#include <stdbool.h> -#include "quantum.h" #include "led_matrix.h" #include "progmem.h" #include "config.h" #include "eeprom.h" #include <string.h> #include <math.h> +#include "led_tables.h" -led_eeconfig_t led_matrix_eeconfig; +#include <lib/lib8tion/lib8tion.h> -#ifndef MAX -# define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#ifndef LED_MATRIX_CENTER +const led_point_t k_led_matrix_center = {112, 32}; +#else +const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; #endif -#ifndef MIN -# define MIN(a, b) ((a) < (b) ? (a) : (b)) +// Generic effect runners +#include "led_matrix_runners/effect_runner_dx_dy_dist.h" +#include "led_matrix_runners/effect_runner_dx_dy.h" +#include "led_matrix_runners/effect_runner_i.h" +#include "led_matrix_runners/effect_runner_sin_cos_i.h" +#include "led_matrix_runners/effect_runner_reactive.h" +#include "led_matrix_runners/effect_runner_reactive_splash.h" + +// ------------------------------------------ +// -----Begin led effect includes macros----- +#define LED_MATRIX_EFFECT(name) +#define LED_MATRIX_CUSTOM_EFFECT_IMPLS + +#include "led_matrix_animations/led_matrix_effects.inc" +#ifdef LED_MATRIX_CUSTOM_KB +# include "led_matrix_kb.inc" #endif +#ifdef LED_MATRIX_CUSTOM_USER +# include "led_matrix_user.inc" +#endif + +#undef LED_MATRIX_CUSTOM_EFFECT_IMPLS +#undef LED_MATRIX_EFFECT +// -----End led effect includes macros------- +// ------------------------------------------ -#ifndef LED_DISABLE_AFTER_TIMEOUT -# define LED_DISABLE_AFTER_TIMEOUT 0 +#if defined(LED_DISABLE_AFTER_TIMEOUT) && !defined(LED_DISABLE_TIMEOUT) +# define LED_DISABLE_TIMEOUT (LED_DISABLE_AFTER_TIMEOUT * 1200UL) #endif -#ifndef LED_DISABLE_WHEN_USB_SUSPENDED -# define LED_DISABLE_WHEN_USB_SUSPENDED false +#ifndef LED_DISABLE_TIMEOUT +# define LED_DISABLE_TIMEOUT 0 #endif -#ifndef EECONFIG_LED_MATRIX -# define EECONFIG_LED_MATRIX EECONFIG_RGBLIGHT +#if LED_DISABLE_WHEN_USB_SUSPENDED != 1 +# undef LED_DISABLE_WHEN_USB_SUSPENDED #endif -#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > 255 -# define LED_MATRIX_MAXIMUM_BRIGHTNESS 255 +#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX +# undef LED_MATRIX_MAXIMUM_BRIGHTNESS +# define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX #endif -bool g_suspend_state = false; +#if !defined(LED_MATRIX_VAL_STEP) +# define LED_MATRIX_VAL_STEP 8 +#endif -// Global tick at 20 Hz -uint32_t g_tick = 0; +#if !defined(LED_MATRIX_SPD_STEP) +# define LED_MATRIX_SPD_STEP 16 +#endif -// Ticks since this key was last hit. -uint8_t g_key_hit[DRIVER_LED_TOTAL]; +#if !defined(LED_MATRIX_STARTUP_MODE) +# define LED_MATRIX_STARTUP_MODE LED_MATRIX_SOLID +#endif -// Ticks since any key was last hit. -uint32_t g_any_key_hit = 0; +#if !defined(LED_MATRIX_STARTUP_VAL) +# define LED_MATRIX_STARTUP_VAL LED_MATRIX_MAXIMUM_BRIGHTNESS +#endif -uint32_t eeconfig_read_led_matrix(void) { return eeprom_read_dword(EECONFIG_LED_MATRIX); } +#if !defined(LED_MATRIX_STARTUP_SPD) +# define LED_MATRIX_STARTUP_SPD UINT8_MAX / 2 +#endif -void eeconfig_update_led_matrix(uint32_t config_value) { eeprom_update_dword(EECONFIG_LED_MATRIX, config_value); } +// globals +led_eeconfig_t led_matrix_eeconfig; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr +uint32_t g_led_timer; +#ifdef LED_MATRIX_FRAMEBUFFER_EFFECTS +uint8_t g_led_frame_buffer[MATRIX_ROWS][MATRIX_COLS] = {{0}}; +#endif // LED_MATRIX_FRAMEBUFFER_EFFECTS +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +last_hit_t g_last_hit_tracker; +#endif // LED_MATRIX_KEYREACTIVE_ENABLED + +// internals +static bool suspend_state = 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}; +static led_task_states led_task_state = SYNCING; +#if LED_DISABLE_TIMEOUT > 0 +static uint32_t led_anykey_timer; +#endif // LED_DISABLE_TIMEOUT > 0 + +// double buffers +static uint32_t led_timer_buffer; +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +static last_hit_t last_hit_buffer; +#endif // LED_MATRIX_KEYREACTIVE_ENABLED + +// split led matrix +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +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)); } + +void eeconfig_update_led_matrix(void) { eeprom_update_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); } void eeconfig_update_led_matrix_default(void) { dprintf("eeconfig_update_led_matrix_default\n"); led_matrix_eeconfig.enable = 1; - led_matrix_eeconfig.mode = LED_MATRIX_UNIFORM_BRIGHTNESS; - led_matrix_eeconfig.val = 128; - led_matrix_eeconfig.speed = 0; - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); + led_matrix_eeconfig.mode = LED_MATRIX_STARTUP_MODE; + 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(); } void eeconfig_debug_led_matrix(void) { - dprintf("led_matrix_eeconfig eeprom\n"); + dprintf("led_matrix_eeconfig EEPROM\n"); dprintf("led_matrix_eeconfig.enable = %d\n", led_matrix_eeconfig.enable); dprintf("led_matrix_eeconfig.mode = %d\n", led_matrix_eeconfig.mode); dprintf("led_matrix_eeconfig.val = %d\n", led_matrix_eeconfig.val); dprintf("led_matrix_eeconfig.speed = %d\n", led_matrix_eeconfig.speed); + dprintf("led_matrix_eeconfig.flags = %d\n", led_matrix_eeconfig.flags); } -uint8_t g_last_led_hit[LED_HITS_TO_REMEMBER] = {255}; -uint8_t g_last_led_count = 0; +__attribute__((weak)) uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; } -uint8_t map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) { - uint8_t led_count = 0; +uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) { + uint8_t led_count = led_matrix_map_row_column_to_led_kb(row, column, led_i); uint8_t led_index = g_led_config.matrix_co[row][column]; if (led_index != NO_LED) { led_i[led_count] = led_index; @@ -100,88 +164,235 @@ uint8_t map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) { void led_matrix_update_pwm_buffers(void) { led_matrix_driver.flush(); } -void led_matrix_set_index_value(int index, uint8_t value) { led_matrix_driver.set_value(index, value); } - -void led_matrix_set_index_value_all(uint8_t value) { led_matrix_driver.set_value_all(value); } - -bool process_led_matrix(uint16_t keycode, keyrecord_t *record) { - if (record->event.pressed) { - uint8_t led[8]; - uint8_t led_count = map_row_column_to_led(record->event.key.row, record->event.key.col, led); - if (led_count > 0) { - for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) { - g_last_led_hit[i - 1] = g_last_led_hit[i - 2]; - } - g_last_led_hit[0] = led[0]; - g_last_led_count = MIN(LED_HITS_TO_REMEMBER, g_last_led_count + 1); - } - for (uint8_t i = 0; i < led_count; i++) g_key_hit[led[i]] = 0; - g_any_key_hit = 0; - } else { -#ifdef LED_MATRIX_KEYRELEASES - uint8_t led[8]; - uint8_t led_count = map_row_column_to_led(record->event.key.row, record->event.key.col, led); - for (uint8_t i = 0; i < led_count; i++) g_key_hit[led[i]] = 255; +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); +#endif +} - g_any_key_hit = 255; +void led_matrix_set_value_all(uint8_t value) { +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) led_matrix_set_value(i, value); +#else +# ifdef USE_CIE1931_CURVE + led_matrix_driver.set_value_all(pgm_read_byte(&CIE1931_CURVE[value])); +# else + led_matrix_driver.set_value_all(value); +# endif #endif - } - return true; } -void led_matrix_set_suspend_state(bool state) { g_suspend_state = state; } +void process_led_matrix(uint8_t row, uint8_t col, bool pressed) { +#ifndef LED_MATRIX_SPLIT + if (!is_keyboard_master()) return; +#endif +#if LED_DISABLE_TIMEOUT > 0 + led_anykey_timer = 0; +#endif // LED_DISABLE_TIMEOUT > 0 -// All LEDs off -void led_matrix_all_off(void) { led_matrix_set_index_value_all(0); } +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED + uint8_t led[LED_HITS_TO_REMEMBER]; + uint8_t led_count = 0; -// Uniform brightness -void led_matrix_uniform_brightness(void) { led_matrix_set_index_value_all(LED_MATRIX_MAXIMUM_BRIGHTNESS / BACKLIGHT_LEVELS * led_matrix_eeconfig.val); } +# if defined(LED_MATRIX_KEYRELEASES) + if (!pressed) +# elif defined(LED_MATRIX_KEYPRESSES) + if (pressed) +# endif // defined(LED_MATRIX_KEYRELEASES) + { + led_count = led_matrix_map_row_column_to_led(row, col, led); + } -void led_matrix_custom(void) {} + if (last_hit_buffer.count + led_count > LED_HITS_TO_REMEMBER) { + memcpy(&last_hit_buffer.x[0], &last_hit_buffer.x[led_count], LED_HITS_TO_REMEMBER - led_count); + memcpy(&last_hit_buffer.y[0], &last_hit_buffer.y[led_count], LED_HITS_TO_REMEMBER - led_count); + memcpy(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2); // 16 bit + memcpy(&last_hit_buffer.index[0], &last_hit_buffer.index[led_count], LED_HITS_TO_REMEMBER - led_count); + last_hit_buffer.count--; + } -void led_matrix_task(void) { - if (!led_matrix_eeconfig.enable) { - led_matrix_all_off(); - led_matrix_indicators(); - return; + for (uint8_t i = 0; i < led_count; i++) { + uint8_t index = last_hit_buffer.count; + last_hit_buffer.x[index] = g_led_config.point[led[i]].x; + last_hit_buffer.y[index] = g_led_config.point[led[i]].y; + last_hit_buffer.index[index] = led[i]; + last_hit_buffer.tick[index] = 0; + last_hit_buffer.count++; } +#endif // LED_MATRIX_KEYREACTIVE_ENABLED - g_tick++; +#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_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) +} - if (g_any_key_hit < 0xFFFFFFFF) { - g_any_key_hit++; +static bool led_matrix_none(effect_params_t *params) { + if (!params->init) { + return false; } - for (int led = 0; led < DRIVER_LED_TOTAL; led++) { - if (g_key_hit[led] < 255) { - if (g_key_hit[led] == 254) g_last_led_count = MAX(g_last_led_count - 1, 0); - g_key_hit[led]++; + led_matrix_set_value_all(0); + return false; +} + +static void led_task_timers(void) { +#if defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_DISABLE_TIMEOUT > 0 + uint32_t deltaTime = sync_timer_elapsed32(led_timer_buffer); +#endif // defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_DISABLE_TIMEOUT > 0 + led_timer_buffer = sync_timer_read32(); + + // Update double buffer timers +#if LED_DISABLE_TIMEOUT > 0 + if (led_anykey_timer < UINT32_MAX) { + if (UINT32_MAX - deltaTime < led_anykey_timer) { + led_anykey_timer = UINT32_MAX; + } else { + led_anykey_timer += deltaTime; } } +#endif // LED_DISABLE_TIMEOUT > 0 + + // Update double buffer last hit timers +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED + uint8_t count = last_hit_buffer.count; + for (uint8_t i = 0; i < count; ++i) { + if (UINT16_MAX - deltaTime < last_hit_buffer.tick[i]) { + last_hit_buffer.count--; + continue; + } + last_hit_buffer.tick[i] += deltaTime; + } +#endif // LED_MATRIX_KEYREACTIVE_ENABLED +} - // Ideally we would also stop sending zeros to the LED driver PWM buffers - // while suspended and just do a software shutdown. This is a cheap hack for now. - bool suspend_backlight = ((g_suspend_state && LED_DISABLE_WHEN_USB_SUSPENDED) || (LED_DISABLE_AFTER_TIMEOUT > 0 && g_any_key_hit > LED_DISABLE_AFTER_TIMEOUT * 60 * 20)); - uint8_t effect = suspend_backlight ? 0 : led_matrix_eeconfig.mode; +static void led_task_sync(void) { + // next task + if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING; +} + +static void led_task_start(void) { + // reset iter + led_effect_params.iter = 0; + + // update double buffers + g_led_timer = led_timer_buffer; +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED + g_last_hit_tracker = last_hit_buffer; +#endif // LED_MATRIX_KEYREACTIVE_ENABLED + + // next task + led_task_state = RENDERING; +} + +static void led_task_render(uint8_t effect) { + bool rendering = false; + led_effect_params.init = (effect != led_last_effect) || (led_matrix_eeconfig.enable != led_last_enable); + if (led_effect_params.flags != led_matrix_eeconfig.flags) { + led_effect_params.flags = led_matrix_eeconfig.flags; + led_matrix_set_value_all(0); + } - // this gets ticked at 20 Hz. // each effect can opt to do calculations // and/or request PWM buffer updates. switch (effect) { - case LED_MATRIX_UNIFORM_BRIGHTNESS: - led_matrix_uniform_brightness(); + case LED_MATRIX_NONE: + rendering = led_matrix_none(&led_effect_params); break; - default: - led_matrix_custom(); + +// --------------------------------------------- +// -----Begin led effect switch case macros----- +#define LED_MATRIX_EFFECT(name, ...) \ + case LED_MATRIX_##name: \ + rendering = name(&led_effect_params); \ + break; +#include "led_matrix_animations/led_matrix_effects.inc" +#undef LED_MATRIX_EFFECT + +#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) +# define LED_MATRIX_EFFECT(name, ...) \ + case LED_MATRIX_CUSTOM_##name: \ + rendering = name(&led_effect_params); \ break; +# ifdef LED_MATRIX_CUSTOM_KB +# include "led_matrix_kb.inc" +# endif +# ifdef LED_MATRIX_CUSTOM_USER +# include "led_matrix_user.inc" +# endif +# undef LED_MATRIX_EFFECT +#endif + // -----End led effect switch case macros------- + // --------------------------------------------- } - if (!suspend_backlight) { - led_matrix_indicators(); + led_effect_params.iter++; + + // next task + if (!rendering) { + led_task_state = FLUSHING; + if (!led_effect_params.init && effect == LED_MATRIX_NONE) { + // We only need to flush once if we are LED_MATRIX_NONE + led_task_state = SYNCING; + } } +} + +static void led_task_flush(uint8_t effect) { + // update last trackers after the first full render so we can init over several frames + led_last_effect = effect; + led_last_enable = led_matrix_eeconfig.enable; + + // update pwm buffers + led_matrix_update_pwm_buffers(); - // Tell the LED driver to update its state - led_matrix_driver.flush(); + // next task + led_task_state = SYNCING; +} + +void led_matrix_task(void) { + led_task_timers(); + + // Ideally we would also stop sending zeros to the LED driver PWM buffers + // while suspended and just do a software shutdown. This is a cheap hack for now. + bool suspend_backlight = suspend_state || +#if LED_DISABLE_TIMEOUT > 0 + (led_anykey_timer > (uint32_t)LED_DISABLE_TIMEOUT) || +#endif // LED_DISABLE_TIMEOUT > 0 + false; + + uint8_t effect = suspend_backlight || !led_matrix_eeconfig.enable ? 0 : led_matrix_eeconfig.mode; + + switch (led_task_state) { + case STARTING: + led_task_start(); + break; + case RENDERING: + led_task_render(effect); + if (effect) { + led_matrix_indicators(); + led_matrix_indicators_advanced(&led_effect_params); + } + break; + case FLUSHING: + led_task_flush(effect); + break; + case SYNCING: + led_task_sync(); + break; + } } void led_matrix_indicators(void) { @@ -193,33 +404,42 @@ __attribute__((weak)) void led_matrix_indicators_kb(void) {} __attribute__((weak)) void led_matrix_indicators_user(void) {} -// void led_matrix_set_indicator_index(uint8_t *index, uint8_t row, uint8_t column) -// { -// if (row >= MATRIX_ROWS) -// { -// // Special value, 255=none, 254=all -// *index = row; -// } -// else -// { -// // This needs updated to something like -// // uint8_t led[8]; -// // uint8_t led_count = map_row_column_to_led(row, column, led); -// // for(uint8_t i = 0; i < led_count; i++) -// map_row_column_to_led(row, column, index); -// } -// } +void led_matrix_indicators_advanced(effect_params_t *params) { + /* special handling is needed for "params->iter", since it's already been incremented. + * Could move the invocations to led_task_render, but then it's missing a few checks + * and not sure which would be better. Otherwise, this should be called from + * led_task_render, right before the iter++ line. + */ +#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL + uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * (params->iter - 1); + uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; + if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; +#else + uint8_t min = 0; + uint8_t max = DRIVER_LED_TOTAL; +#endif + led_matrix_indicators_advanced_kb(min, max); + led_matrix_indicators_advanced_user(min, max); +} + +__attribute__((weak)) void led_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max) {} + +__attribute__((weak)) void led_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {} void led_matrix_init(void) { led_matrix_driver.init(); - // Wait half a second for the driver to finish initializing - wait_ms(500); +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED + g_last_hit_tracker.count = 0; + for (uint8_t i = 0; i < LED_HITS_TO_REMEMBER; ++i) { + g_last_hit_tracker.tick[i] = UINT16_MAX; + } - // clear the key hits - for (int led = 0; led < DRIVER_LED_TOTAL; led++) { - g_key_hit[led] = 255; + last_hit_buffer.count = 0; + for (uint8_t i = 0; i < LED_HITS_TO_REMEMBER; ++i) { + last_hit_buffer.tick[i] = UINT16_MAX; } +#endif // LED_MATRIX_KEYREACTIVE_ENABLED if (!eeconfig_is_enabled()) { dprintf("led_matrix_init_drivers eeconfig is not enabled.\n"); @@ -227,122 +447,137 @@ void led_matrix_init(void) { eeconfig_update_led_matrix_default(); } - led_matrix_eeconfig.raw = eeconfig_read_led_matrix(); - + eeconfig_read_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(); - led_matrix_eeconfig.raw = eeconfig_read_led_matrix(); } - eeconfig_debug_led_matrix(); // display current eeprom values } -// Deals with the messy details of incrementing an integer -static uint8_t increment(uint8_t value, uint8_t step, uint8_t min, uint8_t max) { - int16_t new_value = value; - new_value += step; - return MIN(MAX(new_value, min), max); +void led_matrix_set_suspend_state(bool state) { +#ifdef LED_DISABLE_WHEN_USB_SUSPENDED + if (state) { + led_matrix_set_value_all(0); // turn off all LEDs when suspending + } + suspend_state = state; +#endif } -static uint8_t decrement(uint8_t value, uint8_t step, uint8_t min, uint8_t max) { - int16_t new_value = value; - new_value -= step; - return MIN(MAX(new_value, min), max); -} +bool led_matrix_get_suspend_state(void) { return suspend_state; } -// void *backlight_get_custom_key_value_eeprom_address(uint8_t led) { -// // 3 bytes per value -// return EECONFIG_LED_MATRIX + (led * 3); -// } - -// void backlight_get_key_value(uint8_t led, uint8_t *value) { -// void *address = backlight_get_custom_key_value_eeprom_address(led); -// value = eeprom_read_byte(address); -// } - -// void backlight_set_key_value(uint8_t row, uint8_t column, uint8_t value) { -// uint8_t led[8]; -// uint8_t led_count = map_row_column_to_led(row, column, led); -// for(uint8_t i = 0; i < led_count; i++) { -// if (led[i] < DRIVER_LED_TOTAL) { -// void *address = backlight_get_custom_key_value_eeprom_address(led[i]); -// eeprom_update_byte(address, value); -// } -// } -// } - -uint32_t led_matrix_get_tick(void) { return g_tick; } - -void led_matrix_toggle(void) { +void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { led_matrix_eeconfig.enable ^= 1; - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); + led_task_state = STARTING; + if (write_to_eeprom) { + eeconfig_update_led_matrix(); + } + 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); } +void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); } void led_matrix_enable(void) { - led_matrix_eeconfig.enable = 1; - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); + led_matrix_enable_noeeprom(); + eeconfig_update_led_matrix(); } -void led_matrix_enable_noeeprom(void) { led_matrix_eeconfig.enable = 1; } +void led_matrix_enable_noeeprom(void) { + if (!led_matrix_eeconfig.enable) led_task_state = STARTING; + led_matrix_eeconfig.enable = 1; +} void led_matrix_disable(void) { + led_matrix_disable_noeeprom(); + eeconfig_update_led_matrix(); +} + +void led_matrix_disable_noeeprom(void) { + if (led_matrix_eeconfig.enable) led_task_state = STARTING; led_matrix_eeconfig.enable = 0; - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); } -void led_matrix_disable_noeeprom(void) { led_matrix_eeconfig.enable = 0; } +uint8_t led_matrix_is_enabled(void) { return led_matrix_eeconfig.enable; } -void led_matrix_step(void) { - led_matrix_eeconfig.mode++; - if (led_matrix_eeconfig.mode >= LED_MATRIX_EFFECT_MAX) { - led_matrix_eeconfig.mode = 1; +void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { + if (!led_matrix_eeconfig.enable) { + return; } - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); -} - -void led_matrix_step_reverse(void) { - led_matrix_eeconfig.mode--; - if (led_matrix_eeconfig.mode < 1) { + if (mode < 1) { + led_matrix_eeconfig.mode = 1; + } else if (mode >= LED_MATRIX_EFFECT_MAX) { led_matrix_eeconfig.mode = LED_MATRIX_EFFECT_MAX - 1; + } else { + led_matrix_eeconfig.mode = mode; + } + led_task_state = STARTING; + if (write_to_eeprom) { + eeconfig_update_led_matrix(); } - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); + 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); } +void led_matrix_mode(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, true); } -void led_matrix_increase_val(void) { - led_matrix_eeconfig.val = increment(led_matrix_eeconfig.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS); - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); -} +uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; } -void led_matrix_decrease_val(void) { - led_matrix_eeconfig.val = decrement(led_matrix_eeconfig.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS); - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); +void led_matrix_step_helper(bool write_to_eeprom) { + uint8_t mode = led_matrix_eeconfig.mode + 1; + led_matrix_mode_eeprom_helper((mode < LED_MATRIX_EFFECT_MAX) ? mode : 1, write_to_eeprom); } +void led_matrix_step_noeeprom(void) { led_matrix_step_helper(false); } +void led_matrix_step(void) { led_matrix_step_helper(true); } -void led_matrix_increase_speed(void) { - led_matrix_eeconfig.speed = increment(led_matrix_eeconfig.speed, 1, 0, 3); - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); // EECONFIG needs to be increased to support this +void led_matrix_step_reverse_helper(bool write_to_eeprom) { + uint8_t mode = led_matrix_eeconfig.mode - 1; + led_matrix_mode_eeprom_helper((mode < 1) ? LED_MATRIX_EFFECT_MAX - 1 : mode, write_to_eeprom); } +void led_matrix_step_reverse_noeeprom(void) { led_matrix_step_reverse_helper(false); } +void led_matrix_step_reverse(void) { led_matrix_step_reverse_helper(true); } -void led_matrix_decrease_speed(void) { - led_matrix_eeconfig.speed = decrement(led_matrix_eeconfig.speed, 1, 0, 3); - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); // EECONFIG needs to be increased to support this +void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) { + if (!led_matrix_eeconfig.enable) { + return; + } + led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; + if (write_to_eeprom) { + eeconfig_update_led_matrix(); + } + 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); } +void led_matrix_set_val(uint8_t val) { led_matrix_set_val_eeprom_helper(val, true); } -void led_matrix_mode(uint8_t mode, bool eeprom_write) { - led_matrix_eeconfig.mode = mode; - if (eeprom_write) { - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); +uint8_t led_matrix_get_val(void) { return led_matrix_eeconfig.val; } + +void led_matrix_increase_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qadd8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); } +void led_matrix_increase_val_noeeprom(void) { led_matrix_increase_val_helper(false); } +void led_matrix_increase_val(void) { led_matrix_increase_val_helper(true); } + +void led_matrix_decrease_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qsub8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); } +void led_matrix_decrease_val_noeeprom(void) { led_matrix_decrease_val_helper(false); } +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; + if (write_to_eeprom) { + eeconfig_update_led_matrix(); } + 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); } +void led_matrix_set_speed(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, true); } -uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; } +uint8_t led_matrix_get_speed(void) { return led_matrix_eeconfig.speed; } -void led_matrix_set_value_noeeprom(uint8_t val) { led_matrix_eeconfig.val = val; } +void led_matrix_increase_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qadd8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); } +void led_matrix_increase_speed_noeeprom(void) { led_matrix_increase_speed_helper(false); } +void led_matrix_increase_speed(void) { led_matrix_increase_speed_helper(true); } -void led_matrix_set_value(uint8_t val) { - led_matrix_set_value_noeeprom(val); - eeconfig_update_led_matrix(led_matrix_eeconfig.raw); -} +void led_matrix_decrease_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qsub8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); } +void led_matrix_decrease_speed_noeeprom(void) { led_matrix_decrease_speed_helper(false); } +void led_matrix_decrease_speed(void) { led_matrix_decrease_speed_helper(true); } + +led_flags_t led_matrix_get_flags(void) { return led_matrix_eeconfig.flags; } -void backlight_set(uint8_t val) { led_matrix_set_value(val); } +void led_matrix_set_flags(led_flags_t flags) { led_matrix_eeconfig.flags = flags; } diff --git a/quantum/led_matrix.h b/quantum/led_matrix.h index 85bae43c15..0984de73b3 100644 --- a/quantum/led_matrix.h +++ b/quantum/led_matrix.h @@ -19,61 +19,120 @@ #pragma once +#include <stdint.h> +#include <stdbool.h> #include "led_matrix_types.h" +#include "quantum.h" -#ifndef BACKLIGHT_ENABLE -# error You must define BACKLIGHT_ENABLE with LED_MATRIX_ENABLE +#ifdef IS31FL3731 +# include "is31fl3731-simple.h" #endif +#ifndef LED_MATRIX_LED_FLUSH_LIMIT +# define LED_MATRIX_LED_FLUSH_LIMIT 16 +#endif + +#ifndef LED_MATRIX_LED_PROCESS_LIMIT +# define LED_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 +#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; +#else +# define LED_MATRIX_USE_LIMITS(min, max) \ + uint8_t min = 0; \ + uint8_t max = DRIVER_LED_TOTAL; +#endif + +#define LED_MATRIX_TEST_LED_FLAGS() \ + if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) continue + enum led_matrix_effects { - LED_MATRIX_UNIFORM_BRIGHTNESS = 1, - // All new effects go above this line + LED_MATRIX_NONE = 0, + +// -------------------------------------- +// -----Begin led effect enum macros----- +#define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name, +#include "led_matrix_animations/led_matrix_effects.inc" +#undef LED_MATRIX_EFFECT + +#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) +# define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_CUSTOM_##name, +# ifdef LED_MATRIX_CUSTOM_KB +# include "led_matrix_kb.inc" +# endif +# ifdef LED_MATRIX_CUSTOM_USER +# include "led_matrix_user.inc" +# endif +# undef LED_MATRIX_EFFECT +#endif + // -------------------------------------- + // -----End led effect enum macros------- + LED_MATRIX_EFFECT_MAX }; -void led_matrix_set_index_value(int index, uint8_t value); -void led_matrix_set_index_value_all(uint8_t value); +void eeconfig_update_led_matrix_default(void); +void eeconfig_update_led_matrix(void); +void eeconfig_debug_led_matrix(void); + +uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i); +uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i); + +void led_matrix_set_value(int index, uint8_t value); +void led_matrix_set_value_all(uint8_t value); + +void process_led_matrix(uint8_t row, uint8_t col, bool pressed); + +void led_matrix_task(void); // This runs after another backlight effect and replaces -// colors already set +// values already set void led_matrix_indicators(void); void led_matrix_indicators_kb(void); void led_matrix_indicators_user(void); -void led_matrix_init(void); -void led_matrix_setup_drivers(void); - -void led_matrix_set_suspend_state(bool state); -void led_matrix_set_indicator_state(uint8_t state); +void led_matrix_indicators_advanced(effect_params_t *params); +void led_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max); +void led_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max); -void led_matrix_task(void); +void led_matrix_init(void); -// This should not be called from an interrupt -// (eg. from a timer interrupt). -// Call this while idle (in between matrix scans). -// If the buffer is dirty, it will update the driver with the buffer. -void led_matrix_update_pwm_buffers(void); - -bool process_led_matrix(uint16_t keycode, keyrecord_t *record); - -uint32_t led_matrix_get_tick(void); - -void led_matrix_toggle(void); -void led_matrix_enable(void); -void led_matrix_enable_noeeprom(void); -void led_matrix_disable(void); -void led_matrix_disable_noeeprom(void); -void led_matrix_step(void); -void led_matrix_step_reverse(void); -void led_matrix_increase_val(void); -void led_matrix_decrease_val(void); -void led_matrix_increase_speed(void); -void led_matrix_decrease_speed(void); -void led_matrix_mode(uint8_t mode, bool eeprom_write); -void led_matrix_mode_noeeprom(uint8_t mode); -uint8_t led_matrix_get_mode(void); -void led_matrix_set_value(uint8_t mode); -void led_matrix_set_value_noeeprom(uint8_t mode); +void led_matrix_set_suspend_state(bool state); +bool led_matrix_get_suspend_state(void); +void led_matrix_toggle(void); +void led_matrix_toggle_noeeprom(void); +void led_matrix_enable(void); +void led_matrix_enable_noeeprom(void); +void led_matrix_disable(void); +void led_matrix_disable_noeeprom(void); +uint8_t led_matrix_is_enabled(void); +void led_matrix_mode(uint8_t mode); +void led_matrix_mode_noeeprom(uint8_t mode); +uint8_t led_matrix_get_mode(void); +void led_matrix_step(void); +void led_matrix_step_noeeprom(void); +void led_matrix_step_reverse(void); +void led_matrix_step_reverse_noeeprom(void); +void led_matrix_set_val(uint8_t val); +void led_matrix_set_val_noeeprom(uint8_t val); +uint8_t led_matrix_get_val(void); +void led_matrix_increase_val(void); +void led_matrix_increase_val_noeeprom(void); +void led_matrix_decrease_val(void); +void led_matrix_decrease_val_noeeprom(void); +void led_matrix_set_speed(uint8_t speed); +void led_matrix_set_speed_noeeprom(uint8_t speed); +uint8_t led_matrix_get_speed(void); +void led_matrix_increase_speed(void); +void led_matrix_increase_speed_noeeprom(void); +void led_matrix_decrease_speed(void); +void led_matrix_decrease_speed_noeeprom(void); +led_flags_t led_matrix_get_flags(void); +void led_matrix_set_flags(led_flags_t flags); typedef struct { /* Perform any initialisation required for the other driver functions to work. */ @@ -91,4 +150,11 @@ extern const led_matrix_driver_t led_matrix_driver; extern led_eeconfig_t led_matrix_eeconfig; +extern uint32_t g_led_timer; extern led_config_t g_led_config; +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +extern last_hit_t g_last_hit_tracker; +#endif +#ifdef LED_MATRIX_FRAMEBUFFER_EFFECTS +extern uint8_t g_led_frame_buffer[MATRIX_ROWS][MATRIX_COLS]; +#endif diff --git a/quantum/led_matrix_animations/alpha_mods_anim.h b/quantum/led_matrix_animations/alpha_mods_anim.h new file mode 100644 index 0000000000..6f69f6892b --- /dev/null +++ b/quantum/led_matrix_animations/alpha_mods_anim.h @@ -0,0 +1,24 @@ +#ifndef DISABLE_LED_MATRIX_ALPHAS_MODS +LED_MATRIX_EFFECT(ALPHAS_MODS) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +// alphas = val1, mods = val2 +bool ALPHAS_MODS(effect_params_t* params) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + uint8_t val1 = led_matrix_eeconfig.val; + uint8_t val2 = val1 + led_matrix_eeconfig.speed; + + for (uint8_t i = led_min; i < led_max; i++) { + LED_MATRIX_TEST_LED_FLAGS(); + if (HAS_FLAGS(g_led_config.flags[i], LED_FLAG_MODIFIER)) { + led_matrix_set_value(i, val2); + } else { + led_matrix_set_value(i, val1); + } + } + return led_max < DRIVER_LED_TOTAL; +} + +# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif // DISABLE_LED_MATRIX_ALPHAS_MODS diff --git a/quantum/led_matrix_animations/band_anim.h b/quantum/led_matrix_animations/band_anim.h new file mode 100644 index 0000000000..523dba1b78 --- /dev/null +++ b/quantum/led_matrix_animations/band_anim.h @@ -0,0 +1,13 @@ +#ifndef DISABLE_LED_MATRIX_BAND +LED_MATRIX_EFFECT(BAND) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) { + int16_t v = val - abs(scale8(g_led_config.point[i].x, 228) + 28 - time) * 8; + return scale8(v < 0 ? 0 : v, val); +} + +bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); } + +# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif // DISABLE_LED_MATRIX_BAND diff --git a/quantum/led_matrix_animations/band_pinwheel_anim.h b/quantum/led_matrix_animations/band_pinwheel_anim.h new file mode 100644 index 0000000000..fb3b835cad --- /dev/null +++ b/quantum/led_matrix_animations/band_pinwheel_anim.h @@ -0,0 +1,10 @@ +#ifndef DISABLE_LED_MATRIX_BAND_PINWHEEL +LED_MATRIX_EFFECT(BAND_PINWHEEL) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t time) { return scale8(val - time - atan2_8(dy, dx) * 3, val); } + +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 diff --git a/quantum/led_matrix_animations/band_spiral_anim.h b/quantum/led_matrix_animations/band_spiral_anim.h new file mode 100644 index 0000000000..fca22aad9c --- /dev/null +++ b/quantum/led_matrix_animations/band_spiral_anim.h @@ -0,0 +1,10 @@ +#ifndef DISABLE_LED_MATRIX_BAND_SPIRAL +LED_MATRIX_EFFECT(BAND_SPIRAL) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { return scale8(val + dist - time - atan2_8(dy, dx), val); } + +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 diff --git a/quantum/led_matrix_animations/breathing_anim.h b/quantum/led_matrix_animations/breathing_anim.h new file mode 100644 index 0000000000..00310e3f65 --- /dev/null +++ b/quantum/led_matrix_animations/breathing_anim.h @@ -0,0 +1,19 @@ +#ifndef DISABLE_LED_MATRIX_BREATHING +LED_MATRIX_EFFECT(BREATHING) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +bool BREATHING(effect_params_t* params) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + uint8_t val = led_matrix_eeconfig.val; + uint16_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 8); + val = scale8(abs8(sin8(time) - 128) * 2, val); + for (uint8_t i = led_min; i < led_max; i++) { + LED_MATRIX_TEST_LED_FLAGS(); + led_matrix_set_value(i, val); + } + return led_max < DRIVER_LED_TOTAL; +} + +# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif // DISABLE_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 new file mode 100644 index 0000000000..51e81d57ca --- /dev/null +++ b/quantum/led_matrix_animations/cycle_left_right_anim.h @@ -0,0 +1,10 @@ +#ifndef DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT +LED_MATRIX_EFFECT(CYCLE_LEFT_RIGHT) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(g_led_config.point[i].x - time, val); } + +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 diff --git a/quantum/led_matrix_animations/cycle_out_in_anim.h b/quantum/led_matrix_animations/cycle_out_in_anim.h new file mode 100644 index 0000000000..f62061552c --- /dev/null +++ b/quantum/led_matrix_animations/cycle_out_in_anim.h @@ -0,0 +1,10 @@ +#ifndef DISABLE_LED_MATRIX_CYCLE_OUT_IN +LED_MATRIX_EFFECT(CYCLE_OUT_IN) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { return scale8(3 * dist / 2 + time, val); } + +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 diff --git a/quantum/led_matrix_animations/cycle_up_down_anim.h b/quantum/led_matrix_animations/cycle_up_down_anim.h new file mode 100644 index 0000000000..bd1d125672 --- /dev/null +++ b/quantum/led_matrix_animations/cycle_up_down_anim.h @@ -0,0 +1,10 @@ +#ifndef DISABLE_LED_MATRIX_CYCLE_UP_DOWN +LED_MATRIX_EFFECT(CYCLE_UP_DOWN) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(g_led_config.point[i].y - time, val); } + +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 diff --git a/quantum/led_matrix_animations/dual_beacon_anim.h b/quantum/led_matrix_animations/dual_beacon_anim.h new file mode 100644 index 0000000000..9b8a7877c9 --- /dev/null +++ b/quantum/led_matrix_animations/dual_beacon_anim.h @@ -0,0 +1,10 @@ +#ifndef DISABLE_LED_MATRIX_DUAL_BEACON +LED_MATRIX_EFFECT(DUAL_BEACON) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time) { return scale8(((g_led_config.point[i].y - k_led_matrix_center.y) * cos + (g_led_config.point[i].x - k_led_matrix_center.x) * sin) / 128, val); } + +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 diff --git a/quantum/led_matrix_animations/led_matrix_effects.inc b/quantum/led_matrix_animations/led_matrix_effects.inc new file mode 100644 index 0000000000..67237c5683 --- /dev/null +++ b/quantum/led_matrix_animations/led_matrix_effects.inc @@ -0,0 +1,18 @@ +// Add your new core led matrix effect here, order determins enum order, requires "led_matrix_animations/ directory +#include "led_matrix_animations/solid_anim.h" +#include "led_matrix_animations/alpha_mods_anim.h" +#include "led_matrix_animations/breathing_anim.h" +#include "led_matrix_animations/band_anim.h" +#include "led_matrix_animations/band_pinwheel_anim.h" +#include "led_matrix_animations/band_spiral_anim.h" +#include "led_matrix_animations/cycle_left_right_anim.h" +#include "led_matrix_animations/cycle_up_down_anim.h" +#include "led_matrix_animations/cycle_out_in_anim.h" +#include "led_matrix_animations/dual_beacon_anim.h" +#include "led_matrix_animations/solid_reactive_simple_anim.h" +#include "led_matrix_animations/solid_reactive_wide.h" +#include "led_matrix_animations/solid_reactive_cross.h" +#include "led_matrix_animations/solid_reactive_nexus.h" +#include "led_matrix_animations/solid_splash_anim.h" +#include "led_matrix_animations/wave_left_right_anim.h" +#include "led_matrix_animations/wave_up_down_anim.h" diff --git a/quantum/led_matrix_animations/solid_anim.h b/quantum/led_matrix_animations/solid_anim.h new file mode 100644 index 0000000000..4c9e43c581 --- /dev/null +++ b/quantum/led_matrix_animations/solid_anim.h @@ -0,0 +1,15 @@ +LED_MATRIX_EFFECT(SOLID) +#ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +bool SOLID(effect_params_t* params) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + uint8_t val = led_matrix_eeconfig.val; + for (uint8_t i = led_min; i < led_max; i++) { + LED_MATRIX_TEST_LED_FLAGS(); + led_matrix_set_value(i, val); + } + return led_max < DRIVER_LED_TOTAL; +} + +#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 new file mode 100644 index 0000000000..f402d99b37 --- /dev/null +++ b/quantum/led_matrix_animations/solid_reactive_cross.h @@ -0,0 +1,35 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) + +# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS +LED_MATRIX_EFFECT(SOLID_REACTIVE_CROSS) +# endif + +# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS +LED_MATRIX_EFFECT(SOLID_REACTIVE_MULTICROSS) +# endif + +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t SOLID_REACTIVE_CROSS_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { + uint16_t effect = tick + dist; + dx = dx < 0 ? dx * -1 : dx; + dy = dy < 0 ? dy * -1 : dy; + dx = dx * 16 > 255 ? 255 : dx * 16; + dy = dy * 16 > 255 ? 255 : dy * 16; + effect += dx > dy ? dy : dx; + if (effect > 255) effect = 255; + return qadd8(val, 255 - effect); +} + +# ifndef DISABLE_LED_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_LED_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 // LED_MATRIX_CUSTOM_EFFECT_IMPLS +# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_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 new file mode 100644 index 0000000000..4d0d252263 --- /dev/null +++ b/quantum/led_matrix_animations/solid_reactive_nexus.h @@ -0,0 +1,32 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) + +# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS +LED_MATRIX_EFFECT(SOLID_REACTIVE_NEXUS) +# endif + +# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS +LED_MATRIX_EFFECT(SOLID_REACTIVE_MULTINEXUS) +# endif + +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t SOLID_REACTIVE_NEXUS_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { + uint16_t effect = tick - dist; + if (effect > 255) effect = 255; + if (dist > 72) effect = 255; + if ((dx > 8 || dx < -8) && (dy > 8 || dy < -8)) effect = 255; + return qadd8(val, 255 - effect); +} + +# ifndef DISABLE_LED_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_LED_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 // LED_MATRIX_CUSTOM_EFFECT_IMPLS +# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_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 new file mode 100644 index 0000000000..30e2527f60 --- /dev/null +++ b/quantum/led_matrix_animations/solid_reactive_simple_anim.h @@ -0,0 +1,12 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE +LED_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { return scale8(255 - offset, val); } + +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 // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/solid_reactive_wide.h b/quantum/led_matrix_animations/solid_reactive_wide.h new file mode 100644 index 0000000000..34a230c259 --- /dev/null +++ b/quantum/led_matrix_animations/solid_reactive_wide.h @@ -0,0 +1,30 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) + +# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE +LED_MATRIX_EFFECT(SOLID_REACTIVE_WIDE) +# endif + +# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE +LED_MATRIX_EFFECT(SOLID_REACTIVE_MULTIWIDE) +# endif + +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t SOLID_REACTIVE_WIDE_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { + uint16_t effect = tick + dist * 5; + if (effect > 255) effect = 255; + return qadd8(val, 255 - effect); +} + +# ifndef DISABLE_LED_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_LED_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 // LED_MATRIX_CUSTOM_EFFECT_IMPLS +# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_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 new file mode 100644 index 0000000000..4f6ba3d343 --- /dev/null +++ b/quantum/led_matrix_animations/solid_splash_anim.h @@ -0,0 +1,30 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +# if !defined(DISABLE_LED_MATRIX_SOLID_SPLASH) || !defined(DISABLE_LED_MATRIX_SOLID_MULTISPLASH) + +# ifndef DISABLE_LED_MATRIX_SOLID_SPLASH +LED_MATRIX_EFFECT(SOLID_SPLASH) +# endif + +# ifndef DISABLE_LED_MATRIX_SOLID_MULTISPLASH +LED_MATRIX_EFFECT(SOLID_MULTISPLASH) +# endif + +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +uint8_t SOLID_SPLASH_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { + uint16_t effect = tick - dist; + if (effect > 255) effect = 255; + return qadd8(val, 255 - effect); +} + +# ifndef DISABLE_LED_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_LED_MATRIX_SOLID_MULTISPLASH +bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math); } +# endif + +# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS +# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_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 new file mode 100644 index 0000000000..736f22ddc5 --- /dev/null +++ b/quantum/led_matrix_animations/wave_left_right_anim.h @@ -0,0 +1,10 @@ +#ifndef DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT +LED_MATRIX_EFFECT(WAVE_LEFT_RIGHT) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(sin8(g_led_config.point[i].x - time), val); } + +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 diff --git a/quantum/led_matrix_animations/wave_up_down_anim.h b/quantum/led_matrix_animations/wave_up_down_anim.h new file mode 100644 index 0000000000..3cab0597d4 --- /dev/null +++ b/quantum/led_matrix_animations/wave_up_down_anim.h @@ -0,0 +1,10 @@ +#ifndef DISABLE_LED_MATRIX_WAVE_UP_DOWN +LED_MATRIX_EFFECT(WAVE_UP_DOWN) +# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(sin8(g_led_config.point[i].y - time), val); } + +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 diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix_drivers.c index eddf3f2863..1d46b2c506 100644 --- a/quantum/led_matrix_drivers.c +++ b/quantum/led_matrix_drivers.c @@ -15,9 +15,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <stdint.h> -#include <stdbool.h> -#include "quantum.h" #include "led_matrix.h" /* Each driver needs to define a struct: @@ -30,10 +27,6 @@ #if defined(IS31FL3731) || defined(IS31FL3733) -# if defined(IS31FL3731) -# include "is31fl3731-simple.h" -# endif - # include "i2c_master.h" static void init(void) { @@ -53,16 +46,28 @@ static void init(void) { # endif # else # ifdef LED_DRIVER_ADDR_1 - IS31FL3733_init(LED_DRIVER_ADDR_1, 0); +# ifndef LED_DRIVER_SYNC_1 +# define LED_DRIVER_SYNC_1 0 +# endif + IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1); # endif # ifdef LED_DRIVER_ADDR_2 - IS31FL3733_init(LED_DRIVER_ADDR_2, 0); +# ifndef 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 - IS31FL3733_init(LED_DRIVER_ADDR_3, 0); +# ifndef 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 - IS31FL3733_init(LED_DRIVER_ADDR_4, 0); +# ifndef LED_DRIVER_SYNC_4 +# define LED_DRIVER_SYNC_4 0 +# endif + IS31FL3733_init(LED_DRIVER_ADDR_4, LED_DRIVER_SYNC_4); # endif # endif diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy.h b/quantum/led_matrix_runners/effect_runner_dx_dy.h new file mode 100644 index 0000000000..ef97631b90 --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_dx_dy.h @@ -0,0 +1,16 @@ +#pragma once + +typedef uint8_t (*dx_dy_f)(uint8_t val, int16_t dx, int16_t dy, uint8_t time); + +bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + uint8_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 2); + for (uint8_t i = led_min; i < led_max; i++) { + LED_MATRIX_TEST_LED_FLAGS(); + int16_t dx = g_led_config.point[i].x - k_led_matrix_center.x; + 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; +} diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h new file mode 100644 index 0000000000..5ef5938be0 --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h @@ -0,0 +1,17 @@ +#pragma once + +typedef uint8_t (*dx_dy_dist_f)(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time); + +bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + uint8_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 2); + for (uint8_t i = led_min; i < led_max; i++) { + LED_MATRIX_TEST_LED_FLAGS(); + int16_t dx = g_led_config.point[i].x - k_led_matrix_center.x; + int16_t dy = g_led_config.point[i].y - k_led_matrix_center.y; + 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; +} diff --git a/quantum/led_matrix_runners/effect_runner_i.h b/quantum/led_matrix_runners/effect_runner_i.h new file mode 100644 index 0000000000..b3015759be --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_i.h @@ -0,0 +1,14 @@ +#pragma once + +typedef uint8_t (*i_f)(uint8_t val, uint8_t i, uint8_t time); + +bool effect_runner_i(effect_params_t* params, i_f effect_func) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + uint8_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 4); + for (uint8_t i = led_min; i < led_max; i++) { + LED_MATRIX_TEST_LED_FLAGS(); + led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, i, time)); + } + return led_max < DRIVER_LED_TOTAL; +} diff --git a/quantum/led_matrix_runners/effect_runner_reactive.h b/quantum/led_matrix_runners/effect_runner_reactive.h new file mode 100644 index 0000000000..4369ea8c49 --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_reactive.h @@ -0,0 +1,28 @@ +#pragma once + +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED + +typedef uint8_t (*reactive_f)(uint8_t val, uint16_t offset); + +bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + uint16_t max_tick = 65535 / led_matrix_eeconfig.speed; + for (uint8_t i = led_min; i < led_max; i++) { + LED_MATRIX_TEST_LED_FLAGS(); + uint16_t tick = max_tick; + // Reverse search to find most recent key hit + for (int8_t j = g_last_hit_tracker.count - 1; j >= 0; j--) { + if (g_last_hit_tracker.index[j] == i && g_last_hit_tracker.tick[j] < tick) { + tick = g_last_hit_tracker.tick[j]; + break; + } + } + + 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; +} + +#endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_runners/effect_runner_reactive_splash.h b/quantum/led_matrix_runners/effect_runner_reactive_splash.h new file mode 100644 index 0000000000..d6eb9731ee --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_reactive_splash.h @@ -0,0 +1,26 @@ +#pragma once + +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED + +typedef uint8_t (*reactive_splash_f)(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick); + +bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, reactive_splash_f effect_func) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + uint8_t count = g_last_hit_tracker.count; + for (uint8_t i = led_min; i < led_max; i++) { + LED_MATRIX_TEST_LED_FLAGS(); + uint8_t val = 0; + for (uint8_t j = start; j < count; j++) { + int16_t dx = g_led_config.point[i].x - g_last_hit_tracker.x[j]; + int16_t dy = g_led_config.point[i].y - g_last_hit_tracker.y[j]; + uint8_t dist = sqrt16(dx * dx + dy * dy); + uint16_t tick = scale16by8(g_last_hit_tracker.tick[j], led_matrix_eeconfig.speed); + val = effect_func(val, dx, dy, dist, tick); + } + led_matrix_set_value(i, scale8(val, led_matrix_eeconfig.val)); + } + return led_max < DRIVER_LED_TOTAL; +} + +#endif // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_runners/effect_runner_sin_cos_i.h b/quantum/led_matrix_runners/effect_runner_sin_cos_i.h new file mode 100644 index 0000000000..4a5219abd1 --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_sin_cos_i.h @@ -0,0 +1,16 @@ +#pragma once + +typedef uint8_t (*sin_cos_i_f)(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time); + +bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) { + LED_MATRIX_USE_LIMITS(led_min, led_max); + + uint16_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 4); + int8_t cos_value = cos8(time) - 128; + int8_t sin_value = sin8(time) - 128; + for (uint8_t i = led_min; i < led_max; i++) { + 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; +} diff --git a/quantum/led_matrix_types.h b/quantum/led_matrix_types.h index 669b67042b..61cdbd9b8e 100644 --- a/quantum/led_matrix_types.h +++ b/quantum/led_matrix_types.h @@ -29,15 +29,42 @@ # pragma pack(push, 1) #endif +#if defined(LED_MATRIX_KEYPRESSES) || defined(LED_MATRIX_KEYRELEASES) +# define LED_MATRIX_KEYREACTIVE_ENABLED +#endif + // Last led hit #ifndef LED_HITS_TO_REMEMBER # define LED_HITS_TO_REMEMBER 8 #endif // LED_HITS_TO_REMEMBER +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +typedef struct PACKED { + uint8_t count; + uint8_t x[LED_HITS_TO_REMEMBER]; + uint8_t y[LED_HITS_TO_REMEMBER]; + uint8_t index[LED_HITS_TO_REMEMBER]; + uint16_t tick[LED_HITS_TO_REMEMBER]; +} last_hit_t; +#endif // LED_MATRIX_KEYREACTIVE_ENABLED + +typedef enum led_task_states { STARTING, RENDERING, FLUSHING, SYNCING } led_task_states; + +typedef uint8_t led_flags_t; + +typedef struct PACKED { + uint8_t iter; + led_flags_t flags; + bool init; +} effect_params_t; + typedef struct PACKED { uint8_t x; uint8_t y; -} point_t; +} led_point_t; + +#define HAS_FLAGS(bits, flags) ((bits & flags) == flags) +#define HAS_ANY_FLAGS(bits, flags) ((bits & flags) != 0x00) #define LED_FLAG_ALL 0xFF #define LED_FLAG_NONE 0x00 @@ -48,19 +75,20 @@ typedef struct PACKED { #define NO_LED 255 typedef struct PACKED { - uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS]; - point_t point[DRIVER_LED_TOTAL]; - uint8_t flags[DRIVER_LED_TOTAL]; + uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS]; + led_point_t point[DRIVER_LED_TOTAL]; + uint8_t flags[DRIVER_LED_TOTAL]; } led_config_t; typedef union { uint32_t raw; struct PACKED { - uint8_t enable : 2; - uint8_t mode : 6; - uint16_t reserved; - uint8_t val; - uint8_t speed; // EECONFIG needs to be increased to support this + uint8_t enable : 2; + uint8_t mode : 6; + uint16_t reserved; + uint8_t val; + uint8_t speed; // EECONFIG needs to be increased to support this + led_flags_t flags; }; } led_eeconfig_t; diff --git a/quantum/matrix.c b/quantum/matrix.c index c027b7bf27..34d6af2e6d 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -116,9 +116,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) // Unselect row unselect_row(current_row); - if (current_row + 1 < MATRIX_ROWS) { - matrix_output_unselect_delay(); // wait for row signal to go HIGH - } + matrix_output_unselect_delay(); // wait for all Col signals to go HIGH // If the row has changed, store the row and return the changed flag. if (current_matrix[current_row] != current_row_value) { @@ -178,9 +176,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) // Unselect col unselect_col(current_col); - if (current_col + 1 < MATRIX_COLS) { - matrix_output_unselect_delay(); // wait for col signal to go HIGH - } + matrix_output_unselect_delay(); // wait for all Row signals to go HIGH return matrix_changed; } diff --git a/quantum/matrix.h b/quantum/matrix.h index ce57010a47..3fe691aaee 100644 --- a/quantum/matrix.h +++ b/quantum/matrix.h @@ -74,6 +74,11 @@ void matrix_scan_kb(void); void matrix_init_user(void); void matrix_scan_user(void); +#ifdef SPLIT_KEYBOARD +void matrix_slave_scan_kb(void); +void matrix_slave_scan_user(void); +#endif + #ifdef __cplusplus } #endif diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index f7329fc4d9..9268c4522e 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -81,6 +81,33 @@ ifneq ($(findstring MK20DX256, $(MCU)),) 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 @@ -112,6 +139,9 @@ ifneq ($(findstring STM32F042, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F0 endif ifneq ($(findstring STM32F072, $(MCU)),) @@ -145,6 +175,9 @@ ifneq ($(findstring STM32F072, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F0 endif ifneq ($(findstring STM32F103, $(MCU)),) @@ -178,6 +211,9 @@ ifneq ($(findstring STM32F103, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F1 endif ifneq ($(findstring STM32F303, $(MCU)),) @@ -211,6 +247,9 @@ ifneq ($(findstring STM32F303, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F3 endif ifneq ($(findstring STM32F401, $(MCU)),) @@ -244,6 +283,9 @@ ifneq ($(findstring STM32F401, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32F4 endif ifneq ($(findstring STM32F411, $(MCU)),) @@ -262,7 +304,12 @@ ifneq ($(findstring STM32F411, $(MCU)),) # Linker script to use # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ # or <keyboard_dir>/ld/ - MCU_LDSCRIPT ?= STM32F411xE + 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/ @@ -277,6 +324,43 @@ ifneq ($(findstring STM32F411, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # 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/ports/ARMCMx/compilers/GCC/ld/ + # or <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 + + # Options to pass to dfu-util when flashing + DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave + DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 endif ifneq ($(findstring STM32G431, $(MCU)),) @@ -310,6 +394,9 @@ ifneq ($(findstring STM32G431, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32G4 endif ifneq ($(findstring STM32G474, $(MCU)),) @@ -343,6 +430,47 @@ ifneq ($(findstring STM32G474, $(MCU)),) # Options to pass to dfu-util when flashing DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # 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/ports/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 + + # Options to pass to dfu-util when flashing + DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave + DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + + # UF2 settings + UF2_FAMILY ?= STM32L4 endif ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287)) diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c index 7fa4bad75a..5d8de56a37 100644 --- a/quantum/process_keycode/process_auto_shift.c +++ b/quantum/process_keycode/process_auto_shift.c @@ -216,7 +216,18 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { # endif } } + if (get_auto_shifted_key(keycode, record)) { + if (record->event.pressed) { + return autoshift_press(keycode, now, record); + } else { + autoshift_end(keycode, now, false); + return false; + } + } + return true; +} +__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { switch (keycode) { # ifndef NO_AUTO_SHIFT_ALPHA case KC_A ... KC_Z: @@ -231,14 +242,9 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { case KC_MINUS ... KC_SLASH: case KC_NONUS_BSLASH: # endif - if (record->event.pressed) { - return autoshift_press(keycode, now, record); - } else { - autoshift_end(keycode, now, false); - return false; - } + return true; } - return true; + return false; } #endif diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h index 5b2718f11c..00a9ab036f 100644 --- a/quantum/process_keycode/process_auto_shift.h +++ b/quantum/process_keycode/process_auto_shift.h @@ -31,3 +31,4 @@ bool get_autoshift_state(void); uint16_t get_autoshift_timeout(void); void set_autoshift_timeout(uint16_t timeout); void autoshift_matrix_scan(void); +bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_backlight.c b/quantum/process_keycode/process_backlight.c index 4d12f6813a..8b70339a55 100644 --- a/quantum/process_keycode/process_backlight.c +++ b/quantum/process_keycode/process_backlight.c @@ -16,11 +16,35 @@ #include "process_backlight.h" -#include "backlight.h" +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#else +# include "backlight.h" +#endif bool process_backlight(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { switch (keycode) { +#ifdef LED_MATRIX_ENABLE + case BL_ON: + led_matrix_enable(); + return false; + case BL_OFF: + led_matrix_disable(); + return false; + case BL_DEC: + led_matrix_decrease_val(); + return false; + case BL_INC: + led_matrix_increase_val(); + return false; + case BL_TOGG: + led_matrix_toggle(); + return false; + case BL_STEP: + led_matrix_step(); + return false; +#else case BL_ON: backlight_level(BACKLIGHT_LEVELS); return false; @@ -39,10 +63,11 @@ bool process_backlight(uint16_t keycode, keyrecord_t *record) { case BL_STEP: backlight_step(); return false; -#ifdef BACKLIGHT_BREATHING +# ifdef BACKLIGHT_BREATHING case BL_BRTG: backlight_toggle_breathing(); return false; +# endif #endif } } diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c index 58a615d85a..cf63f25141 100644 --- a/quantum/process_keycode/process_leader.c +++ b/quantum/process_keycode/process_leader.c @@ -49,7 +49,10 @@ bool process_leader(uint16_t keycode, keyrecord_t *record) { // Leader key set-up if (record->event.pressed) { if (leading) { - if (timer_elapsed(leader_time) < LEADER_TIMEOUT) { +# ifndef LEADER_NO_TIMEOUT + if (timer_elapsed(leader_time) < LEADER_TIMEOUT) +# endif // LEADER_NO_TIMEOUT + { # ifndef LEADER_KEY_STRICT_KEY_PROCESSING if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { keycode = keycode & 0xFF; diff --git a/quantum/process_keycode/process_leader.h b/quantum/process_keycode/process_leader.h index 9844f27a1b..f3fe14a432 100644 --- a/quantum/process_keycode/process_leader.h +++ b/quantum/process_keycode/process_leader.h @@ -35,4 +35,9 @@ void qk_leader_start(void); extern uint16_t leader_time; \ extern uint16_t leader_sequence[5]; \ extern uint8_t leader_sequence_size -#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT) + +#ifdef LEADER_NO_TIMEOUT +# define LEADER_DICTIONARY() if (leading && leader_sequence_size > 0 && timer_elapsed(leader_time) > LEADER_TIMEOUT) +#else +# define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT) +#endif diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c index 5dd8e7809d..167c0c03c9 100644 --- a/quantum/process_keycode/process_rgb.c +++ b/quantum/process_keycode/process_rgb.c @@ -207,6 +207,11 @@ bool process_rgb(const uint16_t keycode, const keyrecord_t *record) { rgblight_mode(RGBLIGHT_MODE_RGB_TEST); #endif return false; + case RGB_MODE_TWINKLE: +#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_TWINKLE) + handleKeycodeRGBMode(RGBLIGHT_MODE_TWINKLE, RGBLIGHT_MODE_TWINKLE_end); +#endif + return false; } } diff --git a/quantum/quantum.c b/quantum/quantum.c index d5d97f3242..a9f5f5d95f 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -16,6 +16,7 @@ #include <ctype.h> #include "quantum.h" +#include "magic.h" #ifdef BLUETOOTH_ENABLE # include "outputselect.h" @@ -236,7 +237,7 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef AUDIO_ENABLE process_audio(keycode, record) && #endif -#ifdef BACKLIGHT_ENABLE +#if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE) process_backlight(keycode, record) && #endif #ifdef STENO_ENABLE @@ -321,6 +322,17 @@ bool process_record_quantum(keyrecord_t *record) { set_output(OUTPUT_BLUETOOTH); return false; #endif +#ifndef NO_ACTION_ONESHOT + case ONESHOT_TOGGLE: + oneshot_toggle(); + break; + case ONESHOT_ENABLE: + oneshot_enable(); + break; + case ONESHOT_DISABLE: + oneshot_disable(); + break; +#endif } } @@ -345,29 +357,26 @@ layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_ void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) { layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3)); } void matrix_init_quantum() { -#ifdef BOOTMAGIC_LITE - bootmagic_lite(); -#endif - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } + + magic(); + #if defined(ORYX_ENABLE) && defined(DYNAMIC_KEYMAP_ENABLE) matrix_init_oryx(); #endif + #if defined(LED_NUM_LOCK_PIN) || defined(LED_CAPS_LOCK_PIN) || defined(LED_SCROLL_LOCK_PIN) || defined(LED_COMPOSE_PIN) || defined(LED_KANA_PIN) // TODO: remove calls to led_init_ports from keyboards and remove ifdef led_init_ports(); #endif #ifdef BACKLIGHT_ENABLE -# ifdef LED_MATRIX_ENABLE - led_matrix_init(); -# else backlight_init_ports(); -# endif #endif #ifdef AUDIO_ENABLE audio_init(); #endif +#ifdef LED_MATRIX_ENABLE + led_matrix_init(); +#endif #ifdef RGB_MATRIX_ENABLE rgb_matrix_init(); #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index a5ed1b66bd..9df15d4cac 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -30,11 +30,11 @@ #include "keymap.h" #ifdef BACKLIGHT_ENABLE -# ifdef LED_MATRIX_ENABLE -# include "led_matrix.h" -# else -# include "backlight.h" -# endif +# include "backlight.h" +#endif + +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" #endif #if defined(RGBLIGHT_ENABLE) @@ -52,6 +52,7 @@ #include "action_layer.h" #include "eeconfig.h" #include "bootloader.h" +#include "bootmagic.h" #include "timer.h" #include "sync_timer.h" #include "config_common.h" @@ -97,7 +98,7 @@ extern layer_state_t layer_state; # include "process_music.h" #endif -#ifdef BACKLIGHT_ENABLE +#if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE) # include "process_backlight.h" #endif @@ -209,37 +210,8 @@ extern layer_state_t layer_state; # include "usbpd.h" #endif -// Function substitutions to ease GPIO manipulation -#if defined(__AVR__) - -/* The AVR series GPIOs have a one clock read delay for changes in the digital input signal. - * But here's more margin to make it two clocks. */ -# if !defined(GPIO_INPUT_PIN_DELAY) -# define GPIO_INPUT_PIN_DELAY 2 -# endif -# define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) - -#elif defined(__ARMEL__) || defined(__ARMEB__) - -/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus - * to which the GPIO is connected. - * The connected buses differ depending on the various series of MCUs. - * And since the instruction execution clock of the CPU and the bus clock of GPIO are different, - * there is a delay of several clocks to read the change of the input signal. - * - * Define this delay with the GPIO_INPUT_PIN_DELAY macro. - * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. - * (A fairly large value of 0.25 microseconds is set.) - */ -# if !defined(GPIO_INPUT_PIN_DELAY) -# if defined(STM32_SYSCLK) -# define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) -# elif defined(KINETIS_SYSCLK_FREQUENCY) -# define GPIO_INPUT_PIN_DELAY (KINETIS_SYSCLK_FREQUENCY / 1000000L / 4) -# endif -# endif -# define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) - +#ifdef ENCODER_ENABLE +# include "encoder.h" #endif // For tri-layer @@ -266,15 +238,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record); void post_process_record_kb(uint16_t keycode, keyrecord_t *record); void post_process_record_user(uint16_t keycode, keyrecord_t *record); -#ifndef BOOTMAGIC_LITE_COLUMN -# define BOOTMAGIC_LITE_COLUMN 0 -#endif -#ifndef BOOTMAGIC_LITE_ROW -# define BOOTMAGIC_LITE_ROW 0 -#endif - -void bootmagic_lite(void); - void reset_keyboard(void); void startup_user(void); diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 97d200c8cf..0ab3a535df 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -16,19 +16,7 @@ #pragma once -#if defined(SEQUENCER_ENABLE) -# include "sequencer.h" -#endif - -#ifndef MIDI_ENABLE_STRICT -# define MIDI_ENABLE_STRICT 0 -#endif - -#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)) -# ifndef MIDI_TONE_KEYCODE_OCTAVES -# define MIDI_TONE_KEYCODE_OCTAVES 3 -# endif -#endif +#include "sequencer.h" // Fillers to make layering more clear #define _______ KC_TRNS @@ -67,6 +55,8 @@ enum quantum_keycodes { QK_ONE_SHOT_LAYER_MAX = 0x54FF, QK_ONE_SHOT_MOD = 0x5500, QK_ONE_SHOT_MOD_MAX = 0x55FF, + QK_SWAP_HANDS = 0x5600, + QK_SWAP_HANDS_MAX = 0x56FF, QK_TAP_DANCE = 0x5700, QK_TAP_DANCE_MAX = 0x57FF, QK_LAYER_TAP_TOGGLE = 0x5800, @@ -77,509 +67,460 @@ enum quantum_keycodes { QK_STENO_BOLT = 0x5A30, QK_STENO_GEMINI = 0x5A31, QK_STENO_MAX = 0x5A3F, - QK_SWAP_HANDS = 0x5B00, - QK_SWAP_HANDS_MAX = 0x5BFF, - QK_MOD_TAP = 0x6000, - QK_MOD_TAP_MAX = 0x7FFF, - QK_UNICODE = 0x8000, - QK_UNICODE_MAX = 0xFFFF, - QK_UNICODEMAP = 0x8000, - QK_UNICODEMAP_MAX = 0xBFFF, - QK_UNICODEMAP_PAIR = 0xC000, - QK_UNICODEMAP_PAIR_MAX = 0xFFFF, + // 0x5C00 - 0x5FFF are reserved, see below + QK_MOD_TAP = 0x6000, + QK_MOD_TAP_MAX = 0x7FFF, + QK_UNICODE = 0x8000, + QK_UNICODE_MAX = 0xFFFF, + QK_UNICODEMAP = 0x8000, + QK_UNICODEMAP_MAX = 0xBFFF, + QK_UNICODEMAP_PAIR = 0xC000, + QK_UNICODEMAP_PAIR_MAX = 0xFFFF, // Loose keycodes - to be used directly RESET = 0x5C00, - DEBUG, - MAGIC_SWAP_CONTROL_CAPSLOCK, - MAGIC_CAPSLOCK_TO_CONTROL, - MAGIC_SWAP_LALT_LGUI, - MAGIC_SWAP_RALT_RGUI, - MAGIC_NO_GUI, - MAGIC_SWAP_GRAVE_ESC, - MAGIC_SWAP_BACKSLASH_BACKSPACE, - MAGIC_HOST_NKRO, - MAGIC_SWAP_ALT_GUI, - MAGIC_UNSWAP_CONTROL_CAPSLOCK, - MAGIC_UNCAPSLOCK_TO_CONTROL, - MAGIC_UNSWAP_LALT_LGUI, - MAGIC_UNSWAP_RALT_RGUI, - MAGIC_UNNO_GUI, - MAGIC_UNSWAP_GRAVE_ESC, - MAGIC_UNSWAP_BACKSLASH_BACKSPACE, - MAGIC_UNHOST_NKRO, - MAGIC_UNSWAP_ALT_GUI, - MAGIC_TOGGLE_NKRO, - MAGIC_TOGGLE_ALT_GUI, - GRAVE_ESC, - -// Leader key -#ifdef LEADER_ENABLE - KC_LEAD, -#endif - -// Auto Shift setup -#ifndef AUTO_SHIFT_NO_SETUP - KC_ASUP, - KC_ASDN, - KC_ASRP, -#endif - KC_ASTG, - KC_ASON, - KC_ASOFF, - - // Audio on/off/toggle - AU_ON, - AU_OFF, - AU_TOG, - - // Faux clicky as part of main audio feature - CLICKY_TOGGLE, - CLICKY_ENABLE, - CLICKY_DISABLE, - CLICKY_UP, - CLICKY_DOWN, - CLICKY_RESET, - - // Music mode on/off/toggle - MU_ON, - MU_OFF, - MU_TOG, - - // Music mode cycle - MU_MOD, - - // Music voice iterate - MUV_IN, - MUV_DE, - -// Midi -#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) - MI_ON, - MI_OFF, - MI_TOG, -#endif - -#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)) - MIDI_TONE_MIN, - -# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 0 - MI_C = MIDI_TONE_MIN, - MI_Cs, + DEBUG, // 5C01 + + // Magic + MAGIC_SWAP_CONTROL_CAPSLOCK, // 5C02 + MAGIC_CAPSLOCK_TO_CONTROL, // 5C03 + MAGIC_SWAP_LALT_LGUI, // 5C04 + MAGIC_SWAP_RALT_RGUI, // 5C05 + MAGIC_NO_GUI, // 5C06 + MAGIC_SWAP_GRAVE_ESC, // 5C07 + MAGIC_SWAP_BACKSLASH_BACKSPACE, // 5C08 + MAGIC_HOST_NKRO, // 5C09 + MAGIC_SWAP_ALT_GUI, // 5C0A + MAGIC_UNSWAP_CONTROL_CAPSLOCK, // 5C0B + MAGIC_UNCAPSLOCK_TO_CONTROL, // 5C0C + MAGIC_UNSWAP_LALT_LGUI, // 5C0D + MAGIC_UNSWAP_RALT_RGUI, // 5C0E + MAGIC_UNNO_GUI, // 5C0F + MAGIC_UNSWAP_GRAVE_ESC, // 5C10 + MAGIC_UNSWAP_BACKSLASH_BACKSPACE, // 5C11 + MAGIC_UNHOST_NKRO, // 5C12 + MAGIC_UNSWAP_ALT_GUI, // 5C13 + MAGIC_TOGGLE_NKRO, // 5C14 + MAGIC_TOGGLE_ALT_GUI, // 5C15 + + // Grave Escape + GRAVE_ESC, // 5C16 + + // Auto Shift + KC_ASUP, // 5C17 + KC_ASDN, // 5C18 + KC_ASRP, // 5C19 + KC_ASTG, // 5C1A + KC_ASON, // 5C1B + KC_ASOFF, // 5C1C + + // Audio + AU_ON, // 5C1D + AU_OFF, // 5C1E + AU_TOG, // 5C1F + + // Audio Clicky + CLICKY_TOGGLE, // 5C20 + CLICKY_ENABLE, // 5C21 + CLICKY_DISABLE, // 5C22 + CLICKY_UP, // 5C23 + CLICKY_DOWN, // 5C24 + CLICKY_RESET, // 5C25 + + // Music mode + MU_ON, // 5C26 + MU_OFF, // 5C27 + MU_TOG, // 5C28 + MU_MOD, // 5C29 + MUV_IN, // 5C2A + MUV_DE, // 5C2B + + // MIDI + MI_ON, // 5C2C + MI_OFF, // 5C2D + MI_TOG, // 5C2E + + MI_C, // 5C2F + MI_Cs, // 5C30 MI_Db = MI_Cs, - MI_D, - MI_Ds, + MI_D, // 5C31 + MI_Ds, // 5C32 MI_Eb = MI_Ds, - MI_E, - MI_F, - MI_Fs, + MI_E, // 5C33 + MI_F, // 5C34 + MI_Fs, // 5C35 MI_Gb = MI_Fs, - MI_G, - MI_Gs, + MI_G, // 5C36 + MI_Gs, // 5C37 MI_Ab = MI_Gs, - MI_A, - MI_As, + MI_A, // 5C38 + MI_As, // 5C39 MI_Bb = MI_As, - MI_B, -# endif + MI_B, // 5C3A -# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 1 - MI_C_1, - MI_Cs_1, + MI_C_1, // 5C3B + MI_Cs_1, // 5C3C MI_Db_1 = MI_Cs_1, - MI_D_1, - MI_Ds_1, + MI_D_1, // 5C3D + MI_Ds_1, // 5C3E MI_Eb_1 = MI_Ds_1, - MI_E_1, - MI_F_1, - MI_Fs_1, + MI_E_1, // 5C3F + MI_F_1, // 5C40 + MI_Fs_1, // 5C41 MI_Gb_1 = MI_Fs_1, - MI_G_1, - MI_Gs_1, + MI_G_1, // 5C42 + MI_Gs_1, // 5C43 MI_Ab_1 = MI_Gs_1, - MI_A_1, - MI_As_1, + MI_A_1, // 5C44 + MI_As_1, // 5C45 MI_Bb_1 = MI_As_1, - MI_B_1, -# endif + MI_B_1, // 5C46 -# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 2 - MI_C_2, - MI_Cs_2, + MI_C_2, // 5C47 + MI_Cs_2, // 5C48 MI_Db_2 = MI_Cs_2, - MI_D_2, - MI_Ds_2, + MI_D_2, // 5C49 + MI_Ds_2, // 5C4A MI_Eb_2 = MI_Ds_2, - MI_E_2, - MI_F_2, - MI_Fs_2, + MI_E_2, // 5C4B + MI_F_2, // 5C4C + MI_Fs_2, // 5C4D MI_Gb_2 = MI_Fs_2, - MI_G_2, - MI_Gs_2, + MI_G_2, // 5C4E + MI_Gs_2, // 5C4F MI_Ab_2 = MI_Gs_2, - MI_A_2, - MI_As_2, + MI_A_2, // 5C50 + MI_As_2, // 5C51 MI_Bb_2 = MI_As_2, - MI_B_2, -# endif + MI_B_2, // 5C52 -# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 3 - MI_C_3, - MI_Cs_3, + MI_C_3, // 5C53 + MI_Cs_3, // 5C54 MI_Db_3 = MI_Cs_3, - MI_D_3, - MI_Ds_3, + MI_D_3, // 5C55 + MI_Ds_3, // 5C56 MI_Eb_3 = MI_Ds_3, - MI_E_3, - MI_F_3, - MI_Fs_3, + MI_E_3, // 5C57 + MI_F_3, // 5C58 + MI_Fs_3, // 5C59 MI_Gb_3 = MI_Fs_3, - MI_G_3, - MI_Gs_3, + MI_G_3, // 5C5A + MI_Gs_3, // 5C5B MI_Ab_3 = MI_Gs_3, - MI_A_3, - MI_As_3, + MI_A_3, // 5C5C + MI_As_3, // 5C5D MI_Bb_3 = MI_As_3, - MI_B_3, -# endif + MI_B_3, // 5C5E -# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 4 - MI_C_4, - MI_Cs_4, + MI_C_4, // 5C5F + MI_Cs_4, // 5C60 MI_Db_4 = MI_Cs_4, - MI_D_4, - MI_Ds_4, + MI_D_4, // 5C61 + MI_Ds_4, // 5C62 MI_Eb_4 = MI_Ds_4, - MI_E_4, - MI_F_4, - MI_Fs_4, + MI_E_4, // 5C63 + MI_F_4, // 5C64 + MI_Fs_4, // 5C65 MI_Gb_4 = MI_Fs_4, - MI_G_4, - MI_Gs_4, + MI_G_4, // 5C66 + MI_Gs_4, // 5C67 MI_Ab_4 = MI_Gs_4, - MI_A_4, - MI_As_4, + MI_A_4, // 5C68 + MI_As_4, // 5C69 MI_Bb_4 = MI_As_4, - MI_B_4, -# endif + MI_B_4, // 5C6A -# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5 - MI_C_5, - MI_Cs_5, + MI_C_5, // 5C6B + MI_Cs_5, // 5C6C MI_Db_5 = MI_Cs_5, - MI_D_5, - MI_Ds_5, + MI_D_5, // 5C6D + MI_Ds_5, // 5C6E MI_Eb_5 = MI_Ds_5, - MI_E_5, - MI_F_5, - MI_Fs_5, + MI_E_5, // 5C6F + MI_F_5, // 5C70 + MI_Fs_5, // 5C71 MI_Gb_5 = MI_Fs_5, - MI_G_5, - MI_Gs_5, + MI_G_5, // 5C72 + MI_Gs_5, // 5C73 MI_Ab_5 = MI_Gs_5, - MI_A_5, - MI_As_5, + MI_A_5, // 5C74 + MI_As_5, // 5C75 MI_Bb_5 = MI_As_5, - MI_B_5, -# endif - -# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5 - MIDI_TONE_MAX = MI_B_5, -# elif MIDI_TONE_KEYCODE_OCTAVES > 4 - MIDI_TONE_MAX = MI_B_4, -# elif MIDI_TONE_KEYCODE_OCTAVES > 3 - MIDI_TONE_MAX = MI_B_3, -# elif MIDI_TONE_KEYCODE_OCTAVES > 2 - MIDI_TONE_MAX = MI_B_2, -# elif MIDI_TONE_KEYCODE_OCTAVES > 1 - MIDI_TONE_MAX = MI_B_1, -# elif MIDI_TONE_KEYCODE_OCTAVES > 0 - MIDI_TONE_MAX = MI_B, -# endif - - MIDI_OCTAVE_MIN, - MI_OCT_N2 = MIDI_OCTAVE_MIN, - MI_OCT_N1, - MI_OCT_0, - MI_OCT_1, - MI_OCT_2, - MI_OCT_3, - MI_OCT_4, - MI_OCT_5, - MI_OCT_6, - MI_OCT_7, - MIDI_OCTAVE_MAX = MI_OCT_7, - MI_OCTD, // octave down - MI_OCTU, // octave up - - MIDI_TRANSPOSE_MIN, - MI_TRNS_N6 = MIDI_TRANSPOSE_MIN, - MI_TRNS_N5, - MI_TRNS_N4, - MI_TRNS_N3, - MI_TRNS_N2, - MI_TRNS_N1, - MI_TRNS_0, - MI_TRNS_1, - MI_TRNS_2, - MI_TRNS_3, - MI_TRNS_4, - MI_TRNS_5, - MI_TRNS_6, - MIDI_TRANSPOSE_MAX = MI_TRNS_6, - MI_TRNSD, // transpose down - MI_TRNSU, // transpose up - - MIDI_VELOCITY_MIN, - MI_VEL_0 = MIDI_VELOCITY_MIN, -# ifdef VIA_ENABLE - MI_VEL_1 = MIDI_VELOCITY_MIN, -# else - MI_VEL_1, -# endif - MI_VEL_2, - MI_VEL_3, - MI_VEL_4, - MI_VEL_5, - MI_VEL_6, - MI_VEL_7, - MI_VEL_8, - MI_VEL_9, - MI_VEL_10, - MIDI_VELOCITY_MAX = MI_VEL_10, - MI_VELD, // velocity down - MI_VELU, // velocity up - - MIDI_CHANNEL_MIN, - MI_CH1 = MIDI_CHANNEL_MIN, - MI_CH2, - MI_CH3, - MI_CH4, - MI_CH5, - MI_CH6, - MI_CH7, - MI_CH8, - MI_CH9, - MI_CH10, - MI_CH11, - MI_CH12, - MI_CH13, - MI_CH14, - MI_CH15, - MI_CH16, - MIDI_CHANNEL_MAX = MI_CH16, - MI_CHD, // previous channel - MI_CHU, // next channel - - MI_ALLOFF, // all notes off - - MI_SUS, // sustain - MI_PORT, // portamento - MI_SOST, // sostenuto - MI_SOFT, // soft pedal - MI_LEG, // legato - - MI_MOD, // modulation - MI_MODSD, // decrease modulation speed - MI_MODSU, // increase modulation speed - - MI_BENDD, // Bend down - MI_BENDU, // Bend up -#endif // MIDI_ADVANCED - - // Backlight functionality - BL_ON, - BL_OFF, - BL_DEC, - BL_INC, - BL_TOGG, - BL_STEP, - BL_BRTG, - - // RGB functionality - RGB_TOG, - RGB_MODE_FORWARD, - RGB_MODE_REVERSE, - RGB_HUI, - RGB_HUD, - RGB_SAI, - RGB_SAD, - RGB_VAI, - RGB_VAD, - RGB_SPI, - RGB_SPD, - RGB_MODE_PLAIN, - RGB_MODE_BREATHE, - RGB_MODE_RAINBOW, - RGB_MODE_SWIRL, - RGB_MODE_SNAKE, - RGB_MODE_KNIGHT, - RGB_MODE_XMAS, - RGB_MODE_GRADIENT, - RGB_MODE_RGBTEST, - - // Momentum matching toggle - VLK_TOG, - - // Left shift, open paren - KC_LSPO, - - // Right shift, close paren - KC_RSPC, - - // Shift, Enter - KC_SFTENT, - - // Printing - PRINT_ON, - PRINT_OFF, - - // output selection - OUT_AUTO, - OUT_USB, -#ifdef BLUETOOTH_ENABLE - OUT_BT, -#endif - -#ifdef KEY_LOCK_ENABLE - KC_LOCK, + MI_B_5, // 5C76 + + MI_OCT_N2, // 5C77 + MI_OCT_N1, // 5C78 + MI_OCT_0, // 5C79 + MI_OCT_1, // 5C7A + MI_OCT_2, // 5C7B + MI_OCT_3, // 5C7C + MI_OCT_4, // 5C7D + MI_OCT_5, // 5C7E + MI_OCT_6, // 5C7F + MI_OCT_7, // 5C80 + MI_OCTD, // 5C81 + MI_OCTU, // 5C82 + + MI_TRNS_N6, // 5C83 + MI_TRNS_N5, // 5C84 + MI_TRNS_N4, // 5C85 + MI_TRNS_N3, // 5C86 + MI_TRNS_N2, // 5C87 + MI_TRNS_N1, // 5C88 + MI_TRNS_0, // 5C89 + MI_TRNS_1, // 5C8A + MI_TRNS_2, // 5C8B + MI_TRNS_3, // 5C8C + MI_TRNS_4, // 5C8D + MI_TRNS_5, // 5C8E + MI_TRNS_6, // 5C8F + MI_TRNSD, // 5C90 + MI_TRNSU, // 5C91 + + MI_VEL_0, // 5C92 +#ifdef VIA_ENABLE + MI_VEL_1 = MI_VEL_0, +#else + MI_VEL_1, // 5C93 #endif - -#ifdef TERMINAL_ENABLE - TERM_ON, - TERM_OFF, -#endif - - EEPROM_RESET, - - UNICODE_MODE_FORWARD, - UNICODE_MODE_REVERSE, - UNICODE_MODE_MAC, - UNICODE_MODE_LNX, - UNICODE_MODE_WIN, - UNICODE_MODE_BSD, - UNICODE_MODE_WINC, - - HPT_ON, - HPT_OFF, - HPT_TOG, - HPT_RST, - HPT_FBK, - HPT_BUZ, - HPT_MODI, - HPT_MODD, - HPT_CONT, - HPT_CONI, - HPT_COND, - HPT_DWLI, - HPT_DWLD, - - // Left control, open paren - KC_LCPO, - - // Right control, close paren - KC_RCPC, - - // Left control, open paren - KC_LAPO, - - // Right control, close paren - KC_RAPC, - - CMB_ON, - CMB_OFF, - CMB_TOG, - - MAGIC_SWAP_LCTL_LGUI, - MAGIC_SWAP_RCTL_RGUI, - MAGIC_UNSWAP_LCTL_LGUI, - MAGIC_UNSWAP_RCTL_RGUI, - MAGIC_SWAP_CTL_GUI, - MAGIC_UNSWAP_CTL_GUI, - MAGIC_TOGGLE_CTL_GUI, - MAGIC_EE_HANDS_LEFT, - MAGIC_EE_HANDS_RIGHT, + MI_VEL_2, // 5C94 + MI_VEL_3, // 5C95 + MI_VEL_4, // 5C96 + MI_VEL_5, // 5C97 + MI_VEL_6, // 5C98 + MI_VEL_7, // 5C99 + MI_VEL_8, // 5C9A + MI_VEL_9, // 5C9B + MI_VEL_10, // 5C9C + MI_VELD, // 5C9D + MI_VELU, // 5C9E + + MI_CH1, // 5C9F + MI_CH2, // 5CA0 + MI_CH3, // 5CA1 + MI_CH4, // 5CA2 + MI_CH5, // 5CA3 + MI_CH6, // 5CA4 + MI_CH7, // 5CA5 + MI_CH8, // 5CA6 + MI_CH9, // 5CA7 + MI_CH10, // 5CA8 + MI_CH11, // 5CA9 + MI_CH12, // 5CAA + MI_CH13, // 5CAB + MI_CH14, // 5CAC + MI_CH15, // 5CAD + MI_CH16, // 5CAE + MI_CHD, // 5CAF + MI_CHU, // 5CB0 + + MI_ALLOFF, // 5CB1 + + MI_SUS, // 5CB2 + MI_PORT, // 5CB3 + MI_SOST, // 5CB4 + MI_SOFT, // 5CB5 + MI_LEG, // 5CB6 + + MI_MOD, // 5CB7 + MI_MODSD, // 5CB8 + MI_MODSU, // 5CB9 + + MI_BENDD, // 5CBA + MI_BENDU, // 5CBB + + // Backlight + BL_ON, // 5CBC + BL_OFF, // 5CBD + BL_DEC, // 5CBE + BL_INC, // 5CBF + BL_TOGG, // 5CC0 + BL_STEP, // 5CC1 + BL_BRTG, // 5CC2 + + // RGB underglow/matrix + RGB_TOG, // 5CC3 + RGB_MODE_FORWARD, // 5CC4 + RGB_MODE_REVERSE, // 5CC5 + RGB_HUI, // 5CC6 + RGB_HUD, // 5CC7 + RGB_SAI, // 5CC8 + RGB_SAD, // 5CC9 + RGB_VAI, // 5CCA + RGB_VAD, // 5CCB + RGB_SPI, // 5CCC + RGB_SPD, // 5CCD + RGB_MODE_PLAIN, // 5CCE + RGB_MODE_BREATHE, // 5CCF + RGB_MODE_RAINBOW, // 5CD0 + RGB_MODE_SWIRL, // 5CD1 + RGB_MODE_SNAKE, // 5CD2 + RGB_MODE_KNIGHT, // 5CD3 + RGB_MODE_XMAS, // 5CD4 + RGB_MODE_GRADIENT, // 5CD5 + RGB_MODE_RGBTEST, // 5CD6 + + // Velocikey + VLK_TOG, // 5CD7 + + // Space Cadet + KC_LSPO, // 5CD8 + KC_RSPC, // 5CD9 + KC_SFTENT, // 5CDA + + // Thermal Printer + PRINT_ON, // 5CDB + PRINT_OFF, // 5CDC + + // Bluetooth: output selection + OUT_AUTO, // 5CDD + OUT_USB, // 5CDE + + // Clear EEPROM + EEPROM_RESET, // 5CDF + + // Unicode + UNICODE_MODE_FORWARD, // 5CE0 + UNICODE_MODE_REVERSE, // 5CE1 + UNICODE_MODE_MAC, // 5CE2 + UNICODE_MODE_LNX, // 5CE3 + UNICODE_MODE_WIN, // 5CE4 + UNICODE_MODE_BSD, // 5CE5 + UNICODE_MODE_WINC, // 5CE6 + + // Haptic + HPT_ON, // 5CE7 + HPT_OFF, // 5CE8 + HPT_TOG, // 5CE9 + HPT_RST, // 5CEA + HPT_FBK, // 5CEB + HPT_BUZ, // 5CEC + HPT_MODI, // 5CED + HPT_MODD, // 5CEE + HPT_CONT, // 5CEF + HPT_CONI, // 5CF0 + HPT_COND, // 5CF1 + HPT_DWLI, // 5CF2 + HPT_DWLD, // 5CF3 + + // Space Cadet (continued) + KC_LCPO, // 5CF4 + KC_RCPC, // 5CF5 + KC_LAPO, // 5CF6 + KC_RAPC, // 5CF7 + + // Combos + CMB_ON, // 5CF8 + CMB_OFF, // 5CF9 + CMB_TOG, // 5CFA + + // Magic (continued) + MAGIC_SWAP_LCTL_LGUI, // 5CFB + MAGIC_SWAP_RCTL_RGUI, // 5CFC + MAGIC_UNSWAP_LCTL_LGUI, // 5CFD + MAGIC_UNSWAP_RCTL_RGUI, // 5CFE + MAGIC_SWAP_CTL_GUI, // 5CFF + MAGIC_UNSWAP_CTL_GUI, // 5D00 + MAGIC_TOGGLE_CTL_GUI, // 5D01 + MAGIC_EE_HANDS_LEFT, // 5D02 + MAGIC_EE_HANDS_RIGHT, // 5D03 // Dynamic Macros - DYN_REC_START1, - DYN_REC_START2, - DYN_REC_STOP, - DYN_MACRO_PLAY1, - DYN_MACRO_PLAY2, + DYN_REC_START1, // 5D04 + DYN_REC_START2, // 5D05 + DYN_REC_STOP, // 5D06 + DYN_MACRO_PLAY1, // 5D07 + DYN_MACRO_PLAY2, // 5D08 WEBUSB_PAIR, - JS_BUTTON0, - JS_BUTTON_MIN = JS_BUTTON0, - JS_BUTTON1, - JS_BUTTON2, - JS_BUTTON3, - JS_BUTTON4, - JS_BUTTON5, - JS_BUTTON6, - JS_BUTTON7, - JS_BUTTON8, - JS_BUTTON9, - JS_BUTTON10, - JS_BUTTON11, - JS_BUTTON12, - JS_BUTTON13, - JS_BUTTON14, - JS_BUTTON15, - JS_BUTTON16, - JS_BUTTON17, - JS_BUTTON18, - JS_BUTTON19, - JS_BUTTON20, - JS_BUTTON21, - JS_BUTTON22, - JS_BUTTON23, - JS_BUTTON24, - JS_BUTTON25, - JS_BUTTON26, - JS_BUTTON27, - JS_BUTTON28, - JS_BUTTON29, - JS_BUTTON30, - JS_BUTTON31, - JS_BUTTON_MAX = JS_BUTTON31, - -#if defined(SEQUENCER_ENABLE) - SQ_ON, - SQ_OFF, - SQ_TOG, - - SQ_TMPD, // Decrease tempo - SQ_TMPU, // Increase tempo + // Joystick + JS_BUTTON0, // 5D09 + JS_BUTTON1, // 5D0A + JS_BUTTON2, // 5D0B + JS_BUTTON3, // 5D0C + JS_BUTTON4, // 5D0D + JS_BUTTON5, // 5D0E + JS_BUTTON6, // 5D0F + JS_BUTTON7, // 5D10 + JS_BUTTON8, // 5D11 + JS_BUTTON9, // 5D12 + JS_BUTTON10, // 5D13 + JS_BUTTON11, // 5D14 + JS_BUTTON12, // 5D15 + JS_BUTTON13, // 5D16 + JS_BUTTON14, // 5D17 + JS_BUTTON15, // 5D18 + JS_BUTTON16, // 5D19 + JS_BUTTON17, // 5D1A + JS_BUTTON18, // 5D1B + JS_BUTTON19, // 5D1C + JS_BUTTON20, // 5D1D + JS_BUTTON21, // 5D1E + JS_BUTTON22, // 5D1F + JS_BUTTON23, // 5D20 + JS_BUTTON24, // 5D21 + JS_BUTTON25, // 5D22 + JS_BUTTON26, // 5D23 + JS_BUTTON27, // 5D24 + JS_BUTTON28, // 5D25 + JS_BUTTON29, // 5D26 + JS_BUTTON30, // 5D27 + JS_BUTTON31, // 5D28 + + // Leader Key + KC_LEAD, // 5D29 + + // Bluetooth: output selection (continued) + OUT_BT, // 5D2A + + // Lock Key + KC_LOCK, // 5D2B + + // Terminal + TERM_ON, // 5D2C + TERM_OFF, // 5D2D + + // Sequencer + SQ_ON, // 5D2E + SQ_OFF, // 5D2F + SQ_TOG, // 5D30 + + SQ_TMPD, // 5D31 + SQ_TMPU, // 5D32 + + SQ_RESD, // 5D33 + SQ_RESU, // 5D34 + + SQ_SALL, // 5D35 + SQ_SCLR, // 5D36 + + SEQUENCER_STEP_MIN, // 5D37 + SEQUENCER_STEP_MAX = SEQUENCER_STEP_MIN + SEQUENCER_STEPS, SEQUENCER_RESOLUTION_MIN, SEQUENCER_RESOLUTION_MAX = SEQUENCER_RESOLUTION_MIN + SEQUENCER_RESOLUTIONS, - SQ_RESD, // Decrease resolution - SQ_RESU, // Increase resolution - - SQ_SALL, // All steps on - SQ_SCLR, // All steps off - SEQUENCER_STEP_MIN, - SEQUENCER_STEP_MAX = SEQUENCER_STEP_MIN + SEQUENCER_STEPS, SEQUENCER_TRACK_MIN, SEQUENCER_TRACK_MAX = SEQUENCER_TRACK_MIN + SEQUENCER_TRACKS, -/** - * Helpers to assign a keycode to a step, a resolution, or a track. - * Falls back to NOOP if n is out of range. - */ -# define SQ_S(n) (n < SEQUENCER_STEPS ? SEQUENCER_STEP_MIN + n : XXXXXXX) -# define SQ_R(n) (n < SEQUENCER_RESOLUTIONS ? SEQUENCER_RESOLUTION_MIN + n : XXXXXXX) -# define SQ_T(n) (n < SEQUENCER_TRACKS ? SEQUENCER_TRACK_MIN + n : XXXXXXX) +#define SQ_S(n) (n < SEQUENCER_STEPS ? SEQUENCER_STEP_MIN + n : KC_NO) +#define SQ_R(n) (n < SEQUENCER_RESOLUTIONS ? SEQUENCER_RESOLUTION_MIN + n : KC_NO) +#define SQ_T(n) (n < SEQUENCER_TRACKS ? SEQUENCER_TRACK_MIN + n : KC_NO) -#endif + // One Shot + ONESHOT_ENABLE, + ONESHOT_DISABLE, + ONESHOT_TOGGLE, + + // RGB underglow/matrix (continued) + RGB_MODE_TWINKLE, - // always leave at the end + // Start of custom keycode range for keyboards and keymaps - always leave at the end SAFE_RANGE }; -// Ability to use mods in layouts +// Keycode modifiers & aliases #define LCTL(kc) (QK_LCTL | (kc)) #define LSFT(kc) (QK_LSFT | (kc)) #define LALT(kc) (QK_LALT | (kc)) @@ -599,9 +540,13 @@ enum quantum_keycodes { #define HYPR(kc) (QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI | (kc)) #define MEH(kc) (QK_LCTL | QK_LSFT | QK_LALT | (kc)) #define LCAG(kc) (QK_LCTL | QK_LALT | QK_LGUI | (kc)) -#define SGUI(kc) (QK_LGUI | QK_LSFT | (kc)) -#define SCMD(kc) SGUI(kc) -#define SWIN(kc) SGUI(kc) +#define LSG(kc) (QK_LSFT | QK_LGUI | (kc)) +#define SGUI(kc) LSG(kc) +#define SCMD(kc) LSG(kc) +#define SWIN(kc) LSG(kc) +#define LAG(kc) (QK_LALT | QK_LGUI | (kc)) +#define RSG(kc) (QK_RSFT | QK_RGUI | (kc)) +#define RAG(kc) (QK_RALT | QK_RGUI | (kc)) #define LCA(kc) (QK_LCTL | QK_LALT | (kc)) #define LSA(kc) (QK_LSFT | QK_LALT | (kc)) #define RSA(kc) (QK_RSFT | QK_RALT | (kc)) @@ -611,11 +556,7 @@ enum quantum_keycodes { #define MOD_HYPR 0xF #define MOD_MEH 0x7 -// Aliases for shifted symbols -// Each key has a 4-letter code, and some have longer aliases too. -// While the long aliases are descriptive, the 4-letter codes -// make for nicer grid layouts (everything lines up), and are -// the preferred style for Quantum. +// US ANSI shifted keycode aliases #define KC_TILD LSFT(KC_GRV) // ~ #define KC_TILDE KC_TILD @@ -682,18 +623,15 @@ enum quantum_keycodes { #define KC_DELT KC_DELETE // Del key (four letter code) -// Alias for function layers than expand past FN31 -#define FUNC(kc) (QK_FUNCTION | (kc)) - -// Aliases +// Modified keycode aliases #define C(kc) LCTL(kc) #define S(kc) LSFT(kc) #define A(kc) LALT(kc) #define G(kc) LGUI(kc) -#define F(kc) FUNC(kc) +// Deprecated - do not use +#define F(kc) (QK_FUNCTION | (kc)) #define M(kc) (QK_MACRO | (kc)) - #define MACROTAP(kc) (QK_MACRO | (FUNC_TAP << 8) | (kc)) #define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE) @@ -701,19 +639,21 @@ enum quantum_keycodes { #define EEP_RST EEPROM_RESET +// Audio Clicky aliases #define CK_TOGG CLICKY_TOGGLE #define CK_RST CLICKY_RESET #define CK_UP CLICKY_UP #define CK_DOWN CLICKY_DOWN #define CK_ON CLICKY_ENABLE #define CK_OFF CLICKY_DISABLE +// Fauxclicky (deprecated) redirects to Audio Clicky #define FC_ON CLICKY_ENABLE #define FC_OFF CLICKY_DISABLE #define FC_TOGG CLICKY_TOGGLE +// RGB aliases #define RGB_MOD RGB_MODE_FORWARD #define RGB_RMOD RGB_MODE_REVERSE - #define RGB_M_P RGB_MODE_PLAIN #define RGB_M_B RGB_MODE_BREATHE #define RGB_M_R RGB_MODE_RAINBOW @@ -723,10 +663,9 @@ enum quantum_keycodes { #define RGB_M_X RGB_MODE_XMAS #define RGB_M_G RGB_MODE_GRADIENT #define RGB_M_T RGB_MODE_RGBTEST +#define RGB_M_TW RGB_MODE_TWINKLE -// L-ayer, T-ap - 256 keycode max, 16 layer max -#define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF)) - +// Magic aliases #define CL_SWAP MAGIC_SWAP_CONTROL_CAPSLOCK #define CL_NORM MAGIC_UNSWAP_CONTROL_CAPSLOCK #define CL_CTRL MAGIC_CAPSLOCK_TO_CONTROL @@ -795,6 +734,9 @@ enum quantum_keycodes { // Layer tap-toggle #define TT(layer) (QK_LAYER_TAP_TOGGLE | ((layer)&0xFF)) +// L-ayer, T-ap - 256 keycode max, 16 layer max +#define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF)) + // M-od, T-ap - 256 keycode max #define MT(mod, kc) (QK_MOD_TAP | (((mod)&0x1F) << 8) | ((kc)&0xFF)) @@ -824,14 +766,18 @@ enum quantum_keycodes { #define CMD_T(kc) LCMD_T(kc) #define WIN_T(kc) LWIN_T(kc) -#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal -#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt -#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI -#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI +#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal +#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt +#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI +#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI #define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/ -#define SGUI_T(kc) MT(MOD_LGUI | MOD_LSFT, kc) // Left Shift + GUI -#define SCMD_T(kc) SGUI_T(kc) -#define SWIN_T(kc) SGUI_T(kc) +#define LSG_T(kc) MT(MOD_LSFT | MOD_LGUI, kc) // Left Shift + GUI +#define SGUI_T(kc) LSG_T(kc) +#define SCMD_T(kc) LSG_T(kc) +#define SWIN_T(kc) LSG_T(kc) +#define LAG_T(kc) MT(MOD_LALT | MOD_LGUI, kc) // Left Alt + GUI +#define RSG_T(kc) MT(MOD_RSFT | MOD_RGUI, kc) // Right Shift + GUI +#define RAG_T(kc) MT(MOD_RALT | MOD_RGUI, kc) // Right Alt + GUI #define LCA_T(kc) MT(MOD_LCTL | MOD_LALT, kc) // Left Control + Alt #define LSA_T(kc) MT(MOD_LSFT | MOD_LALT, kc) // Left Shift + Alt #define RSA_T(kc) MT(MOD_RSFT | MOD_RALT, kc) // Right Shift + Alt @@ -844,6 +790,7 @@ enum quantum_keycodes { #define KC_HYPR HYPR(KC_NO) #define KC_MEH MEH(KC_NO) +// Unicode aliases // UNICODE_ENABLE - Allows Unicode input up to 0x7FFF #define UC(c) (QK_UNICODE | (c)) // UNICODEMAP_ENABLE - Allows Unicode input up to 0x10FFFF, requires unicode_map @@ -855,12 +802,13 @@ enum quantum_keycodes { #define UC_M_MA UNICODE_MODE_MAC #define UNICODE_MODE_OSX UNICODE_MODE_MAC // Deprecated alias -#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias +#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias #define UC_M_LN UNICODE_MODE_LNX #define UC_M_WI UNICODE_MODE_WIN #define UC_M_BS UNICODE_MODE_BSD #define UC_M_WC UNICODE_MODE_WINC +// Swap Hands #define SH_T(kc) (QK_SWAP_HANDS | (kc)) #define SH_TG (QK_SWAP_HANDS | OP_SH_TOGGLE) #define SH_TT (QK_SWAP_HANDS | OP_SH_TAP_TOGGLE) @@ -870,9 +818,30 @@ enum quantum_keycodes { #define SH_ON (QK_SWAP_HANDS | OP_SH_ON) #define SH_OFF (QK_SWAP_HANDS | OP_SH_OFF) +// MIDI aliases +#define MIDI_TONE_MIN MI_C +#define MIDI_TONE_MAX MI_B_5 +#define MIDI_OCTAVE_MIN MI_OCT_N2 +#define MIDI_OCTAVE_MAX MI_OCT_7 +#define MIDI_TRANSPOSE_MIN MI_TRNS_N6 +#define MIDI_TRANSPOSE_MAX MI_TRNS_6 +#define MIDI_VELOCITY_MIN MI_VEL_0 +#define MIDI_VELOCITY_MAX MI_VEL_10 +#define MIDI_CHANNEL_MIN MI_CH1 +#define MIDI_CHANNEL_MAX MI_CH16 + // Dynamic Macros aliases #define DM_REC1 DYN_REC_START1 #define DM_REC2 DYN_REC_START2 #define DM_RSTP DYN_REC_STOP #define DM_PLY1 DYN_MACRO_PLAY1 #define DM_PLY2 DYN_MACRO_PLAY2 + +// Joystick aliases +#define JS_BUTTON_MIN JS_BUTTON0 +#define JS_BUTTON_MAX JS_BUTTON31 + +// One Shot aliases +#define OS_TOGG ONESHOT_TOGGLE +#define OS_ON ONESHOT_ENABLE +#define OS_OFF ONESHOT_DISABLE diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index ec17b4d72c..ab8dbd849b 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -26,9 +26,9 @@ #include <lib/lib8tion/lib8tion.h> #ifndef RGB_MATRIX_CENTER -const point_t k_rgb_matrix_center = {112, 32}; +const led_point_t k_rgb_matrix_center = {112, 32}; #else -const point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; +const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; #endif __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } @@ -67,8 +67,8 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv # define RGB_DISABLE_TIMEOUT 0 #endif -#ifndef RGB_DISABLE_WHEN_USB_SUSPENDED -# define RGB_DISABLE_WHEN_USB_SUSPENDED false +#if RGB_DISABLE_WHEN_USB_SUSPENDED != 1 +# undef RGB_DISABLE_WHEN_USB_SUSPENDED #endif #if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX @@ -118,7 +118,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv #endif // globals -bool g_suspend_state = false; rgb_config_t rgb_matrix_config; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr uint32_t g_rgb_timer; #ifdef RGB_MATRIX_FRAMEBUFFER_EFFECTS @@ -129,9 +128,10 @@ last_hit_t g_last_hit_tracker; #endif // RGB_MATRIX_KEYREACTIVE_ENABLED // internals +static bool suspend_state = 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, 0xFF}; +static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; static rgb_task_states rgb_task_state = SYNCING; #if RGB_DISABLE_TIMEOUT > 0 static uint32_t rgb_anykey_timer; @@ -143,6 +143,11 @@ static uint32_t rgb_timer_buffer; static last_hit_t last_hit_buffer; #endif // RGB_MATRIX_KEYREACTIVE_ENABLED +// split rgb matrix +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +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)); } void eeconfig_update_rgb_matrix(void) { eeprom_update_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } @@ -153,6 +158,7 @@ void eeconfig_update_rgb_matrix_default(void) { rgb_matrix_config.mode = RGB_MATRIX_STARTUP_MODE; 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(); } @@ -164,6 +170,7 @@ void eeconfig_debug_rgb_matrix(void) { dprintf("rgb_matrix_config.hsv.s = %d\n", rgb_matrix_config.hsv.s); dprintf("rgb_matrix_config.hsv.v = %d\n", rgb_matrix_config.hsv.v); dprintf("rgb_matrix_config.speed = %d\n", rgb_matrix_config.speed); + dprintf("rgb_matrix_config.flags = %d\n", rgb_matrix_config.flags); } __attribute__((weak)) uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; } @@ -180,9 +187,22 @@ 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) { 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) { +#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_all(uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color_all(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) + for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) rgb_matrix_set_color(i, red, green, blue); +#else + rgb_matrix_driver.set_color_all(red, green, blue); +#endif +} void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed) { #ifndef RGB_MATRIX_SPLIT @@ -315,6 +335,10 @@ static void rgb_task_start(void) { static void rgb_task_render(uint8_t effect) { bool rendering = false; rgb_effect_params.init = (effect != rgb_last_effect) || (rgb_matrix_config.enable != rgb_last_enable); + if (rgb_effect_params.flags != rgb_matrix_config.flags) { + rgb_effect_params.flags = rgb_matrix_config.flags; + rgb_matrix_set_color_all(0, 0, 0); + } // each effect can opt to do calculations // and/or request PWM buffer updates. @@ -385,14 +409,11 @@ void rgb_matrix_task(void) { // Ideally we would also stop sending zeros to the LED driver PWM buffers // while suspended and just do a software shutdown. This is a cheap hack for now. - bool suspend_backlight = -#if RGB_DISABLE_WHEN_USB_SUSPENDED == true - g_suspend_state || -#endif // RGB_DISABLE_WHEN_USB_SUSPENDED == true + bool suspend_backlight = suspend_state || #if RGB_DISABLE_TIMEOUT > 0 - (rgb_anykey_timer > (uint32_t)RGB_DISABLE_TIMEOUT) || + (rgb_anykey_timer > (uint32_t)RGB_DISABLE_TIMEOUT) || #endif // RGB_DISABLE_TIMEOUT > 0 - false; + false; uint8_t effect = suspend_backlight || !rgb_matrix_config.enable ? 0 : rgb_matrix_config.mode; @@ -477,13 +498,15 @@ void rgb_matrix_init(void) { } void rgb_matrix_set_suspend_state(bool state) { - if (RGB_DISABLE_WHEN_USB_SUSPENDED && state) { +#ifdef RGB_DISABLE_WHEN_USB_SUSPENDED + if (state) { rgb_matrix_set_color_all(0, 0, 0); // turn off all LEDs when suspending } - g_suspend_state = state; + suspend_state = state; +#endif } -bool rgb_matrix_get_suspend_state(void) { return g_suspend_state; } +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; @@ -618,6 +641,6 @@ void rgb_matrix_decrease_speed_helper(bool write_to_eeprom) { rgb_matrix_set_spe void rgb_matrix_decrease_speed_noeeprom(void) { rgb_matrix_decrease_speed_helper(false); } void rgb_matrix_decrease_speed(void) { rgb_matrix_decrease_speed_helper(true); } -led_flags_t rgb_matrix_get_flags(void) { return rgb_effect_params.flags; } +led_flags_t rgb_matrix_get_flags(void) { return rgb_matrix_config.flags; } -void rgb_matrix_set_flags(led_flags_t flags) { rgb_effect_params.flags = flags; } +void rgb_matrix_set_flags(led_flags_t flags) { rgb_matrix_config.flags = flags; } diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h index bb8bcfab68..a615b8422c 100644 --- a/quantum/rgb_matrix.h +++ b/quantum/rgb_matrix.h @@ -216,7 +216,6 @@ extern const rgb_matrix_driver_t rgb_matrix_driver; extern rgb_config_t rgb_matrix_config; -extern bool g_suspend_state; extern uint32_t g_rgb_timer; extern led_config_t g_led_config; #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix_drivers.c b/quantum/rgb_matrix_drivers.c index 2978e7bed9..896fa6d0ef 100644 --- a/quantum/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix_drivers.c @@ -41,7 +41,28 @@ static void init(void) { IS31FL3731_init(DRIVER_ADDR_4); # endif # elif defined(IS31FL3733) - IS31FL3733_init(DRIVER_ADDR_1, 0); +# ifndef 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 +# 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 + IS31FL3733_init(DRIVER_ADDR_3, DRIVER_SYNC_3); +# endif +# ifdef DRIVER_ADDR_4 +# ifndef DRIVER_SYNC_4 +# define DRIVER_SYNC_4 0 +# endif + IS31FL3733_init(DRIVER_ADDR_4, DRIVER_SYNC_4); +# endif # elif defined(IS31FL3737) IS31FL3737_init(DRIVER_ADDR_1); # else @@ -74,7 +95,15 @@ static void init(void) { # endif # elif defined(IS31FL3733) IS31FL3733_update_led_control_registers(DRIVER_ADDR_1, 0); +# ifdef DRIVER_ADDR_2 IS31FL3733_update_led_control_registers(DRIVER_ADDR_2, 1); +# endif +# ifdef DRIVER_ADDR_3 + IS31FL3733_update_led_control_registers(DRIVER_ADDR_3, 2); +# endif +# ifdef DRIVER_ADDR_4 + IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3); +# endif # elif defined(IS31FL3737) IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, DRIVER_ADDR_2); # else @@ -105,7 +134,15 @@ const rgb_matrix_driver_t rgb_matrix_driver = { # elif defined(IS31FL3733) static void flush(void) { IS31FL3733_update_pwm_buffers(DRIVER_ADDR_1, 0); +# ifdef DRIVER_ADDR_2 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_2, 1); +# endif +# ifdef DRIVER_ADDR_3 + IS31FL3733_update_pwm_buffers(DRIVER_ADDR_3, 2); +# endif +# ifdef DRIVER_ADDR_4 + IS31FL3733_update_pwm_buffers(DRIVER_ADDR_4, 3); +# endif } const rgb_matrix_driver_t rgb_matrix_driver = { diff --git a/quantum/rgb_matrix_runners/effect_runner_i.h b/quantum/rgb_matrix_runners/effect_runner_i.h index 95bfe8b390..1881cd6c60 100644 --- a/quantum/rgb_matrix_runners/effect_runner_i.h +++ b/quantum/rgb_matrix_runners/effect_runner_i.h @@ -5,7 +5,7 @@ typedef HSV (*i_f)(HSV hsv, uint8_t i, uint8_t time); bool effect_runner_i(effect_params_t* params, i_f effect_func) { RGB_MATRIX_USE_LIMITS(led_min, led_max); - uint8_t time = scale16by8(g_rgb_timer, rgb_matrix_config.speed / 4); + uint8_t time = scale16by8(g_rgb_timer, qadd8(rgb_matrix_config.speed / 4, 1)); for (uint8_t i = led_min; i < led_max; i++) { RGB_MATRIX_TEST_LED_FLAGS(); RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, i, time)); diff --git a/quantum/rgb_matrix_runners/effect_runner_reactive.h b/quantum/rgb_matrix_runners/effect_runner_reactive.h index 8485b61f3d..75b7c0df4e 100644 --- a/quantum/rgb_matrix_runners/effect_runner_reactive.h +++ b/quantum/rgb_matrix_runners/effect_runner_reactive.h @@ -7,7 +7,7 @@ typedef HSV (*reactive_f)(HSV hsv, uint16_t offset); bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) { RGB_MATRIX_USE_LIMITS(led_min, led_max); - uint16_t max_tick = 65535 / rgb_matrix_config.speed; + uint16_t max_tick = 65535 / qadd8(rgb_matrix_config.speed, 1); for (uint8_t i = led_min; i < led_max; i++) { RGB_MATRIX_TEST_LED_FLAGS(); uint16_t tick = max_tick; @@ -19,7 +19,7 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) { } } - uint16_t offset = scale16by8(tick, rgb_matrix_config.speed); + uint16_t offset = scale16by8(tick, qadd8(rgb_matrix_config.speed, 1)); 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); } diff --git a/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h b/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h index 5c69d0fbb9..2e46ffb350 100644 --- a/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h +++ b/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h @@ -16,7 +16,7 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react int16_t dx = g_led_config.point[i].x - g_last_hit_tracker.x[j]; int16_t dy = g_led_config.point[i].y - g_last_hit_tracker.y[j]; uint8_t dist = sqrt16(dx * dx + dy * dy); - uint16_t tick = scale16by8(g_last_hit_tracker.tick[j], rgb_matrix_config.speed); + uint16_t tick = scale16by8(g_last_hit_tracker.tick[j], qadd8(rgb_matrix_config.speed, 1)); hsv = effect_func(hsv, dx, dy, dist, tick); } hsv.v = scale8(hsv.v, rgb_matrix_config.hsv.v); diff --git a/quantum/rgb_matrix_types.h b/quantum/rgb_matrix_types.h index 7b8171fb23..df575d6577 100644 --- a/quantum/rgb_matrix_types.h +++ b/quantum/rgb_matrix_types.h @@ -62,7 +62,7 @@ typedef struct PACKED { typedef struct PACKED { uint8_t x; uint8_t y; -} point_t; +} led_point_t; #define HAS_FLAGS(bits, flags) ((bits & flags) == flags) #define HAS_ANY_FLAGS(bits, flags) ((bits & flags) != 0x00) @@ -77,18 +77,19 @@ typedef struct PACKED { #define NO_LED 255 typedef struct PACKED { - uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS]; - point_t point[DRIVER_LED_TOTAL]; - uint8_t flags[DRIVER_LED_TOTAL]; + uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS]; + led_point_t point[DRIVER_LED_TOTAL]; + uint8_t flags[DRIVER_LED_TOTAL]; } led_config_t; typedef union { uint32_t raw; struct PACKED { - uint8_t enable : 2; - uint8_t mode : 6; - HSV hsv; - uint8_t speed; // EECONFIG needs to be increased to support this + uint8_t enable : 2; + uint8_t mode : 6; + HSV hsv; + uint8_t speed; // EECONFIG needs to be increased to support this + led_flags_t flags; }; } rgb_config_t; diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 119d3eab21..baa10ec416 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -722,23 +722,39 @@ static void rgblight_layers_write(void) { } # ifdef RGBLIGHT_LAYER_BLINK -rgblight_layer_mask_t _blinked_layer_mask = 0; -static uint16_t _blink_timer; +rgblight_layer_mask_t _blinking_layer_mask = 0; +static uint16_t _repeat_timer; +static uint8_t _times_remaining; +static uint16_t _dur; + +void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { rgblight_blink_layer_repeat(layer, duration_ms, 1); } + +void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times) { + _times_remaining = times * 2; + _dur = duration_ms; -void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { rgblight_set_layer_state(layer, true); - _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; - _blink_timer = sync_timer_read() + duration_ms; + _times_remaining--; + _blinking_layer_mask |= (rgblight_layer_mask_t)1 << layer; + _repeat_timer = sync_timer_read() + duration_ms; } -void rgblight_unblink_layers(void) { - if (_blinked_layer_mask != 0 && timer_expired(sync_timer_read(), _blink_timer)) { +void rgblight_blink_layer_repeat_helper(void) { + if (_blinking_layer_mask != 0 && timer_expired(sync_timer_read(), _repeat_timer)) { for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { - if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) { - rgblight_set_layer_state(layer, false); + if ((_blinking_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0 && _times_remaining > 0) { + if (_times_remaining % 2 == 1) { + rgblight_set_layer_state(layer, false); + } else { + rgblight_set_layer_state(layer, true); + } + _times_remaining--; + _repeat_timer = sync_timer_read() + _dur; } } - _blinked_layer_mask = 0; + if (_times_remaining <= 0) { + _blinking_layer_mask = 0; + } } } # endif @@ -755,8 +771,8 @@ void rgblight_suspend(void) { # ifdef RGBLIGHT_LAYER_BLINK // make sure any layer blinks don't come back after suspend - rgblight_status.enabled_layer_mask &= ~_blinked_layer_mask; - _blinked_layer_mask = 0; + rgblight_status.enabled_layer_mask &= ~_blinking_layer_mask; + _blinking_layer_mask = 0; # endif rgblight_disable_noeeprom(); @@ -874,7 +890,7 @@ void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) { animation_status.restart = true; } # endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ -# endif /* RGBLIGHT_USE_TIMER */ +# endif /* RGBLIGHT_USE_TIMER */ } #endif /* RGBLIGHT_SPLIT */ @@ -1030,7 +1046,7 @@ void rgblight_task(void) { } # ifdef RGBLIGHT_LAYER_BLINK - rgblight_unblink_layers(); + rgblight_blink_layer_repeat_helper(); # endif } diff --git a/quantum/rgblight.h b/quantum/rgblight.h index 6fb3ab9380..bec2c66955 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -222,6 +222,7 @@ extern const rgblight_segment_t *const *rgblight_layers; # ifdef RGBLIGHT_LAYER_BLINK # define RGBLIGHT_USE_TIMER void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms); +void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times); # endif # endif diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index d6636b886a..039e7d9773 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -43,6 +43,7 @@ extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values uint8_t thisHand, thatHand; // user-defined overridable functions +__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); } __attribute__((weak)) void matrix_slave_scan_user(void) {} static inline void setPinOutput_writeLow(pin_t pin) { @@ -129,9 +130,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) // Unselect row unselect_row(current_row); - if (current_row + 1 < MATRIX_ROWS) { - matrix_output_unselect_delay(); // wait for row signal to go HIGH - } + matrix_output_unselect_delay(); // wait for all Col signals to go HIGH // If the row has changed, store the row and return the changed flag. if (current_matrix[current_row] != current_row_value) { @@ -191,9 +190,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) // Unselect col unselect_col(current_col); - if (current_col + 1 < MATRIX_COLS) { - matrix_output_unselect_delay(); // wait for col signal to go HIGH - } + matrix_output_unselect_delay(); // wait for all Row signals to go HIGH return matrix_changed; } @@ -284,7 +281,7 @@ bool matrix_post_scan(void) { } else { transport_slave(matrix + thatHand, matrix + thisHand); - matrix_slave_scan_user(); + matrix_slave_scan_kb(); } return changed; diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 2ae44e6e15..9e75e19ce0 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -1,3 +1,18 @@ +/* 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 3 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 "split_util.h" #include "matrix.h" #include "keyboard.h" @@ -6,14 +21,7 @@ #include "transport.h" #include "quantum.h" #include "wait.h" - -#ifdef PROTOCOL_LUFA -# include <LUFA/Drivers/USB/USB.h> -#endif - -#ifdef PROTOCOL_VUSB -# include <usbdrv/usbdrv.h> -#endif +#include "usb_util.h" #ifdef EE_HANDS # include "eeconfig.h" @@ -31,56 +39,21 @@ # define SPLIT_USB_TIMEOUT_POLL 10 #endif -#ifdef PROTOCOL_CHIBIOS -# define SPLIT_USB_DETECT // Force this on for now -#endif - volatile bool isLeftHand = true; #if defined(SPLIT_USB_DETECT) -# if defined(PROTOCOL_LUFA) -static inline bool usbHasActiveConnection(void) { return USB_Device_IsAddressSet(); } -static inline void usbDisable(void) { - USB_Disable(); - USB_DeviceState = DEVICE_STATE_Unattached; -} -# elif defined(PROTOCOL_CHIBIOS) -static inline bool usbHasActiveConnection(void) { return usbGetDriverStateI(&USBD1) == USB_ACTIVE; } -static inline void usbDisable(void) { usbStop(&USBD1); } -# elif defined(PROTOCOL_VUSB) -static inline bool usbHasActiveConnection(void) { - usbPoll(); - return usbConfiguration; -} -static inline void usbDisable(void) { usbDeviceDisconnect(); } -# else -static inline bool usbHasActiveConnection(void) { return true; } -static inline void usbDisable(void) {} -# endif - -bool usbIsActive(void) { +static bool usbIsActive(void) { for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) { // This will return true if a USB connection has been established - if (usbHasActiveConnection()) { + if (usb_connected_state()) { return true; } wait_ms(SPLIT_USB_TIMEOUT_POLL); } - - // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow - usbDisable(); - return false; } -#elif defined(PROTOCOL_LUFA) && defined(OTGPADE) -static inline bool usbIsActive(void) { - USB_OTGPAD_On(); // enables VBUS pad - wait_us(5); - - return USB_VBUS_GetStatus(); // checks state of VBUS -} #else -static inline bool usbIsActive(void) { return true; } +static inline bool usbIsActive(void) { return usb_vbus_state(); } #endif #ifdef SPLIT_HAND_MATRIX_GRID @@ -126,6 +99,11 @@ __attribute__((weak)) bool is_keyboard_master(void) { // only check once, as this is called often if (usbstate == UNKNOWN) { usbstate = usbIsActive() ? MASTER : SLAVE; + + // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow + if (usbstate == SLAVE) { + usb_disable(); + } } return (usbstate == MASTER); diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index 61b61ea08c..9ed0f7591b 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -22,6 +22,13 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A; # define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t)) #endif +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +# include "led_matrix.h" +#endif +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +# include "rgb_matrix.h" +#endif + #if defined(USE_I2C) # include "i2c_master.h" @@ -54,6 +61,14 @@ typedef struct _I2C_slave_buffer_t { # ifdef WPM_ENABLE uint8_t current_wpm; # endif +# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + led_eeconfig_t led_matrix; + bool led_suspend_state; +# endif +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + rgb_config_t rgb_matrix; + bool rgb_suspend_state; +# endif } I2C_slave_buffer_t; static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; @@ -68,6 +83,10 @@ static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_re # define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) # define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) # define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) +# define I2C_LED_MATRIX_START offsetof(I2C_slave_buffer_t, led_matrix) +# define I2C_LED_SUSPEND_START offsetof(I2C_slave_buffer_t, led_suspend_state) +# define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix) +# define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state) # define TIMEOUT 100 @@ -141,6 +160,17 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) # endif # endif +# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_MATRIX_START, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix), TIMEOUT); + bool suspend_state = led_matrix_get_suspend_state(); + i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->led_suspend_state), TIMEOUT); +# endif +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT); + bool suspend_state = rgb_matrix_get_suspend_state(); + i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT); +# endif + # ifndef DISABLE_SYNC_TIMER i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT); @@ -186,6 +216,15 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) set_oneshot_mods(i2c_buffer->oneshot_mods); # endif # endif + +# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + memcpy((void *)i2c_buffer->led_matrix, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix)); + led_matrix_set_suspend_state(i2c_buffer->led_suspend_state); +# endif +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + memcpy((void *)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix)); + rgb_matrix_set_suspend_state(i2c_buffer->rgb_suspend_state); +# endif } void transport_master_init(void) { i2c_init(); } @@ -201,30 +240,38 @@ typedef struct _Serial_s2m_buffer_t { matrix_row_t smatrix[ROWS_PER_HAND]; # ifdef ENCODER_ENABLE - uint8_t encoder_state[NUMBER_OF_ENCODERS]; + uint8_t encoder_state[NUMBER_OF_ENCODERS]; # endif } Serial_s2m_buffer_t; typedef struct _Serial_m2s_buffer_t { # ifdef SPLIT_MODS_ENABLE - uint8_t real_mods; - uint8_t weak_mods; + uint8_t real_mods; + uint8_t weak_mods; # ifndef NO_ACTION_ONESHOT - uint8_t oneshot_mods; + uint8_t oneshot_mods; # endif # endif # ifndef DISABLE_SYNC_TIMER - uint32_t sync_timer; + uint32_t sync_timer; # endif # ifdef SPLIT_TRANSPORT_MIRROR matrix_row_t mmatrix[ROWS_PER_HAND]; # endif # ifdef BACKLIGHT_ENABLE - uint8_t backlight_level; + uint8_t backlight_level; # endif # ifdef WPM_ENABLE - uint8_t current_wpm; + uint8_t current_wpm; +# endif +# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + led_eeconfig_t led_matrix; + bool led_suspend_state; +# endif +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + rgb_config_t rgb_matrix; + bool rgb_suspend_state; # endif } Serial_m2s_buffer_t; @@ -316,7 +363,7 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) // TODO: if MATRIX_COLS > 8 change to unpack() for (int i = 0; i < ROWS_PER_HAND; ++i) { - slave_matrix[i] = serial_s2m_buffer.smatrix[i]; + slave_matrix[i] = serial_s2m_buffer.smatrix[i]; # ifdef SPLIT_TRANSPORT_MIRROR serial_m2s_buffer.mmatrix[i] = master_matrix[i]; # endif @@ -333,18 +380,28 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) # ifdef WPM_ENABLE // Write wpm to slave - serial_m2s_buffer.current_wpm = get_current_wpm(); + serial_m2s_buffer.current_wpm = get_current_wpm(); # endif # ifdef SPLIT_MODS_ENABLE - serial_m2s_buffer.real_mods = get_mods(); - serial_m2s_buffer.weak_mods = get_weak_mods(); + serial_m2s_buffer.real_mods = get_mods(); + serial_m2s_buffer.weak_mods = get_weak_mods(); # ifndef NO_ACTION_ONESHOT serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); # endif # endif + +# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + serial_m2s_buffer.led_matrix = led_matrix_eeconfig; + serial_m2s_buffer.led_suspend_state = led_matrix_get_suspend_state(); +# endif +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + serial_m2s_buffer.rgb_matrix = rgb_matrix_config; + serial_m2s_buffer.rgb_suspend_state = rgb_matrix_get_suspend_state(); +# endif + # ifndef DISABLE_SYNC_TIMER - serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; + serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; # endif return true; } @@ -359,7 +416,7 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) for (int i = 0; i < ROWS_PER_HAND; ++i) { serial_s2m_buffer.smatrix[i] = slave_matrix[i]; # ifdef SPLIT_TRANSPORT_MIRROR - master_matrix[i] = serial_m2s_buffer.mmatrix[i]; + master_matrix[i] = serial_m2s_buffer.mmatrix[i]; # endif } # ifdef BACKLIGHT_ENABLE @@ -381,6 +438,15 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) set_oneshot_mods(serial_m2s_buffer.oneshot_mods); # endif # endif + +# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + led_matrix_eeconfig = serial_m2s_buffer.led_matrix; + led_matrix_set_suspend_state(serial_m2s_buffer.led_suspend_state); +# endif +# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + rgb_matrix_config = serial_m2s_buffer.rgb_matrix; + rgb_matrix_set_suspend_state(serial_m2s_buffer.rgb_suspend_state); +# endif } #endif diff --git a/quantum/wpm.c b/quantum/wpm.c index da30bd252c..bec419a48e 100644 --- a/quantum/wpm.c +++ b/quantum/wpm.c @@ -19,11 +19,10 @@ // WPM Stuff static uint8_t current_wpm = 0; -static uint8_t latest_wpm = 0; static uint16_t wpm_timer = 0; // This smoothing is 40 keystrokes -static const float wpm_smoothing = 0.0487; +static const float wpm_smoothing = WPM_SMOOTHING; void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; } @@ -46,19 +45,46 @@ __attribute__((weak)) bool wpm_keycode_user(uint16_t keycode) { return false; } +#ifdef WPM_ALLOW_COUNT_REGRESSION +__attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) { + bool weak_modded = (keycode >= QK_LCTL && keycode < QK_LSFT) || (keycode >= QK_RCTL && keycode < QK_RSFT); + + if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) || (keycode >= QK_MODS && keycode <= QK_MODS_MAX)) { + keycode = keycode & 0xFF; + } else if (keycode > 0xFF) { + keycode = 0; + } + if (keycode == KC_DEL || keycode == KC_BSPC) { + if (((get_mods() | get_oneshot_mods()) & MOD_MASK_CTRL) || weak_modded) { + return WPM_ESTIMATED_WORD_SIZE; + } else { + return 1; + } + } else { + return 0; + } +} +#endif + void update_wpm(uint16_t keycode) { if (wpm_keycode(keycode)) { if (wpm_timer > 0) { - latest_wpm = 60000 / timer_elapsed(wpm_timer) / 5; - current_wpm = (latest_wpm - current_wpm) * wpm_smoothing + current_wpm; + current_wpm += ((60000 / timer_elapsed(wpm_timer) / WPM_ESTIMATED_WORD_SIZE) - current_wpm) * wpm_smoothing; } wpm_timer = timer_read(); } +#ifdef WPM_ALLOW_COUNT_REGRESSION + uint8_t regress = wpm_regress_count(keycode); + if (regress) { + current_wpm -= regress; + wpm_timer = timer_read(); + } +#endif } void decay_wpm(void) { if (timer_elapsed(wpm_timer) > 1000) { - current_wpm = (0 - current_wpm) * wpm_smoothing + current_wpm; - wpm_timer = timer_read(); + current_wpm += (-current_wpm) * wpm_smoothing; + wpm_timer = timer_read(); } } diff --git a/quantum/wpm.h b/quantum/wpm.h index 15ab4ffcd1..4af52d2b98 100644 --- a/quantum/wpm.h +++ b/quantum/wpm.h @@ -19,10 +19,21 @@ #include "quantum.h" +#ifndef WPM_ESTIMATED_WORD_SIZE +# define WPM_ESTIMATED_WORD_SIZE 5 +#endif +#ifndef WPM_SMOOTHING +# define WPM_SMOOTHING 0.0487 +#endif + bool wpm_keycode(uint16_t keycode); bool wpm_keycode_kb(uint16_t keycode); bool wpm_keycode_user(uint16_t keycode); +#ifdef WPM_ALLOW_COUNT_REGRESSION +uint8_t wpm_regress_count(uint16_t keycode); +#endif + void set_current_wpm(uint8_t); uint8_t get_current_wpm(void); void update_wpm(uint16_t); diff --git a/requirements.txt b/requirements.txt index 8553e2c3f0..3e23a6f333 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,9 @@ appdirs argcomplete colorama dotty-dict +hid hjson jsonschema>=3 -milc>=1.3.0 +milc>=1.4.2 pygments +pyusb @@ -1,14 +1,16 @@ { avr ? true, arm ? true, teensy ? true }: let # We specify sources via Niv: use "niv update nixpkgs" to update nixpkgs, for example. - sources = import ./nix/sources.nix {}; - pkgs = import sources.nixpkgs {}; + sources = import ./nix/sources.nix { }; + pkgs = import sources.nixpkgs { }; + + poetry2nix = pkgs.callPackage (import sources.poetry2nix) { }; # Builds the python env based on nix/pyproject.toml and # nix/poetry.lock Use the "poetry update --lock", "poetry add # --lock" etc. in the nix folder to adjust the contents of those # files if the requirements*.txt files change - pythonEnv = pkgs.poetry2nix.mkPoetryEnv { + pythonEnv = poetry2nix.mkPoetryEnv { projectDir = ./nix; }; in diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk index 2bc7cc9553..eb934ffe60 100644 --- a/tmk_core/avr.mk +++ b/tmk_core/avr.mk @@ -113,10 +113,16 @@ define EXEC_DFU if [ "$(1)" ]; then \ echo "Flashing '$(1)' for EE_HANDS split keyboard support." ;\ fi; \ - until $(DFU_PROGRAMMER) $(MCU) get bootloader-version; do\ - printf "$(MSG_BOOTLOADER_NOT_FOUND)" ;\ - sleep 5 ;\ - done; \ + if ! $(DFU_PROGRAMMER) $(MCU) get bootloader-version >/dev/null 2>/dev/null; then\ + printf "$(MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY)" ;\ + sleep $(BOOTLOADER_RETRY_TIME) ;\ + while ! $(DFU_PROGRAMMER) $(MCU) get bootloader-version >/dev/null 2>/dev/null; do\ + printf "." ;\ + sleep $(BOOTLOADER_RETRY_TIME) ;\ + done ;\ + printf "\n" ;\ + fi; \ + $(DFU_PROGRAMMER) $(MCU) get bootloader-version ;\ if $(DFU_PROGRAMMER) --version 2>&1 | $(GREP) -q 0.7 ; then\ $(DFU_PROGRAMMER) $(MCU) erase --force; \ if [ "$(1)" ]; then \ @@ -172,7 +178,7 @@ define EXEC_AVRDUDE TMP2=`mktemp`; \ list_devices > $$TMP1; \ while [ -z "$$USB" ]; do \ - sleep 0.5; \ + sleep $(BOOTLOADER_RETRY_TIME); \ printf "."; \ list_devices > $$TMP2; \ USB=`comm -13 $$TMP1 $$TMP2 | $(GREP) -o '/dev/tty.*'`; \ @@ -187,7 +193,7 @@ define EXEC_AVRDUDE sleep 1; \ else \ printf "Waiting for $$USB to become writable."; \ - while [ ! -w "$$USB" ]; do sleep 0.5; printf "."; done; echo ""; \ + while [ ! -w "$$USB" ]; do sleep $(BOOTLOADER_RETRY_TIME); printf "."; done; echo ""; \ fi; \ if [ -z "$(1)" ]; then \ $(AVRDUDE_PROGRAMMER) -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex; \ @@ -294,7 +300,7 @@ ifneq ($(strip $(BOOTLOADER)), qmk-dfu) $(error Please set BOOTLOADER = qmk-dfu first!) endif make -C lib/lufa/Bootloaders/DFU/ clean - bin/qmk generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/DFU/Keyboard.h + $(QMK_BIN) generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/DFU/Keyboard.h $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) $(eval PROGRAM_SIZE_KB=$(shell n=`expr $(MAX_SIZE) / 1024` && echo $$(($$n)) || echo 0)) $(eval BOOT_SECTION_SIZE_KB=$(shell n=`expr $(BOOTLOADER_SIZE) / 1024` && echo $$(($$n)) || echo 0)) diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 40595a1e3b..97299b7d32 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -190,6 +190,8 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(KEYBOARD_PATH_2)/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/ld/$(MCU_LDSCRIPT).ld)","") + LDSCRIPT = $(TOP_DIR)/platforms/chibios/$(BOARD)/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld)","") LDSCRIPT = $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld else ifneq ("$(wildcard $(STARTUPLD_CONTRIB)/$(MCU_LDSCRIPT).ld)","") @@ -339,10 +341,15 @@ ST_LINK_CLI ?= st-link_cli ST_FLASH ?= st-flash define EXEC_DFU_UTIL - until $(DFU_UTIL) -l | grep -q "Found DFU"; do\ - printf "$(MSG_BOOTLOADER_NOT_FOUND)" ;\ - sleep 5 ;\ - done + if ! $(DFU_UTIL) -l | grep -q "Found DFU"; then \ + printf "$(MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY)" ;\ + sleep $(BOOTLOADER_RETRY_TIME) ;\ + while ! $(DFU_UTIL) -l | grep -q "Found DFU"; do \ + printf "." ;\ + sleep $(BOOTLOADER_RETRY_TIME) ;\ + done ;\ + printf "\n" ;\ + fi $(DFU_UTIL) $(DFU_ARGS) -D $(BUILD_DIR)/$(TARGET).bin endef diff --git a/tmk_core/common.mk b/tmk_core/common.mk index bcc44a63e6..d34d8368f3 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -14,6 +14,7 @@ TMK_COMMON_SRC += $(COMMON_DIR)/host.c \ $(COMMON_DIR)/sendchar_null.c \ $(COMMON_DIR)/eeconfig.c \ $(COMMON_DIR)/report.c \ + $(COMMON_DIR)/usb_util.c \ $(PLATFORM_COMMON_DIR)/suspend.c \ $(PLATFORM_COMMON_DIR)/timer.c \ $(COMMON_DIR)/sync_timer.c \ @@ -26,28 +27,6 @@ else include $(TMK_PATH)/$(COMMON_DIR)/lib_printf.mk endif -# Option modules -BOOTMAGIC_ENABLE ?= no -VALID_MAGIC_TYPES := yes full lite -ifneq ($(strip $(BOOTMAGIC_ENABLE)), no) - ifeq ($(filter $(BOOTMAGIC_ENABLE),$(VALID_MAGIC_TYPES)),) - $(error BOOTMAGIC_ENABLE="$(BOOTMAGIC_ENABLE)" is not a valid type of magic) - endif - ifeq ($(strip $(BOOTMAGIC_ENABLE)), lite) - TMK_COMMON_DEFS += -DBOOTMAGIC_LITE - TMK_COMMON_SRC += $(COMMON_DIR)/bootmagic_lite.c - - TMK_COMMON_DEFS += -DMAGIC_ENABLE - TMK_COMMON_SRC += $(COMMON_DIR)/magic.c - else - TMK_COMMON_DEFS += -DBOOTMAGIC_ENABLE - TMK_COMMON_SRC += $(COMMON_DIR)/bootmagic.c - endif -else - TMK_COMMON_DEFS += -DMAGIC_ENABLE - TMK_COMMON_SRC += $(COMMON_DIR)/magic.c -endif - SHARED_EP_ENABLE = no MOUSE_SHARED_EP ?= yes ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes) diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index 055bd91de0..5660c3fa1f 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -133,7 +133,8 @@ void process_hand_swap(keyevent_t *event) { bool do_swap = event->pressed ? swap_hands : swap_state[pos.row] & (col_bit); if (do_swap) { - event->key = hand_swap_config[pos.row][pos.col]; + event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row); + event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col); swap_state[pos.row] |= col_bit; } else { swap_state[pos.row] &= ~(col_bit); @@ -772,10 +773,9 @@ void register_code(uint8_t code) { } #endif - else if - IS_KEY(code) { - // TODO: should push command_proc out of this block? - if (command_proc(code)) return; + else if IS_KEY (code) { + // TODO: should push command_proc out of this block? + if (command_proc(code)) return; #ifndef NO_ACTION_ONESHOT /* TODO: remove @@ -792,35 +792,33 @@ void register_code(uint8_t code) { } else */ #endif - { - // Force a new key press if the key is already pressed - // without this, keys with the same keycode, but different - // modifiers will be reported incorrectly, see issue #1708 - if (is_key_pressed(keyboard_report, code)) { - del_key(code); - send_keyboard_report(); - } - add_key(code); + { + // Force a new key press if the key is already pressed + // without this, keys with the same keycode, but different + // modifiers will be reported incorrectly, see issue #1708 + if (is_key_pressed(keyboard_report, code)) { + del_key(code); send_keyboard_report(); } - } - else if - IS_MOD(code) { - add_mods(MOD_BIT(code)); + add_key(code); send_keyboard_report(); } + } else if IS_MOD (code) { + add_mods(MOD_BIT(code)); + send_keyboard_report(); + } #ifdef EXTRAKEY_ENABLE - else if - IS_SYSTEM(code) { host_system_send(KEYCODE2SYSTEM(code)); } - else if - IS_CONSUMER(code) { host_consumer_send(KEYCODE2CONSUMER(code)); } + else if IS_SYSTEM (code) { + host_system_send(KEYCODE2SYSTEM(code)); + } else if IS_CONSUMER (code) { + host_consumer_send(KEYCODE2CONSUMER(code)); + } #endif #ifdef MOUSEKEY_ENABLE - else if - IS_MOUSEKEY(code) { - mousekey_on(code); - mousekey_send(); - } + else if IS_MOUSEKEY (code) { + mousekey_on(code); + mousekey_send(); + } #endif } @@ -865,26 +863,22 @@ void unregister_code(uint8_t code) { } #endif - else if - IS_KEY(code) { - del_key(code); - send_keyboard_report(); - } - else if - IS_MOD(code) { - del_mods(MOD_BIT(code)); - send_keyboard_report(); - } - else if - IS_SYSTEM(code) { host_system_send(0); } - else if - IS_CONSUMER(code) { host_consumer_send(0); } + else if IS_KEY (code) { + del_key(code); + send_keyboard_report(); + } else if IS_MOD (code) { + del_mods(MOD_BIT(code)); + send_keyboard_report(); + } else if IS_SYSTEM (code) { + host_system_send(0); + } else if IS_CONSUMER (code) { + host_consumer_send(0); + } #ifdef MOUSEKEY_ENABLE - else if - IS_MOUSEKEY(code) { - mousekey_off(code); - mousekey_send(); - } + else if IS_MOUSEKEY (code) { + mousekey_off(code); + mousekey_send(); + } #endif } diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 9a991de1c2..8cb4722c6e 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -77,8 +77,8 @@ extern bool disable_action_cache; /* Code for handling one-handed key modifiers. */ #ifdef SWAP_HANDS_ENABLE -extern bool swap_hands; -extern const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; +extern bool swap_hands; +extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; # if (MATRIX_COLS <= 8) typedef uint8_t swap_state_row_t; # elif (MATRIX_COLS <= 16) diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c index 000503b082..a57c8bf66a 100644 --- a/tmk_core/common/action_util.c +++ b/tmk_core/common/action_util.c @@ -147,12 +147,16 @@ void clear_oneshot_swaphands(void) { * FIXME: needs doc */ void set_oneshot_layer(uint8_t layer, uint8_t state) { - oneshot_layer_data = layer << 3 | state; - layer_on(layer); + if (!keymap_config.oneshot_disable) { + oneshot_layer_data = layer << 3 | state; + layer_on(layer); # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_layer_time = timer_read(); + oneshot_layer_time = timer_read(); # endif - oneshot_layer_changed_kb(get_oneshot_layer()); + oneshot_layer_changed_kb(get_oneshot_layer()); + } else { + layer_on(layer); + } } /** \brief Reset oneshot layer * @@ -172,7 +176,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) { + if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) { layer_off(get_oneshot_layer()); reset_oneshot_layer(); } @@ -182,6 +186,39 @@ void clear_oneshot_layer_state(oneshot_fullfillment_t state) { * FIXME: needs doc */ bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); } + +/** \brief set oneshot + * + * FIXME: needs doc + */ +void oneshot_set(bool active) { + if (keymap_config.oneshot_disable != active) { + keymap_config.oneshot_disable = active; + eeconfig_update_keymap(keymap_config.raw); + dprintf("Oneshot: active: %d\n", active); + } +} + +/** \brief toggle oneshot + * + * FIXME: needs doc + */ +void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); } + +/** \brief enable oneshot + * + * FIXME: needs doc + */ +void oneshot_enable(void) { oneshot_set(true); } + +/** \brief disable oneshot + * + * FIXME: needs doc + */ +void oneshot_disable(void) { oneshot_set(false); } + +bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; } + #endif /** \brief Send keyboard report @@ -321,14 +358,17 @@ void del_oneshot_mods(uint8_t mods) { * FIXME: needs doc */ void set_oneshot_mods(uint8_t mods) { - if (oneshot_mods != mods) { + if (!keymap_config.oneshot_disable) { + if (oneshot_mods != mods) { # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_time = timer_read(); + oneshot_time = timer_read(); # endif - oneshot_mods = mods; - oneshot_mods_changed_kb(mods); + oneshot_mods = mods; + oneshot_mods_changed_kb(mods); + } } } + /** \brief clear oneshot mods * * FIXME: needs doc diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h index ff29f79b09..f2b3897ae5 100644 --- a/tmk_core/common/action_util.h +++ b/tmk_core/common/action_util.h @@ -85,6 +85,11 @@ void oneshot_mods_changed_kb(uint8_t mods); void oneshot_layer_changed_user(uint8_t layer); void oneshot_layer_changed_kb(uint8_t layer); +void oneshot_toggle(void); +void oneshot_enable(void); +void oneshot_disable(void); +bool is_oneshot_enabled(void); + /* inspect */ uint8_t has_anymod(void); diff --git a/tmk_core/common/arm_atsam/_wait.h b/tmk_core/common/arm_atsam/_wait.h new file mode 100644 index 0000000000..41b686b56c --- /dev/null +++ b/tmk_core/common/arm_atsam/_wait.h @@ -0,0 +1,22 @@ +/* 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 3 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 "clks.h" + +#define wait_ms(ms) CLK_delay_ms(ms) +#define wait_us(us) CLK_delay_us(us) +#define waitInputPinDelay() diff --git a/tmk_core/common/avr/_wait.h b/tmk_core/common/avr/_wait.h new file mode 100644 index 0000000000..56eb316faf --- /dev/null +++ b/tmk_core/common/avr/_wait.h @@ -0,0 +1,29 @@ +/* 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 3 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 <util/delay.h> + +#define wait_ms(ms) _delay_ms(ms) +#define wait_us(us) _delay_us(us) + +/* The AVR series GPIOs have a one clock read delay for changes in the digital input signal. + * But here's more margin to make it two clocks. */ +#ifndef GPIO_INPUT_PIN_DELAY +# define GPIO_INPUT_PIN_DELAY 2 +#endif + +#define waitInputPinDelay() __builtin_avr_delay_cycles(GPIO_INPUT_PIN_DELAY) diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 47a82a2eec..690d7f38ca 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -28,6 +28,13 @@ # include "rgblight.h" #endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif + /** \brief Suspend idle * * FIXME: needs doc @@ -156,6 +163,13 @@ void suspend_power_down(void) { 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 + // Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt) # if defined(WDT_vect) power_down(WDTO_15MS); @@ -208,6 +222,13 @@ void suspend_wakeup_init(void) { 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/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h new file mode 100644 index 0000000000..5bface53e1 --- /dev/null +++ b/tmk_core/common/chibios/_wait.h @@ -0,0 +1,55 @@ +/* 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 3 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 <ch.h> + +/* chThdSleepX of zero maps to infinite - so we map to a tiny delay to still yield */ +#define wait_ms(ms) \ + do { \ + if (ms != 0) { \ + chThdSleepMilliseconds(ms); \ + } else { \ + chThdSleepMicroseconds(1); \ + } \ + } while (0) +#define wait_us(us) \ + do { \ + if (us != 0) { \ + chThdSleepMicroseconds(us); \ + } else { \ + chThdSleepMicroseconds(1); \ + } \ + } while (0) + +/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus + * to which the GPIO is connected. + * The connected buses differ depending on the various series of MCUs. + * And since the instruction execution clock of the CPU and the bus clock of GPIO are different, + * there is a delay of several clocks to read the change of the input signal. + * + * Define this delay with the GPIO_INPUT_PIN_DELAY macro. + * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. + * (A fairly large value of 0.25 microseconds is set.) + */ + +#include "wait.c" + +#ifndef GPIO_INPUT_PIN_DELAY +# define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) +#endif + +#define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 6cabcc4b81..11f7abf432 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -13,7 +13,23 @@ # define STM32_BOOTLOADER_DUAL_BANK FALSE #endif -#if STM32_BOOTLOADER_DUAL_BANK +#ifdef BOOTLOADER_TINYUF2 + +# define DBL_TAP_MAGIC 0xf01669ef // From tinyuf2's board_api.h + +// defined by linker script +extern uint32_t _board_dfu_dbl_tap[]; +# define DBL_TAP_REG _board_dfu_dbl_tap[0] + +void bootloader_jump(void) { + DBL_TAP_REG = DBL_TAP_MAGIC; + NVIC_SystemReset(); +} + +void enter_bootloader_mode_if_requested(void) { /* not needed, no two-stage reset */ +} + +#elif STM32_BOOTLOADER_DUAL_BANK // Need pin definitions # include "config_common.h" @@ -79,7 +95,7 @@ void enter_bootloader_mode_if_requested(void) { } } -#elif defined(KL2x) || defined(K20x) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS +#elif defined(KL2x) || defined(K20x) || defined(MK66F18) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS /* Kinetis */ # if defined(BOOTLOADER_KIIBOHD) diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index b4d96465d1..1d8ace4955 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -15,6 +15,8 @@ */ #pragma once +#define SPLIT_USB_DETECT // Force this on for now + #if defined(STM32F1XX) # define USE_GPIOV1 #endif @@ -28,4 +30,9 @@ # define USE_I2CV1 # define USE_I2CV1_CONTRIB // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed # define USE_GPIOV1 +# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY +#endif + +#if defined(MK66F18) +# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY #endif diff --git a/tmk_core/common/chibios/pin_defs.h b/tmk_core/common/chibios/pin_defs.h index 86bc1076e8..c03f8de0c2 100644 --- a/tmk_core/common/chibios/pin_defs.h +++ b/tmk_core/common/chibios/pin_defs.h @@ -70,6 +70,23 @@ # define A13 PAL_LINE(GPIOA, 13) # define A14 PAL_LINE(GPIOA, 14) # define A15 PAL_LINE(GPIOA, 15) +# define A16 PAL_LINE(GPIOA, 16) +# define A17 PAL_LINE(GPIOA, 17) +# define A18 PAL_LINE(GPIOA, 18) +# define A19 PAL_LINE(GPIOA, 19) +# define A20 PAL_LINE(GPIOA, 20) +# define A21 PAL_LINE(GPIOA, 21) +# define A22 PAL_LINE(GPIOA, 22) +# define A23 PAL_LINE(GPIOA, 23) +# define A24 PAL_LINE(GPIOA, 24) +# define A25 PAL_LINE(GPIOA, 25) +# define A26 PAL_LINE(GPIOA, 26) +# define A27 PAL_LINE(GPIOA, 27) +# define A28 PAL_LINE(GPIOA, 28) +# define A29 PAL_LINE(GPIOA, 29) +# define A30 PAL_LINE(GPIOA, 30) +# define A31 PAL_LINE(GPIOA, 31) +# define A32 PAL_LINE(GPIOA, 32) # define B0 PAL_LINE(GPIOB, 0) # define B1 PAL_LINE(GPIOB, 1) # define B2 PAL_LINE(GPIOB, 2) @@ -90,6 +107,19 @@ # define B17 PAL_LINE(GPIOB, 17) # define B18 PAL_LINE(GPIOB, 18) # define B19 PAL_LINE(GPIOB, 19) +# define B20 PAL_LINE(GPIOB, 20) +# define B21 PAL_LINE(GPIOB, 21) +# define B22 PAL_LINE(GPIOB, 22) +# define B23 PAL_LINE(GPIOB, 23) +# define B24 PAL_LINE(GPIOB, 24) +# define B25 PAL_LINE(GPIOB, 25) +# define B26 PAL_LINE(GPIOB, 26) +# define B27 PAL_LINE(GPIOB, 27) +# define B28 PAL_LINE(GPIOB, 28) +# define B29 PAL_LINE(GPIOB, 29) +# define B30 PAL_LINE(GPIOB, 30) +# define B31 PAL_LINE(GPIOB, 31) +# define B32 PAL_LINE(GPIOB, 32) # define C0 PAL_LINE(GPIOC, 0) # define C1 PAL_LINE(GPIOC, 1) # define C2 PAL_LINE(GPIOC, 2) @@ -106,6 +136,23 @@ # define C13 PAL_LINE(GPIOC, 13) # define C14 PAL_LINE(GPIOC, 14) # define C15 PAL_LINE(GPIOC, 15) +# define C16 PAL_LINE(GPIOC, 16) +# define C17 PAL_LINE(GPIOC, 17) +# define C18 PAL_LINE(GPIOC, 18) +# define C19 PAL_LINE(GPIOC, 19) +# define C20 PAL_LINE(GPIOC, 20) +# define C21 PAL_LINE(GPIOC, 21) +# define C22 PAL_LINE(GPIOC, 22) +# define C23 PAL_LINE(GPIOC, 23) +# define C24 PAL_LINE(GPIOC, 24) +# define C25 PAL_LINE(GPIOC, 25) +# define C26 PAL_LINE(GPIOC, 26) +# define C27 PAL_LINE(GPIOC, 27) +# define C28 PAL_LINE(GPIOC, 28) +# define C29 PAL_LINE(GPIOC, 29) +# define C30 PAL_LINE(GPIOC, 30) +# define C31 PAL_LINE(GPIOC, 31) +# define C32 PAL_LINE(GPIOC, 32) # define D0 PAL_LINE(GPIOD, 0) # define D1 PAL_LINE(GPIOD, 1) # define D2 PAL_LINE(GPIOD, 2) @@ -122,6 +169,23 @@ # define D13 PAL_LINE(GPIOD, 13) # define D14 PAL_LINE(GPIOD, 14) # define D15 PAL_LINE(GPIOD, 15) +# define D16 PAL_LINE(GPIOD, 16) +# define D17 PAL_LINE(GPIOD, 17) +# define D18 PAL_LINE(GPIOD, 18) +# define D19 PAL_LINE(GPIOD, 19) +# define D20 PAL_LINE(GPIOD, 20) +# define D21 PAL_LINE(GPIOD, 21) +# define D22 PAL_LINE(GPIOD, 22) +# define D23 PAL_LINE(GPIOD, 23) +# define D24 PAL_LINE(GPIOD, 24) +# define D25 PAL_LINE(GPIOD, 25) +# define D26 PAL_LINE(GPIOD, 26) +# define D27 PAL_LINE(GPIOD, 27) +# define D28 PAL_LINE(GPIOD, 28) +# define D29 PAL_LINE(GPIOD, 29) +# define D30 PAL_LINE(GPIOD, 30) +# define D31 PAL_LINE(GPIOD, 31) +# define D32 PAL_LINE(GPIOD, 32) # define E0 PAL_LINE(GPIOE, 0) # define E1 PAL_LINE(GPIOE, 1) # define E2 PAL_LINE(GPIOE, 2) @@ -138,6 +202,23 @@ # define E13 PAL_LINE(GPIOE, 13) # define E14 PAL_LINE(GPIOE, 14) # define E15 PAL_LINE(GPIOE, 15) +# define E16 PAL_LINE(GPIOE, 16) +# define E17 PAL_LINE(GPIOE, 17) +# define E18 PAL_LINE(GPIOE, 18) +# define E19 PAL_LINE(GPIOE, 19) +# define E20 PAL_LINE(GPIOE, 20) +# define E21 PAL_LINE(GPIOE, 21) +# define E22 PAL_LINE(GPIOE, 22) +# define E23 PAL_LINE(GPIOE, 23) +# define E24 PAL_LINE(GPIOE, 24) +# define E25 PAL_LINE(GPIOE, 25) +# define E26 PAL_LINE(GPIOE, 26) +# define E27 PAL_LINE(GPIOE, 27) +# define E28 PAL_LINE(GPIOE, 28) +# define E29 PAL_LINE(GPIOE, 29) +# define E30 PAL_LINE(GPIOE, 30) +# define E31 PAL_LINE(GPIOE, 31) +# define E32 PAL_LINE(GPIOE, 32) # define F0 PAL_LINE(GPIOF, 0) # define F1 PAL_LINE(GPIOF, 1) # define F2 PAL_LINE(GPIOF, 2) diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c index 5595eec0e5..1c65016a42 100644 --- a/tmk_core/common/chibios/sleep_led.c +++ b/tmk_core/common/chibios/sleep_led.c @@ -9,21 +9,13 @@ * Use LP timer on Kinetises, TIM14 on STM32F0. */ -#if defined(KL2x) || defined(K20x) - -/* Use Low Power Timer (LPTMR) */ -# define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR -# define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF - -#elif defined(STM32F0XX) - -/* Use TIM14 manually */ -# define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER -# define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF - +#ifndef SLEEP_LED_GPT_DRIVER +# if defined(STM32F0XX) +# define SLEEP_LED_GPT_DRIVER GPTD14 +# endif #endif -#if defined(KL2x) || defined(K20x) || defined(STM32F0XX) /* common parts for timers/interrupts */ +#if defined(KL2x) || defined(K20x) || defined(SLEEP_LED_GPT_DRIVER) /* common parts for timers/interrupts */ /* Breathing Sleep LED brighness(PWM On period) table * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle @@ -33,10 +25,7 @@ */ static const uint8_t breathing_table[64] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -/* interrupt handler */ -OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { - OSAL_IRQ_PROLOGUE(); - +void sleep_led_timer_callback(void) { /* Software PWM * timer:1111 1111 1111 1111 * \_____/\/ \_______/____ count(0-255) @@ -64,20 +53,19 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { if (timer.pwm.count == breathing_table[timer.pwm.index]) { led_set(0); } - - /* Reset the counter */ - RESET_COUNTER; - - OSAL_IRQ_EPILOGUE(); } #endif /* common parts for known platforms */ #if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */ +/* Use Low Power Timer (LPTMR) */ +# define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR +# define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF + /* LPTMR clock options */ # define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */ -# define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ +# define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ # define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */ # define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */ @@ -86,6 +74,18 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { # define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER # endif +/* interrupt handler */ +OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { + OSAL_IRQ_PROLOGUE(); + + sleep_led_timer_callback(); + + /* Reset the counter */ + RESET_COUNTER; + + OSAL_IRQ_EPILOGUE(); +} + /* Initialise the timer */ void sleep_led_init(void) { /* Make sure the clock to the LPTMR is enabled */ @@ -121,7 +121,7 @@ void sleep_led_init(void) { MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock # if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others MCG->MC |= MCG_MC_LIRC_DIV2_DIV2; -# endif /* KL27 */ +# endif /* KL27 */ MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock // to work in stop mode, also MCG_C1_IREFSTEN // Divide 4MHz by 2^N (N=6) => 62500 irqs/sec => @@ -159,45 +159,23 @@ void sleep_led_toggle(void) { LPTMR0->CSR ^= LPTMRx_CSR_TEN; } -#elif defined(STM32F0XX) /* platform selection: STM32F0XX */ - -/* Initialise the timer */ -void sleep_led_init(void) { - /* enable clock */ - rccEnableTIM14(FALSE); /* low power enable = FALSE */ - rccResetTIM14(); - - /* prescale */ - /* Assuming 48MHz internal clock */ - /* getting cca 65484 irqs/sec */ - STM32_TIM14->PSC = 733; +#elif defined(SLEEP_LED_GPT_DRIVER) - /* auto-reload */ - /* 0 => interrupt every time */ - STM32_TIM14->ARR = 3; +static void gptTimerCallback(GPTDriver *gptp) { + (void)gptp; + sleep_led_timer_callback(); +} - /* enable counter update event interrupt */ - STM32_TIM14->DIER |= STM32_TIM_DIER_UIE; +static const GPTConfig gptcfg = {1000000, gptTimerCallback, 0, 0}; - /* register interrupt vector */ - nvicEnableVector(STM32_TIM14_NUMBER, 2); /* vector, priority */ -} +/* Initialise the timer */ +void sleep_led_init(void) { gptStart(&SLEEP_LED_GPT_DRIVER, &gptcfg); } -void sleep_led_enable(void) { - /* Enable the timer */ - STM32_TIM14->CR1 = STM32_TIM_CR1_CEN | STM32_TIM_CR1_URS; - /* URS => update event only on overflow; setting UG bit disabled */ -} +void sleep_led_enable(void) { gptStartContinuous(&SLEEP_LED_GPT_DRIVER, gptcfg.frequency / 0xFFFF); } -void sleep_led_disable(void) { - /* Disable the timer */ - STM32_TIM14->CR1 = 0; -} +void sleep_led_disable(void) { gptStopTimer(&SLEEP_LED_GPT_DRIVER); } -void sleep_led_toggle(void) { - /* Toggle the timer */ - STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN; -} +void sleep_led_toggle(void) { (SLEEP_LED_GPT_DRIVER.state == GPT_READY) ? sleep_led_enable() : sleep_led_disable(); } #else /* platform selection: not on familiar chips */ diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 49e20641fb..38517e06f0 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -24,6 +24,13 @@ # include "rgblight.h" #endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif + /** \brief suspend idle * * FIXME: needs doc @@ -53,6 +60,13 @@ void suspend_power_down(void) { 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) @@ -69,6 +83,13 @@ void suspend_power_down(void) { #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 AUDIO_ENABLE stop_all_notes(); #endif /* AUDIO_ENABLE */ @@ -137,5 +158,12 @@ void suspend_wakeup_init(void) { #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/tmk_core/common/chibios/wait.c b/tmk_core/common/chibios/wait.c new file mode 100644 index 0000000000..c6270fd95e --- /dev/null +++ b/tmk_core/common/chibios/wait.c @@ -0,0 +1,89 @@ +/* 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __OPTIMIZE__ +# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" +#endif + +#define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" + +__attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ + /* The argument n must be a constant expression. + * That way, compiler optimization will remove unnecessary code. */ + if (n < 1) { + return; + } + if (n > 8) { + unsigned int n8 = n / 8; + n = n - n8 * 8; + switch (n8) { + case 16: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 15: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 14: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 13: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 12: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 11: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 10: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 9: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 8: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 7: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 6: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 5: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 4: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 3: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 2: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 1: + asm volatile(CLOCK_DELAY_NOP8::: "memory"); + case 0: + break; + } + } + switch (n) { + case 8: + asm volatile("nop" ::: "memory"); + case 7: + asm volatile("nop" ::: "memory"); + case 6: + asm volatile("nop" ::: "memory"); + case 5: + asm volatile("nop" ::: "memory"); + case 4: + asm volatile("nop" ::: "memory"); + case 3: + asm volatile("nop" ::: "memory"); + case 2: + asm volatile("nop" ::: "memory"); + case 1: + asm volatile("nop" ::: "memory"); + case 0: + break; + } +}
\ No newline at end of file diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index 60b2dcb7e7..57c468ed7a 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c @@ -60,10 +60,12 @@ void eeconfig_init_quantum(void) { eeprom_update_dword(EECONFIG_HAPTIC, 0); eeprom_update_byte(EECONFIG_VELOCIKEY, 0); eeprom_update_dword(EECONFIG_RGB_MATRIX, 0); - eeprom_update_byte(EECONFIG_RGB_MATRIX_SPEED, 0); + eeprom_update_word(EECONFIG_RGB_MATRIX_EXTENDED, 0); + #ifdef ORYX_ENABLE eeconfig_init_oryx(); #endif + // TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS // within the emulated eeprom via dfu-util or another tool #if defined INIT_EE_HANDS_LEFT @@ -160,17 +162,6 @@ void eeconfig_update_keymap(uint16_t val) { eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, (val >> 8) & 0xFF); } -/** \brief eeconfig read backlight - * - * FIXME: needs doc - */ -uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); } -/** \brief eeconfig update backlight - * - * FIXME: needs doc - */ -void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); } - /** \brief eeconfig read audio * * FIXME: needs doc diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 86b9e6f99b..a88071729d 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <stdbool.h> #ifndef EECONFIG_MAGIC_NUMBER -# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEB // When changing, decrement this value to avoid future re-init issues +# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEA // When changing, decrement this value to avoid future re-init issues #endif #define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF @@ -43,12 +43,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define EECONFIG_VELOCIKEY (uint8_t *)23 #define EECONFIG_HAPTIC (uint32_t *)24 + +// Mutually exclusive +#define EECONFIG_LED_MATRIX (uint32_t *)28 #define EECONFIG_RGB_MATRIX (uint32_t *)28 -#define EECONFIG_RGB_MATRIX_SPEED (uint8_t *)32 +// Speed & Flags +#define EECONFIG_LED_MATRIX_EXTENDED (uint16_t *)32 +#define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32 + // TODO: Combine these into a single word and single block of EEPROM -#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)33 +#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34 // Size of EEPROM being used, other code can refer to this for available EEPROM -#define EECONFIG_SIZE 34 +#define EECONFIG_SIZE 35 /* debug bit */ #define EECONFIG_DEBUG_ENABLE (1 << 0) #define EECONFIG_DEBUG_MATRIX (1 << 1) @@ -88,11 +94,6 @@ void eeconfig_update_default_layer(uint8_t val); uint16_t eeconfig_read_keymap(void); void eeconfig_update_keymap(uint16_t val); -#ifdef BACKLIGHT_ENABLE -uint8_t eeconfig_read_backlight(void); -void eeconfig_update_backlight(uint8_t val); -#endif - #ifdef AUDIO_ENABLE uint8_t eeconfig_read_audio(void); void eeconfig_update_audio(uint8_t val); diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index ce3255c069..3d6092e71c 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -34,11 +34,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef BACKLIGHT_ENABLE # include "backlight.h" #endif -#ifdef BOOTMAGIC_ENABLE -# include "bootmagic.h" -#else -# include "magic.h" -#endif #ifdef MOUSEKEY_ENABLE # include "mousekey.h" #endif @@ -54,6 +49,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef RGBLIGHT_ENABLE # include "rgblight.h" #endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif #ifdef RGB_MATRIX_ENABLE # include "rgb_matrix.h" #endif @@ -96,6 +94,12 @@ 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 static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { return last_input_modification_time; } @@ -233,6 +237,12 @@ 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 matrix_setup(); keyboard_pre_init_kb(); } @@ -270,6 +280,15 @@ __attribute__((weak)) void housekeeping_task_kb(void) {} */ __attribute__((weak)) void housekeeping_task_user(void) {} +/** \brief housekeeping_task + * + * Invokes hooks for executing code after QMK is done after each loop iteration. + */ +void housekeeping_task(void) { + housekeeping_task_kb(); + housekeeping_task_user(); +} + /** \brief keyboard_init * * FIXME: needs doc @@ -296,11 +315,6 @@ void keyboard_init(void) { #ifdef ADB_MOUSE_ENABLE adb_mouse_init(); #endif -#ifdef BOOTMAGIC_ENABLE - bootmagic(); -#else - magic(); -#endif #ifdef BACKLIGHT_ENABLE backlight_init(); #endif @@ -337,6 +351,9 @@ void keyboard_init(void) { * This is differnet than keycode events as no layer processing, or filtering occurs. */ void switch_events(uint8_t row, uint8_t col, bool pressed) { +#if defined(LED_MATRIX_ENABLE) + process_led_matrix(row, col, pressed); +#endif #if defined(RGB_MATRIX_ENABLE) process_rgb_matrix(row, col, pressed); #endif @@ -366,9 +383,6 @@ void keyboard_task(void) { bool encoders_changed = false; #endif - housekeeping_task_kb(); - housekeeping_task_user(); - uint8_t matrix_changed = matrix_scan(); if (matrix_changed) last_matrix_activity_trigger(); @@ -422,6 +436,9 @@ MATRIX_LOOP_END: rgblight_task(); #endif +#ifdef LED_MATRIX_ENABLE + led_matrix_task(); +#endif #ifdef RGB_MATRIX_ENABLE rgb_matrix_task(); #endif diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index eaf74bac58..08f4e84f94 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -70,8 +70,9 @@ void keyboard_pre_init_user(void); void keyboard_post_init_kb(void); void keyboard_post_init_user(void); -void housekeeping_task_kb(void); -void housekeeping_task_user(void); +void housekeeping_task(void); // To be executed by the main loop in each backend TMK protocol +void housekeeping_task_kb(void); // To be overridden by keyboard-level code +void housekeeping_task_user(void); // To be overridden by user/keymap-level code uint32_t last_input_activity_time(void); // Timestamp of the last matrix or encoder activity uint32_t last_input_activity_elapsed(void); // Number of milliseconds since the last matrix or encoder activity diff --git a/tmk_core/common/magic.c b/tmk_core/common/magic.c deleted file mode 100644 index e14994164e..0000000000 --- a/tmk_core/common/magic.c +++ /dev/null @@ -1,39 +0,0 @@ -#include <stdint.h> -#include <stdbool.h> -#if defined(__AVR__) -# include <util/delay.h> -#endif -#include "matrix.h" -#include "bootloader.h" -#include "debug.h" -#include "keymap.h" -#include "host.h" -#include "action_layer.h" -#include "eeconfig.h" -#include "magic.h" - -keymap_config_t keymap_config; - -/** \brief Magic - * - * FIXME: Needs doc - */ -void magic(void) { - /* check signature */ - if (!eeconfig_is_enabled()) { - eeconfig_init(); - } - - /* debug enable */ - debug_config.raw = eeconfig_read_debug(); - - /* keymap config */ - keymap_config.raw = eeconfig_read_keymap(); - - uint8_t default_layer = 0; - default_layer = eeconfig_read_default_layer(); - default_layer_set((layer_state_t)default_layer); - - /* Also initialize layer state to trigger callback functions for layer_state */ - layer_state_set_kb((layer_state_t)layer_state); -} diff --git a/tmk_core/common/magic.h b/tmk_core/common/magic.h deleted file mode 100644 index a6552c04dc..0000000000 --- a/tmk_core/common/magic.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void magic(void); diff --git a/tmk_core/common/test/_wait.h b/tmk_core/common/test/_wait.h new file mode 100644 index 0000000000..4e22f593b7 --- /dev/null +++ b/tmk_core/common/test/_wait.h @@ -0,0 +1,22 @@ +/* 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 3 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 <inttypes.h> + +void wait_ms(uint32_t ms); +#define wait_us(us) wait_ms(us / 1000) +#define waitInputPinDelay() diff --git a/tmk_core/common/usb_util.c b/tmk_core/common/usb_util.c new file mode 100644 index 0000000000..e4c50fcb10 --- /dev/null +++ b/tmk_core/common/usb_util.c @@ -0,0 +1,29 @@ +/* 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 3 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 "usb_util.h" +#include "wait.h" + +__attribute__((weak)) void usb_disable(void) {} +__attribute__((weak)) bool usb_connected_state(void) { return true; } +__attribute__((weak)) bool usb_vbus_state(void) { +#ifdef USB_VBUS_PIN + setPinInput(USB_VBUS_PIN); + wait_us(5); + return readPin(USB_VBUS_PIN); +#else + return true; +#endif +} diff --git a/tmk_core/common/usb_util.h b/tmk_core/common/usb_util.h new file mode 100644 index 0000000000..4ebedb1e71 --- /dev/null +++ b/tmk_core/common/usb_util.h @@ -0,0 +1,22 @@ +/* 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 3 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 <stdbool.h> + +void usb_disable(void); +bool usb_connected_state(void); +bool usb_vbus_state(void); diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h index 28224fe3aa..cf7180fb07 100644 --- a/tmk_core/common/wait.h +++ b/tmk_core/common/wait.h @@ -1,3 +1,18 @@ +/* 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 3 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 <inttypes.h> @@ -6,114 +21,8 @@ extern "C" { #endif -#if defined(__ARMEL__) || defined(__ARMEB__) -# ifndef __OPTIMIZE__ -# pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" -# endif - -# define wait_cpuclock(x) wait_cpuclock_allnop(x) - -# define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" - -__attribute__((always_inline)) static inline void wait_cpuclock_allnop(unsigned int n) { /* n: 1..135 */ - /* The argument n must be a constant expression. - * That way, compiler optimization will remove unnecessary code. */ - if (n < 1) { - return; - } - if (n > 8) { - unsigned int n8 = n / 8; - n = n - n8 * 8; - switch (n8) { - case 16: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 15: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 14: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 13: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 12: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 11: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 10: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 9: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 8: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 7: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 6: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 5: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 4: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 3: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 2: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 1: - asm volatile(CLOCK_DELAY_NOP8::: "memory"); - case 0: - break; - } - } - switch (n) { - case 8: - asm volatile("nop" ::: "memory"); - case 7: - asm volatile("nop" ::: "memory"); - case 6: - asm volatile("nop" ::: "memory"); - case 5: - asm volatile("nop" ::: "memory"); - case 4: - asm volatile("nop" ::: "memory"); - case 3: - asm volatile("nop" ::: "memory"); - case 2: - asm volatile("nop" ::: "memory"); - case 1: - asm volatile("nop" ::: "memory"); - case 0: - break; - } -} -#endif - -#if defined(__AVR__) -# include <util/delay.h> -# define wait_ms(ms) _delay_ms(ms) -# define wait_us(us) _delay_us(us) -# define wait_cpuclock(x) __builtin_avr_delay_cycles(x) -#elif defined PROTOCOL_CHIBIOS -# include <ch.h> -# define wait_ms(ms) \ - do { \ - if (ms != 0) { \ - chThdSleepMilliseconds(ms); \ - } else { \ - chThdSleepMicroseconds(1); \ - } \ - } while (0) -# define wait_us(us) \ - do { \ - if (us != 0) { \ - chThdSleepMicroseconds(us); \ - } else { \ - chThdSleepMicroseconds(1); \ - } \ - } while (0) -#elif defined PROTOCOL_ARM_ATSAM -# include "clks.h" -# define wait_ms(ms) CLK_delay_ms(ms) -# define wait_us(us) CLK_delay_us(us) -#else // Unit tests -void wait_ms(uint32_t ms); -# define wait_us(us) wait_ms(us / 1000) +#if __has_include_next("_wait.h") +# include_next "_wait.h" /* Include the platforms _wait.h */ #endif #ifdef __cplusplus diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index 0c41642b9b..cc87e83478 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk @@ -54,5 +54,9 @@ ifeq ($(strip $(XT_ENABLE)), yes) OPT_DEFS += -DXT_ENABLE endif +ifeq ($(strip $(USB_HID_ENABLE)), yes) + include $(TMK_DIR)/protocol/usb_hid.mk +endif + # Search Path VPATH += $(TMK_DIR)/protocol diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index ab5e9a9852..ce0f54593c 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -305,5 +305,10 @@ int main(void) { // dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n", v_5v, v_5v_avg, v_5v_avg - V5_LOW, v_5v_avg - V5_HIGH, gcr_actual, gcr_desired); } #endif // CONSOLE_ENABLE + + // Run housekeeping + housekeeping_task(); + } + return 1; } diff --git a/tmk_core/protocol/chibios.mk b/tmk_core/protocol/chibios.mk index 80554abb32..d01697835b 100644 --- a/tmk_core/protocol/chibios.mk +++ b/tmk_core/protocol/chibios.mk @@ -6,6 +6,7 @@ SRC += $(CHIBIOS_DIR)/usb_main.c SRC += $(CHIBIOS_DIR)/main.c SRC += usb_descriptor.c SRC += $(CHIBIOS_DIR)/usb_driver.c +SRC += $(CHIBIOS_DIR)/usb_util.c SRC += $(LIBSRC) VPATH += $(TMK_PATH)/$(PROTOCOL_DIR) diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index 6cd88be577..2661e58873 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c @@ -51,12 +51,6 @@ #ifdef MIDI_ENABLE # include "qmk_midi.h" #endif -#ifdef STM32_EEPROM_ENABLE -# include "eeprom_stm32.h" -#endif -#ifdef EEPROM_DRIVER -# include "eeprom_driver.h" -#endif #include "suspend.h" #include "wait.h" @@ -154,13 +148,6 @@ int main(void) { halInit(); chSysInit(); -#ifdef STM32_EEPROM_ENABLE - EEPROM_Init(); -#endif -#ifdef EEPROM_DRIVER - eeprom_driver_init(); -#endif - // TESTING // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); @@ -277,7 +264,6 @@ int main(void) { #endif // Run housekeeping - housekeeping_task_kb(); - housekeeping_task_user(); + housekeeping_task(); } } diff --git a/tmk_core/protocol/chibios/usb_util.c b/tmk_core/protocol/chibios/usb_util.c new file mode 100644 index 0000000000..5945e8a8de --- /dev/null +++ b/tmk_core/protocol/chibios/usb_util.c @@ -0,0 +1,21 @@ +/* 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 3 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 <hal.h> +#include "usb_util.h" + +void usb_disable(void) { usbStop(&USBD1); } + +bool usb_connected_state(void) { return usbGetDriverStateI(&USBD1) == USB_ACTIVE; } diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk index 1cc1fa04e5..514d5fac41 100644 --- a/tmk_core/protocol/lufa.mk +++ b/tmk_core/protocol/lufa.mk @@ -44,6 +44,7 @@ ifeq ($(strip $(VIRTSER_ENABLE)), yes) endif SRC += $(LUFA_SRC) +SRC += $(LUFA_DIR)/usb_util.c # Search Path VPATH += $(TMK_PATH)/$(LUFA_DIR) @@ -66,8 +67,8 @@ LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1 -# Remote wakeup fix for ATmega32U2 https://github.com/tmk/tmk_keyboard/issues/361 -ifeq ($(MCU),atmega32u2) +# Remote wakeup fix for ATmega16/32U2 https://github.com/tmk/tmk_keyboard/issues/361 +ifneq (,$(filter $(MCU), at90usb162 atmega16u2 atmega32u2)) LUFA_OPTS += -DNO_LIMITED_CONTROLLER_CONNECT endif diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index b1af36d113..5976470b6e 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -1238,8 +1238,7 @@ int main(void) { #endif // Run housekeeping - housekeeping_task_kb(); - housekeeping_task_user(); + housekeeping_task(); } } diff --git a/tmk_core/protocol/lufa/usb_util.c b/tmk_core/protocol/lufa/usb_util.c new file mode 100644 index 0000000000..9e943a21b9 --- /dev/null +++ b/tmk_core/protocol/lufa/usb_util.c @@ -0,0 +1,34 @@ +/* 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 3 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 <LUFA/Drivers/USB/USB.h> +#include "usb_util.h" +#include "wait.h" + +void usb_disable(void) { + USB_Disable(); + USB_DeviceState = DEVICE_STATE_Unattached; +} + +bool usb_connected_state(void) { return USB_Device_IsAddressSet(); } + +#if defined(OTGPADE) +bool usb_vbus_state(void) { + USB_OTGPAD_On(); // enables VBUS pad + wait_us(5); + + return USB_VBUS_GetStatus(); // checks state of VBUS +} +#endif diff --git a/tmk_core/protocol/vusb.mk b/tmk_core/protocol/vusb.mk index 1de6003089..e4d013b38d 100644 --- a/tmk_core/protocol/vusb.mk +++ b/tmk_core/protocol/vusb.mk @@ -5,6 +5,7 @@ VUSB_PATH = $(LIB_PATH)/vusb SRC += $(VUSB_DIR)/main.c \ $(VUSB_DIR)/vusb.c \ + $(VUSB_DIR)/usb_util.c \ $(VUSB_PATH)/usbdrv/usbdrv.c \ $(VUSB_PATH)/usbdrv/usbdrvasm.S \ $(VUSB_PATH)/usbdrv/oddebug.c diff --git a/tmk_core/protocol/vusb/usb_util.c b/tmk_core/protocol/vusb/usb_util.c new file mode 100644 index 0000000000..602854dbe6 --- /dev/null +++ b/tmk_core/protocol/vusb/usb_util.c @@ -0,0 +1,24 @@ +/* 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 3 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 <usbdrv/usbdrv.h> +#include "usb_util.h" + +void usb_disable(void) { usbDeviceDisconnect(); } + +bool usb_connected_state(void) { + usbPoll(); + return usbConfiguration; +} diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk index bbcfc1e4d1..fc2dc68be2 100644 --- a/tmk_core/rules.mk +++ b/tmk_core/rules.mk @@ -223,6 +223,12 @@ ifneq ($(filter Darwin FreeBSD,$(shell uname -s)),) MD5SUM = md5 endif +# UF2 format settings +# To produce a UF2 file in your build, add to your keyboard's rules.mk: +# FIRMWARE_FORMAT = uf2 +UF2CONV = $(TOP_DIR)/util/uf2conv.py +UF2_FAMILY ?= 0x0 + # Compiler flags to generate dependency files. #GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d GENDEPFLAGS = -MMD -MP -MF $(patsubst %.o,%.td,$@) @@ -255,6 +261,7 @@ DFU_SUFFIX_ARGS ?= elf: $(BUILD_DIR)/$(TARGET).elf hex: $(BUILD_DIR)/$(TARGET).hex +uf2: $(BUILD_DIR)/$(TARGET).uf2 cpfirmware: $(FIRMWARE_FORMAT) $(SILENT) || printf "Copying $(TARGET).$(FIRMWARE_FORMAT) to qmk_firmware folder" | $(AWK_CMD) $(COPY) $(BUILD_DIR)/$(TARGET).$(FIRMWARE_FORMAT) $(TARGET).$(FIRMWARE_FORMAT) && $(PRINT_OK) @@ -283,34 +290,46 @@ gccversion : # Create final output files (.hex, .eep) from ELF output file. %.hex: %.elf - @$(SILENT) || printf "$(MSG_FLASH) $@" | $(AWK_CMD) $(eval CMD=$(HEX) $< $@) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_FLASH) $@" | $(AWK_CMD) + @$(BUILD_CMD) + +%.uf2: %.hex + $(eval CMD=$(UF2CONV) $(BUILD_DIR)/$(TARGET).hex -o $(BUILD_DIR)/$(TARGET).uf2 -c -f $(UF2_FAMILY) >/dev/null 2>&1) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_UF2) $@" | $(AWK_CMD) @$(BUILD_CMD) %.eep: %.elf - @$(SILENT) || printf "$(MSG_EEPROM) $@" | $(AWK_CMD) $(eval CMD=$(EEP) $< $@ || exit 0) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_EEPROM) $@" | $(AWK_CMD) @$(BUILD_CMD) # Create extended listing file from ELF output file. %.lss: %.elf - @$(SILENT) || printf "$(MSG_EXTENDED_LISTING) $@" | $(AWK_CMD) $(eval CMD=$(OBJDUMP) -h -S -z $< > $@) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_EXTENDED_LISTING) $@" | $(AWK_CMD) @$(BUILD_CMD) # Create a symbol table from ELF output file. %.sym: %.elf - @$(SILENT) || printf "$(MSG_SYMBOL_TABLE) $@" | $(AWK_CMD) $(eval CMD=$(NM) -n $< > $@ ) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_SYMBOL_TABLE) $@" | $(AWK_CMD) @$(BUILD_CMD) %.bin: %.elf - @$(SILENT) || printf "$(MSG_BIN) $@" | $(AWK_CMD) $(eval CMD=$(BIN) $< $@ || exit 0) + #@$(SILENT) || printf "$(MSG_EXECUTING) '$(CMD)':\n" + @$(SILENT) || printf "$(MSG_BIN) $@" | $(AWK_CMD) @$(BUILD_CMD) if [ ! -z "$(DFU_SUFFIX_ARGS)" ]; then \ $(DFU_SUFFIX) $(DFU_SUFFIX_ARGS) -a $(BUILD_DIR)/$(TARGET).bin 1>/dev/null ;\ fi + #$(SILENT) || printf "$(MSG_EXECUTING) '$(DFU_SUFFIX) $(DFU_SUFFIX_ARGS) -a $(BUILD_DIR)/$(TARGET).bin 1>/dev/null':\n" ;\ $(COPY) $(BUILD_DIR)/$(TARGET).bin $(TARGET).bin; BEGIN = gccversion sizebefore @@ -476,7 +495,7 @@ $(eval $(foreach OUTPUT,$(OUTPUTS),$(shell mkdir -p $(OUTPUT) 2>/dev/null))) # Listing of phony targets. .PHONY : all dump_vars finish sizebefore sizeafter qmkversion \ -gccversion build elf hex eep lss sym coff extcoff \ +gccversion build elf hex uf2 eep lss sym coff extcoff \ clean clean_list debug gdb-config show_path \ program teensy dfu dfu-ee dfu-start \ flash dfu-split-left dfu-split-right \ diff --git a/util/install/arch.sh b/util/install/arch.sh index 7442e2f136..eac4ad64ef 100755 --- a/util/install/arch.sh +++ b/util/install/arch.sh @@ -4,13 +4,13 @@ _qmk_install() { echo "Installing dependencies" sudo pacman --needed --noconfirm -S \ - base-devel clang diffutils gcc git unzip wget zip \ - python-pip \ - avr-binutils \ - arm-none-eabi-binutils arm-none-eabi-gcc arm-none-eabi-newlib \ - avrdude dfu-programmer dfu-util + base-devel clang diffutils gcc git unzip wget zip python-pip \ + avr-binutils arm-none-eabi-binutils arm-none-eabi-gcc \ + arm-none-eabi-newlib avrdude dfu-programmer dfu-util sudo pacman --needed --noconfirm -U https://archive.archlinux.org/packages/a/avr-gcc/avr-gcc-8.3.0-1-x86_64.pkg.tar.xz sudo pacman --needed --noconfirm -S avr-libc # Must be installed after the above, or it will bring in the latest avr-gcc instead + sudo pacman --needed --noconfirm -S hidapi # This will fail if the community repo isn't enabled + python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt } diff --git a/util/install/debian.sh b/util/install/debian.sh index 885df723d9..9e12996976 100755 --- a/util/install/debian.sh +++ b/util/install/debian.sh @@ -13,10 +13,9 @@ _qmk_install() { sudo apt-get -yq install \ build-essential clang-format diffutils gcc git unzip wget zip \ - python3-pip \ - binutils-avr gcc-avr avr-libc \ - binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi \ - avrdude dfu-programmer dfu-util teensy-loader-cli libusb-dev + python3-pip binutils-avr gcc-avr avr-libc binutils-arm-none-eabi \ + gcc-arm-none-eabi libnewlib-arm-none-eabi avrdude dfu-programmer \ + dfu-util teensy-loader-cli libhidapi-hidraw0 libusb-dev python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt } diff --git a/util/install/fedora.sh b/util/install/fedora.sh index d9452f68d5..3f9695356c 100755 --- a/util/install/fedora.sh +++ b/util/install/fedora.sh @@ -5,11 +5,10 @@ _qmk_install() { # TODO: Check whether devel/headers packages are really needed sudo dnf $SKIP_PROMPT install \ - clang diffutils git gcc glibc-headers kernel-devel kernel-headers make unzip wget zip \ - python3 \ - avr-binutils avr-gcc avr-libc \ + clang diffutils git gcc glibc-headers kernel-devel kernel-headers \ + make unzip wget zip python3 avr-binutils avr-gcc avr-libc \ arm-none-eabi-binutils-cs arm-none-eabi-gcc-cs arm-none-eabi-newlib \ - avrdude dfu-programmer dfu-util libusb-devel + avrdude dfu-programmer dfu-util hidapi python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt } diff --git a/util/install/gentoo.sh b/util/install/gentoo.sh index 97eb5df07f..604d07bf84 100755 --- a/util/install/gentoo.sh +++ b/util/install/gentoo.sh @@ -22,9 +22,10 @@ _qmk_install() { echo "sys-devel/gcc multilib" | sudo tee --append /etc/portage/package.use/qmkfirmware >/dev/null sudo emerge -auN sys-devel/gcc sudo emerge -au --noreplace \ - app-arch/unzip app-arch/zip net-misc/wget sys-devel/clang sys-devel/crossdev \ - \>=dev-lang/python-3.7 \ - dev-embedded/avrdude dev-embedded/dfu-programmer app-mobilephone/dfu-util + app-arch/unzip app-arch/zip net-misc/wget sys-devel/clang \ + sys-devel/crossdev \>=dev-lang/python-3.7 dev-embedded/avrdude \ + dev-embedded/dfu-programmer app-mobilephone/dfu-util sys-apps/hwloc \ + dev-libs/hidapi sudo crossdev -s4 --stable --g \<9 --portage --verbose --target avr sudo crossdev -s4 --stable --g \<9 --portage --verbose --target arm-none-eabi diff --git a/util/install/msys2.sh b/util/install/msys2.sh index b1300a34d2..b027ff53d2 100755 --- a/util/install/msys2.sh +++ b/util/install/msys2.sh @@ -9,11 +9,10 @@ _qmk_install() { pacman --needed --noconfirm --disable-download-timeout -S pactoys-git pacboy sync --needed --noconfirm --disable-download-timeout \ - base-devel: toolchain:x clang:x git: unzip: \ - python3-pip:x \ - avr-binutils:x avr-gcc:x avr-libc:x \ - arm-none-eabi-binutils:x arm-none-eabi-gcc:x arm-none-eabi-newlib:x \ - avrdude:x bootloadhid:x dfu-programmer:x dfu-util:x teensy-loader-cli:x + base-devel: toolchain:x clang:x git: unzip: python3-pip:x \ + avr-binutils:x avr-gcc:x avr-libc:x arm-none-eabi-binutils:x \ + arm-none-eabi-gcc:x arm-none-eabi-newlib:x avrdude:x bootloadhid:x \ + dfu-programmer:x dfu-util:x teensy-loader-cli:x hidapi:x _qmk_install_drivers diff --git a/util/udev/50-qmk.rules b/util/udev/50-qmk.rules index acaa7dcc58..679fe4ced3 100644 --- a/util/udev/50-qmk.rules +++ b/util/udev/50-qmk.rules @@ -60,3 +60,6 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="239a", ATTRS{idProduct}=="000e", TAG+="uacc SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0036", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" ### Micro SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0037", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" + +# hid_listen +KERNEL=="hidraw*", MODE="0660", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl" diff --git a/util/uf2conv.py b/util/uf2conv.py new file mode 100755 index 0000000000..044a7f2318 --- /dev/null +++ b/util/uf2conv.py @@ -0,0 +1,319 @@ +#!/usr/bin/env python3 +import sys +import struct +import subprocess +import re +import os +import os.path +import argparse + + +UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" +UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected +UF2_MAGIC_END = 0x0AB16F30 # Ditto + +families = { + 'SAMD21': 0x68ed2b88, + 'SAML21': 0x1851780a, + 'SAMD51': 0x55114460, + 'NRF52': 0x1b57745f, + 'STM32F0': 0x647824b6, + 'STM32F1': 0x5ee21072, + 'STM32F2': 0x5d1a0a2e, + 'STM32F3': 0x6b846188, + 'STM32F4': 0x57755a57, + 'STM32F7': 0x53b80f00, + 'STM32G0': 0x300f5633, + 'STM32G4': 0x4c71240a, + 'STM32H7': 0x6db66082, + 'STM32L0': 0x202e3a91, + 'STM32L1': 0x1e1f432d, + 'STM32L4': 0x00ff6919, + 'STM32L5': 0x04240bdf, + 'STM32WB': 0x70d16653, + 'STM32WL': 0x21460ff0, + 'ATMEGA32': 0x16573617, + 'MIMXRT10XX': 0x4FB2D5BD, + 'LPC55': 0x2abc77ec, + 'GD32F350': 0x31D228C6, + 'ESP32S2': 0xbfdd4eee, + 'RP2040': 0xe48bff56 +} + +INFO_FILE = "/INFO_UF2.TXT" + +appstartaddr = 0x2000 +familyid = 0x0 + + +def is_uf2(buf): + w = struct.unpack("<II", buf[0:8]) + return w[0] == UF2_MAGIC_START0 and w[1] == UF2_MAGIC_START1 + +def is_hex(buf): + try: + w = buf[0:30].decode("utf-8") + except UnicodeDecodeError: + return False + if w[0] == ':' and re.match(b"^[:0-9a-fA-F\r\n]+$", buf): + return True + return False + +def convert_from_uf2(buf): + global appstartaddr + numblocks = len(buf) // 512 + curraddr = None + outp = [] + for blockno in range(numblocks): + ptr = blockno * 512 + block = buf[ptr:ptr + 512] + hd = struct.unpack(b"<IIIIIIII", block[0:32]) + if hd[0] != UF2_MAGIC_START0 or hd[1] != UF2_MAGIC_START1: + print("Skipping block at " + ptr + "; bad magic") + continue + if hd[2] & 1: + # NO-flash flag set; skip block + continue + datalen = hd[4] + if datalen > 476: + assert False, "Invalid UF2 data size at " + ptr + newaddr = hd[3] + if curraddr == None: + appstartaddr = newaddr + curraddr = newaddr + padding = newaddr - curraddr + if padding < 0: + assert False, "Block out of order at " + ptr + if padding > 10*1024*1024: + assert False, "More than 10M of padding needed at " + ptr + if padding % 4 != 0: + assert False, "Non-word padding size at " + ptr + while padding > 0: + padding -= 4 + outp += b"\x00\x00\x00\x00" + outp.append(block[32 : 32 + datalen]) + curraddr = newaddr + datalen + return b"".join(outp) + +def convert_to_carray(file_content): + outp = "const unsigned long bindata_len = %d;\n" % len(file_content) + outp += "const unsigned char bindata[] __attribute__((aligned(16))) = {" + for i in range(len(file_content)): + if i % 16 == 0: + outp += "\n" + outp += "0x%02x, " % file_content[i] + outp += "\n};\n" + return bytes(outp, "utf-8") + +def convert_to_uf2(file_content): + global familyid + datapadding = b"" + while len(datapadding) < 512 - 256 - 32 - 4: + datapadding += b"\x00\x00\x00\x00" + numblocks = (len(file_content) + 255) // 256 + outp = [] + for blockno in range(numblocks): + ptr = 256 * blockno + chunk = file_content[ptr:ptr + 256] + flags = 0x0 + if familyid: + flags |= 0x2000 + hd = struct.pack(b"<IIIIIIII", + UF2_MAGIC_START0, UF2_MAGIC_START1, + flags, ptr + appstartaddr, 256, blockno, numblocks, familyid) + while len(chunk) < 256: + chunk += b"\x00" + block = hd + chunk + datapadding + struct.pack(b"<I", UF2_MAGIC_END) + assert len(block) == 512 + outp.append(block) + return b"".join(outp) + +class Block: + def __init__(self, addr): + self.addr = addr + self.bytes = bytearray(256) + + def encode(self, blockno, numblocks): + global familyid + flags = 0x0 + if familyid: + flags |= 0x2000 + hd = struct.pack("<IIIIIIII", + UF2_MAGIC_START0, UF2_MAGIC_START1, + flags, self.addr, 256, blockno, numblocks, familyid) + hd += self.bytes[0:256] + while len(hd) < 512 - 4: + hd += b"\x00" + hd += struct.pack("<I", UF2_MAGIC_END) + return hd + +def convert_from_hex_to_uf2(buf): + global appstartaddr + appstartaddr = None + upper = 0 + currblock = None + blocks = [] + for line in buf.split('\n'): + if line[0] != ":": + continue + i = 1 + rec = [] + while i < len(line) - 1: + rec.append(int(line[i:i+2], 16)) + i += 2 + tp = rec[3] + if tp == 4: + upper = ((rec[4] << 8) | rec[5]) << 16 + elif tp == 2: + upper = ((rec[4] << 8) | rec[5]) << 4 + assert (upper & 0xffff) == 0 + elif tp == 1: + break + elif tp == 0: + addr = upper | (rec[1] << 8) | rec[2] + if appstartaddr == None: + appstartaddr = addr + i = 4 + while i < len(rec) - 1: + if not currblock or currblock.addr & ~0xff != addr & ~0xff: + currblock = Block(addr & ~0xff) + blocks.append(currblock) + currblock.bytes[addr & 0xff] = rec[i] + addr += 1 + i += 1 + numblocks = len(blocks) + resfile = b"" + for i in range(0, numblocks): + resfile += blocks[i].encode(i, numblocks) + return resfile + +def to_str(b): + return b.decode("utf-8") + +def get_drives(): + drives = [] + if sys.platform == "win32": + r = subprocess.check_output(["wmic", "PATH", "Win32_LogicalDisk", + "get", "DeviceID,", "VolumeName,", + "FileSystem,", "DriveType"]) + for line in to_str(r).split('\n'): + words = re.split('\s+', line) + if len(words) >= 3 and words[1] == "2" and words[2] == "FAT": + drives.append(words[0]) + else: + rootpath = "/media" + if sys.platform == "darwin": + rootpath = "/Volumes" + elif sys.platform == "linux": + tmp = rootpath + "/" + os.environ["USER"] + if os.path.isdir(tmp): + rootpath = tmp + for d in os.listdir(rootpath): + drives.append(os.path.join(rootpath, d)) + + + def has_info(d): + try: + return os.path.isfile(d + INFO_FILE) + except: + return False + + return list(filter(has_info, drives)) + + +def board_id(path): + with open(path + INFO_FILE, mode='r') as file: + file_content = file.read() + return re.search("Board-ID: ([^\r\n]*)", file_content).group(1) + + +def list_drives(): + for d in get_drives(): + print(d, board_id(d)) + + +def write_file(name, buf): + with open(name, "wb") as f: + f.write(buf) + print("Wrote %d bytes to %s" % (len(buf), name)) + + +def main(): + global appstartaddr, familyid + def error(msg): + print(msg) + sys.exit(1) + parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.') + parser.add_argument('input', metavar='INPUT', type=str, nargs='?', + help='input file (HEX, BIN or UF2)') + parser.add_argument('-b' , '--base', dest='base', type=str, + default="0x2000", + help='set base address of application for BIN format (default: 0x2000)') + parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str, + help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible') + parser.add_argument('-d' , '--device', dest="device_path", + help='select a device path to flash') + parser.add_argument('-l' , '--list', action='store_true', + help='list connected devices') + parser.add_argument('-c' , '--convert', action='store_true', + help='do not flash, just convert') + parser.add_argument('-D' , '--deploy', action='store_true', + help='just flash, do not convert') + parser.add_argument('-f' , '--family', dest='family', type=str, + default="0x0", + help='specify familyID - number or name (default: 0x0)') + parser.add_argument('-C' , '--carray', action='store_true', + help='convert binary file to a C array, not UF2') + args = parser.parse_args() + appstartaddr = int(args.base, 0) + + if args.family.upper() in families: + familyid = families[args.family.upper()] + else: + try: + familyid = int(args.family, 0) + except ValueError: + error("Family ID needs to be a number or one of: " + ", ".join(families.keys())) + + if args.list: + list_drives() + else: + if not args.input: + error("Need input file") + with open(args.input, mode='rb') as f: + inpbuf = f.read() + from_uf2 = is_uf2(inpbuf) + ext = "uf2" + if args.deploy: + outbuf = inpbuf + elif from_uf2: + outbuf = convert_from_uf2(inpbuf) + ext = "bin" + elif is_hex(inpbuf): + outbuf = convert_from_hex_to_uf2(inpbuf.decode("utf-8")) + elif args.carray: + outbuf = convert_to_carray(inpbuf) + ext = "h" + else: + outbuf = convert_to_uf2(inpbuf) + print("Converting to %s, output size: %d, start address: 0x%x" % + (ext, len(outbuf), appstartaddr)) + if args.convert or ext != "uf2": + drives = [] + if args.output == None: + args.output = "flash." + ext + else: + drives = get_drives() + + if args.output: + write_file(args.output, outbuf) + else: + if len(drives) == 0: + error("No drive to deploy.") + for d in drives: + print("Flashing %s (%s)" % (d, board_id(d))) + write_file(d + "/NEW.UF2", outbuf) + + +if __name__ == "__main__": + main() |