From 4d8d69237d0a9e73e1723480e4225c9390533021 Mon Sep 17 00:00:00 2001 From: James Young <18669334+noroadsleft@users.noreply.github.com> Date: Sat, 28 Nov 2020 12:02:18 -0800 Subject: [PATCH] 2020 November 28 Breaking Changes Update (#11053) * Branch point for 2020 November 28 Breaking Change * Remove matrix_col_t to allow MATRIX_ROWS > 32 (#10183) * Add support for soft serial to ATmega32U2 (#10204) * Change MIDI velocity implementation to allow direct control of velocity value (#9940) * Add ability to build a subset of all keyboards based on platform. * Actually use eeprom_driver_init(). * Make bootloader_jump weak for ChibiOS. (#10417) * Joystick 16-bit support (#10439) * Per-encoder resolutions (#10259) * Share button state from mousekey to pointing_device (#10179) * Add hotfix for chibios keyboards not wake (#10088) * Add advanced/efficient RGB Matrix Indicators (#8564) * Naming change. * Support for STM32 GPIOF,G,H,I,J,K (#10206) * Add milc as a dependency and remove the installed milc (#10563) * ChibiOS upgrade: early init conversions (#10214) * ChibiOS upgrade: configuration file migrator (#9952) * Haptic and solenoid cleanup (#9700) * XD75 cleanup (#10524) * OLED display update interval support (#10388) * Add definition based on currently-selected serial driver. (#10716) * New feature: Retro Tapping per key (#10622) * Allow for modification of output RGB values when using rgblight/rgb_matrix. (#10638) * Add housekeeping task callbacks so that keyboards/keymaps are capable of executing code for each main loop iteration. (#10530) * Rescale both ChibiOS and AVR backlighting. * Reduce Helix keyboard build variation (#8669) * Minor change to behavior allowing display updates to continue between task ticks (#10750) * Some GPIO manipulations in matrix.c change to atomic. (#10491) * qmk cformat (#10767) * [Keyboard] Update the Speedo firmware for v3.0 (#10657) * Maartenwut/Maarten namechange to evyd13/Evy (#10274) * [quantum] combine repeated lines of code (#10837) * Add step sequencer feature (#9703) * aeboards/ext65 refactor (#10820) * Refactor xelus/dawn60 for Rev2 later (#10584) * add DEBUG_MATRIX_SCAN_RATE_ENABLE to common_features.mk (#10824) * [Core] Added `add_oneshot_mods` & `del_oneshot_mods` (#10549) * update chibios os usb for the otg driver (#8893) * Remove HD44780 References, Part 4 (#10735) * [Keyboard] Add Valor FRL TKL (+refactor) (#10512) * Fix cursor position bug in oled_write_raw functions (#10800) * Fixup version.h writing when using SKIP_VERSION=yes (#10972) * Allow for certain code in the codebase assuming length of string. (#10974) * Add AT90USB support for serial.c (#10706) * Auto shift: support repeats and early registration (#9826) * Rename ledmatrix.h to match .c file (#7949) * Split RGB_MATRIX_ENABLE into _ENABLE and _DRIVER (#10231) * Split LED_MATRIX_ENABLE into _ENABLE and _DRIVER (#10840) * Merge point for 2020 Nov 28 Breaking Change --- Makefile | 24 +- build_keyboard.mk | 13 + build_test.mk | 1 + common.mk | 1 + common_features.mk | 122 ++-- drivers/avr/serial.c | 139 +++-- drivers/chibios/i2c_master.c | 21 +- drivers/chibios/spi_master.c | 27 +- drivers/eeprom/eeprom_i2c.c | 12 +- drivers/eeprom/eeprom_spi.c | 14 +- drivers/haptic/haptic.c | 53 +- drivers/haptic/solenoid.c | 10 +- drivers/haptic/solenoid.h | 18 +- drivers/oled/oled_driver.c | 22 +- keyboards/ergodox_ez/rules.mk | 3 +- keyboards/moonlander/rules.mk | 3 +- keyboards/planck/ez/glow/rules.mk | 2 +- keyboards/planck/ez/rules.mk | 1 + keyboards/planck/planck.h | 23 +- lib/python/qmk/cli/__init__.py | 1 + lib/python/qmk/cli/chibios/__init__.py | 1 + lib/python/qmk/cli/chibios/confmigrate.py | 161 +++++ lib/python/qmk/cli/doctor.py | 2 +- lib/python/qmk/questions.py | 183 ------ message.mk | 3 + .../BLACKPILL_STM32_F401/configs/config.h | 4 +- .../BLACKPILL_STM32_F411/configs/config.h | 4 +- .../GENERIC_STM32_F042X6/configs/mcuconf.h | 168 +++++ .../GENERIC_STM32_F072XB/board/board.c | 250 -------- .../GENERIC_STM32_F072XB/board/board.h | 407 ------------ .../GENERIC_STM32_F072XB/board/board.mk | 4 +- .../GENERIC_STM32_F072XB/configs/board.h | 20 + .../GENERIC_STM32_F072XB/configs/mcuconf.h | 177 ++++++ .../GENERIC_STM32_F303XC/configs/config.h | 4 +- .../STM32_F103_STM32DUINO/configs/mcuconf.h | 209 +++++++ .../configs/chconf.h | 0 .../configs/halconf.h | 0 platforms/chibios/{ => common}/ld/MKL26Z64.ld | 0 .../ld/STM32F103x8_stm32duino_bootloader.ld | 0 quantum/backlight/backlight_avr.c | 12 +- quantum/backlight/backlight_chibios.c | 14 +- quantum/config_common.h | 92 ++- quantum/encoder.c | 24 +- quantum/joystick.h | 12 +- quantum/led_matrix.c | 2 +- quantum/{ledmatrix.h => led_matrix.h} | 0 quantum/led_matrix_drivers.c | 2 +- quantum/matrix.c | 35 +- quantum/mcu_selection.mk | 3 + quantum/process_keycode/process_auto_shift.c | 213 +++++-- quantum/process_keycode/process_auto_shift.h | 11 +- quantum/process_keycode/process_joystick.c | 8 +- quantum/process_keycode/process_midi.c | 25 +- quantum/process_keycode/process_midi.h | 2 +- quantum/process_keycode/process_sequencer.c | 62 ++ quantum/process_keycode/process_sequencer.h | 21 + quantum/quantum.c | 15 + quantum/quantum.h | 62 +- quantum/quantum_keycodes.h | 38 +- quantum/rgb_matrix.c | 32 +- quantum/rgb_matrix.h | 9 + .../rgb_matrix_animations/alpha_mods_anim.h | 4 +- .../rgb_matrix_animations/breathing_anim.h | 2 +- .../gradient_left_right_anim.h | 2 +- .../gradient_up_down_anim.h | 2 +- .../jellybean_raindrops_anim.h | 2 +- .../rgb_matrix_animations/raindrops_anim.h | 2 +- .../rgb_matrix_animations/solid_color_anim.h | 2 +- .../typing_heatmap_anim.h | 2 +- .../rgb_matrix_runners/effect_runner_dx_dy.h | 2 +- .../effect_runner_dx_dy_dist.h | 2 +- quantum/rgb_matrix_runners/effect_runner_i.h | 2 +- .../effect_runner_reactive.h | 2 +- .../effect_runner_reactive_splash.h | 2 +- .../effect_runner_sin_cos_i.h | 2 +- quantum/rgblight.c | 4 +- quantum/sequencer/sequencer.c | 275 ++++++++ quantum/sequencer/sequencer.h | 122 ++++ quantum/sequencer/tests/midi_mock.c | 26 + quantum/sequencer/tests/midi_mock.h | 26 + quantum/sequencer/tests/rules.mk | 11 + quantum/sequencer/tests/sequencer_tests.cpp | 590 ++++++++++++++++++ quantum/sequencer/tests/testlist.mk | 1 + quantum/split_common/matrix.c | 35 +- requirements.txt | 2 +- show_options.mk | 1 + testlist.mk | 1 + tmk_core/chibios.mk | 10 +- tmk_core/common/action.c | 66 +- tmk_core/common/action_util.c | 31 +- tmk_core/common/action_util.h | 7 +- tmk_core/common/arm_atsam/suspend.c | 2 +- tmk_core/common/chibios/bootloader.c | 10 +- tmk_core/common/eeconfig.c | 15 +- tmk_core/common/keyboard.c | 21 + tmk_core/common/keyboard.h | 3 + tmk_core/common/matrix.h | 10 - tmk_core/common/report.h | 4 + tmk_core/protocol/arm_atsam.mk | 6 +- .../protocol/arm_atsam/arm_atsam_protocol.h | 2 +- tmk_core/protocol/arm_atsam/main_arm_atsam.c | 4 + .../{led_matrix.c => md_rgb_matrix.c} | 12 +- .../{led_matrix.h => md_rgb_matrix.h} | 2 +- ...ix_programs.c => md_rgb_matrix_programs.c} | 2 +- tmk_core/protocol/chibios/main.c | 10 + tmk_core/protocol/chibios/usb_main.c | 81 +++ tmk_core/protocol/chibios/usb_main.h | 3 + tmk_core/protocol/lufa/lufa.c | 4 + tmk_core/protocol/usb_descriptor.c | 15 +- tmk_core/protocol/usb_descriptor.h | 20 + tmk_core/protocol/vusb/main.c | 4 + 111 files changed, 3034 insertions(+), 1235 deletions(-) create mode 100644 lib/python/qmk/cli/chibios/__init__.py create mode 100644 lib/python/qmk/cli/chibios/confmigrate.py delete mode 100644 lib/python/qmk/questions.py create mode 100644 platforms/chibios/GENERIC_STM32_F042X6/configs/mcuconf.h delete mode 100644 platforms/chibios/GENERIC_STM32_F072XB/board/board.c delete mode 100644 platforms/chibios/GENERIC_STM32_F072XB/board/board.h create mode 100644 platforms/chibios/GENERIC_STM32_F072XB/configs/board.h create mode 100644 platforms/chibios/GENERIC_STM32_F072XB/configs/mcuconf.h create mode 100644 platforms/chibios/STM32_F103_STM32DUINO/configs/mcuconf.h rename platforms/chibios/{GENERIC_STM32_F303XC => common}/configs/chconf.h (100%) rename platforms/chibios/{GENERIC_STM32_F303XC => common}/configs/halconf.h (100%) rename platforms/chibios/{ => common}/ld/MKL26Z64.ld (100%) rename platforms/chibios/{ => common}/ld/STM32F103x8_stm32duino_bootloader.ld (100%) rename quantum/{ledmatrix.h => led_matrix.h} (100%) create mode 100644 quantum/process_keycode/process_sequencer.c create mode 100644 quantum/process_keycode/process_sequencer.h create mode 100644 quantum/sequencer/sequencer.c create mode 100644 quantum/sequencer/sequencer.h create mode 100644 quantum/sequencer/tests/midi_mock.c create mode 100644 quantum/sequencer/tests/midi_mock.h create mode 100644 quantum/sequencer/tests/rules.mk create mode 100644 quantum/sequencer/tests/sequencer_tests.cpp create mode 100644 quantum/sequencer/tests/testlist.mk rename tmk_core/protocol/arm_atsam/{led_matrix.c => md_rgb_matrix.c} (98%) rename tmk_core/protocol/arm_atsam/{led_matrix.h => md_rgb_matrix.h} (99%) rename tmk_core/protocol/arm_atsam/{led_matrix_programs.c => md_rgb_matrix_programs.c} (99%) diff --git a/Makefile b/Makefile index 8f68a1ce7482..5d4ba58c0108 100644 --- a/Makefile +++ b/Makefile @@ -272,10 +272,23 @@ endef define PARSE_RULE RULE := $1 COMMANDS := + REQUIRE_PLATFORM_KEY := # If the rule starts with all, then continue the parsing from # PARSE_ALL_KEYBOARDS ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all),true) $$(eval $$(call PARSE_ALL_KEYBOARDS)) + else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all-avr),true) + KEYBOARD_RULE=all + REQUIRE_PLATFORM_KEY := avr + $$(eval $$(call PARSE_ALL_KEYBOARDS)) + else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all-chibios),true) + KEYBOARD_RULE=all + REQUIRE_PLATFORM_KEY := chibios + $$(eval $$(call PARSE_ALL_KEYBOARDS)) + else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,all-arm_atsam),true) + KEYBOARD_RULE=all + REQUIRE_PLATFORM_KEY := arm_atsam + $$(eval $$(call PARSE_ALL_KEYBOARDS)) else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,test),true) $$(eval $$(call PARSE_TEST)) # If the rule starts with the name of a known keyboard, then continue @@ -442,7 +455,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) + MAKE_VARS := KEYBOARD=$$(CURRENT_KB) KEYMAP=$$(CURRENT_KM) REQUIRE_PLATFORM_KEY=$$(REQUIRE_PLATFORM_KEY) # 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 @@ -461,6 +474,8 @@ define BUILD LOG=$$$$($$(MAKE_CMD) $$(MAKE_VARS) SILENT=true 2>&1) ; \ if [ $$$$? -gt 0 ]; \ then $$(PRINT_ERROR_PLAIN); \ + elif [ "$$$$LOG" = "skipped" ] ; \ + then $$(PRINT_SKIPPED_PLAIN); \ elif [ "$$$$LOG" != "" ] ; \ then $$(PRINT_WARNING_PLAIN); \ else \ @@ -632,12 +647,13 @@ else endif ifndef SKIP_VERSION BUILD_DATE := $(shell date +"%Y-%m-%d-%H:%M:%S") +else +BUILD_DATE := 2020-01-01-00:00:00 +endif + $(shell echo '#define QMK_VERSION "$(GIT_VERSION)"' > $(ROOT_DIR)/quantum/version.h) $(shell echo '#define QMK_BUILDDATE "$(BUILD_DATE)"' >> $(ROOT_DIR)/quantum/version.h) $(shell echo '#define CHIBIOS_VERSION "$(CHIBIOS_VERSION)"' >> $(ROOT_DIR)/quantum/version.h) $(shell echo '#define CHIBIOS_CONTRIB_VERSION "$(CHIBIOS_CONTRIB_VERSION)"' >> $(ROOT_DIR)/quantum/version.h) -else -BUILD_DATE := NA -endif include $(ROOT_DIR)/testlist.mk diff --git a/build_keyboard.mk b/build_keyboard.mk index 1d80d8982407..7bcfb51ed5ab 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -317,6 +317,13 @@ SRC += $(TMK_COMMON_SRC) OPT_DEFS += $(TMK_COMMON_DEFS) EXTRALDFLAGS += $(TMK_COMMON_LDFLAGS) +SKIP_COMPILE := no +ifneq ($(REQUIRE_PLATFORM_KEY),) + ifneq ($(REQUIRE_PLATFORM_KEY),$(PLATFORM_KEY)) + SKIP_COMPILE := yes + endif +endif + include $(TMK_PATH)/$(PLATFORM_KEY).mk ifneq ($(strip $(PROTOCOL)),) include $(TMK_PATH)/protocol/$(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]')).mk @@ -352,7 +359,13 @@ $(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC) $(GFXINC) $(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG) # Default target. +ifeq ($(SKIP_COMPILE),no) all: build check-size +else +all: + echo "skipped" >&2 +endif + build: elf cpfirmware check-size: build objs-size: build diff --git a/build_test.mk b/build_test.mk index d13d9a515b84..e705c6a3ba1b 100644 --- a/build_test.mk +++ b/build_test.mk @@ -49,6 +49,7 @@ endif include common_features.mk include $(TMK_PATH)/common.mk +include $(QUANTUM_PATH)/sequencer/tests/rules.mk include $(QUANTUM_PATH)/serial_link/tests/rules.mk ifneq ($(filter $(FULL_TESTS),$(TEST)),) include build_full_test.mk diff --git a/common.mk b/common.mk index aea29a7a20e2..c13b5e2768a7 100644 --- a/common.mk +++ b/common.mk @@ -21,4 +21,5 @@ COMMON_VPATH += $(QUANTUM_PATH)/keymap_extras COMMON_VPATH += $(QUANTUM_PATH)/audio COMMON_VPATH += $(QUANTUM_PATH)/process_keycode COMMON_VPATH += $(QUANTUM_PATH)/api +COMMON_VPATH += $(QUANTUM_PATH)/sequencer COMMON_VPATH += $(DRIVER_PATH) diff --git a/common_features.mk b/common_features.mk index f65b4cf81c6d..22cd53d8a3e7 100644 --- a/common_features.mk +++ b/common_features.mk @@ -21,6 +21,11 @@ QUANTUM_SRC += \ $(QUANTUM_DIR)/keymap_common.c \ $(QUANTUM_DIR)/keycode_config.c +ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes) + OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE + CONSOLE_ENABLE = yes +endif + ifeq ($(strip $(API_SYSEX_ENABLE)), yes) OPT_DEFS += -DAPI_SYSEX_ENABLE OPT_DEFS += -DAPI_ENABLE @@ -39,6 +44,13 @@ ifeq ($(strip $(AUDIO_ENABLE)), yes) SRC += $(QUANTUM_DIR)/audio/luts.c endif +ifeq ($(strip $(SEQUENCER_ENABLE)), yes) + OPT_DEFS += -DSEQUENCER_ENABLE + MUSIC_ENABLE = yes + SRC += $(QUANTUM_DIR)/sequencer/sequencer.c + SRC += $(QUANTUM_DIR)/process_keycode/process_sequencer.c +endif + ifeq ($(strip $(MIDI_ENABLE)), yes) OPT_DEFS += -DMIDI_ENABLE MUSIC_ENABLE = yes @@ -156,12 +168,14 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) endif endif -VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 WS2812 custom LED_MATRIX_ENABLE ?= no -ifneq ($(strip $(LED_MATRIX_ENABLE)), no) - ifeq ($(filter $(LED_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),) - $(error LED_MATRIX_ENABLE="$(LED_MATRIX_ENABLE)" is not a valid matrix type) +VALID_LED_MATRIX_TYPES := IS31FL3731 custom +# TODO: IS31FL3733 IS31FL3737 IS31FL3741 + +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 @@ -169,21 +183,22 @@ ifneq ($(strip $(LED_MATRIX_ENABLE)), no) SRC += $(QUANTUM_DIR)/led_matrix.c SRC += $(QUANTUM_DIR)/led_matrix_drivers.c endif -endif -ifeq ($(strip $(LED_MATRIX_ENABLE)), IS31FL3731) - OPT_DEFS += -DIS31FL3731 - COMMON_VPATH += $(DRIVER_PATH)/issi - SRC += is31fl3731-simple.c - QUANTUM_LIB_SRC += i2c_master.c + ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731) + OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE + COMMON_VPATH += $(DRIVER_PATH)/issi + SRC += is31fl3731-simple.c + QUANTUM_LIB_SRC += i2c_master.c + endif endif RGB_MATRIX_ENABLE ?= no +VALID_RGB_MATRIX_TYPES := IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 WS2812 custom -ifneq ($(strip $(RGB_MATRIX_ENABLE)), no) -ifeq ($(filter $(RGB_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),) - $(error RGB_MATRIX_ENABLE="$(RGB_MATRIX_ENABLE)" is not a valid matrix type) -endif +ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) + ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),) + $(error "$(RGB_MATRIX_DRIVER)" is not a valid matrix type) + endif OPT_DEFS += -DRGB_MATRIX_ENABLE ifneq (,$(filter $(MCU), atmega16u2 atmega32u2)) # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines @@ -194,51 +209,47 @@ endif SRC += $(QUANTUM_DIR)/rgb_matrix_drivers.c CIE1931_CURVE := yes RGB_KEYCODES_ENABLE := yes -endif - -ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) - RGB_MATRIX_ENABLE := IS31FL3731 -endif -ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3731) - OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE - COMMON_VPATH += $(DRIVER_PATH)/issi - SRC += is31fl3731.c - QUANTUM_LIB_SRC += i2c_master.c -endif + ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731) + OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE + COMMON_VPATH += $(DRIVER_PATH)/issi + SRC += is31fl3731.c + QUANTUM_LIB_SRC += i2c_master.c + endif -ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3733) - OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE - COMMON_VPATH += $(DRIVER_PATH)/issi - SRC += is31fl3733.c - QUANTUM_LIB_SRC += i2c_master.c -endif + ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3733) + OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE + COMMON_VPATH += $(DRIVER_PATH)/issi + SRC += is31fl3733.c + QUANTUM_LIB_SRC += i2c_master.c + endif -ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3737) - OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE - COMMON_VPATH += $(DRIVER_PATH)/issi - SRC += is31fl3737.c - QUANTUM_LIB_SRC += i2c_master.c -endif + ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3737) + OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE + COMMON_VPATH += $(DRIVER_PATH)/issi + SRC += is31fl3737.c + QUANTUM_LIB_SRC += i2c_master.c + endif -ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3741) - OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE - COMMON_VPATH += $(DRIVER_PATH)/issi - SRC += is31fl3741.c - QUANTUM_LIB_SRC += i2c_master.c -endif + ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3741) + OPT_DEFS += -DIS31FL3741 -DSTM32_I2C -DHAL_USE_I2C=TRUE + COMMON_VPATH += $(DRIVER_PATH)/issi + SRC += is31fl3741.c + QUANTUM_LIB_SRC += i2c_master.c + endif -ifeq ($(strip $(RGB_MATRIX_ENABLE)), WS2812) - OPT_DEFS += -DWS2812 - WS2812_DRIVER_REQUIRED := yes -endif + ifeq ($(strip $(RGB_MATRIX_DRIVER)), WS2812) + OPT_DEFS += -DWS2812 + WS2812_DRIVER_REQUIRED := yes + endif -ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes) - OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB -endif + ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes) + OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB + endif -ifeq ($(strip $(RGB_MATRIX_CUSTOM_USER)), yes) - OPT_DEFS += -DRGB_MATRIX_CUSTOM_USER + ifeq ($(strip $(RGB_MATRIX_CUSTOM_USER)), yes) + OPT_DEFS += -DRGB_MATRIX_CUSTOM_USER + endif endif ifeq ($(strip $(RGB_KEYCODES_ENABLE)), yes) @@ -453,11 +464,14 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes) # Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called. # Unused functions are pruned away, which is why we can add multiple drivers here without bloat. ifeq ($(PLATFORM),AVR) - QUANTUM_LIB_SRC += i2c_master.c \ - i2c_slave.c + ifneq ($(NO_I2C),yes) + QUANTUM_LIB_SRC += i2c_master.c \ + i2c_slave.c + endif endif SERIAL_DRIVER ?= bitbang + OPT_DEFS += -DSERIAL_DRIVER_$(strip $(shell echo $(SERIAL_DRIVER) | tr '[:lower:]' '[:upper:]')) ifeq ($(strip $(SERIAL_DRIVER)), bitbang) QUANTUM_LIB_SRC += serial.c else diff --git a/drivers/avr/serial.c b/drivers/avr/serial.c index c4ef2a97e7d7..d161b249ccb4 100644 --- a/drivers/avr/serial.c +++ b/drivers/avr/serial.c @@ -21,50 +21,111 @@ #ifdef SOFT_SERIAL_PIN -# ifdef __AVR_ATmega32U4__ -// if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial. -# ifdef USE_AVR_I2C -# if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1 -# error Using ATmega32U4 I2C, so can not use PD0, PD1 -# endif +# if !(defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) +# error serial.c is not supported for the currently selected MCU +# endif +// if using ATmega32U4/2, AT90USBxxx I2C, can not use PD0 and PD1 in soft serial. +# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) +# if defined(USE_AVR_I2C) && (SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1) +# error Using I2C, so can not use PD0, PD1 # endif +# endif +// PD0..PD3, common config +# if SOFT_SERIAL_PIN == D0 +# define EIMSK_BIT _BV(INT0) +# define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01))) +# define SERIAL_PIN_INTERRUPT INT0_vect +# define EICRx EICRA +# elif SOFT_SERIAL_PIN == D1 +# define EIMSK_BIT _BV(INT1) +# define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11))) +# define SERIAL_PIN_INTERRUPT INT1_vect +# define EICRx EICRA +# elif SOFT_SERIAL_PIN == D2 +# define EIMSK_BIT _BV(INT2) +# define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21))) +# define SERIAL_PIN_INTERRUPT INT2_vect +# define EICRx EICRA +# elif SOFT_SERIAL_PIN == D3 +# define EIMSK_BIT _BV(INT3) +# define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31))) +# define SERIAL_PIN_INTERRUPT INT3_vect +# define EICRx EICRA +# endif -# define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) -# define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) -# define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) -# define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) -# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) - -# if SOFT_SERIAL_PIN >= D0 && SOFT_SERIAL_PIN <= D3 -# if SOFT_SERIAL_PIN == D0 -# define EIMSK_BIT _BV(INT0) -# define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01))) -# define SERIAL_PIN_INTERRUPT INT0_vect -# elif SOFT_SERIAL_PIN == D1 -# define EIMSK_BIT _BV(INT1) -# define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11))) -# define SERIAL_PIN_INTERRUPT INT1_vect -# elif SOFT_SERIAL_PIN == D2 -# define EIMSK_BIT _BV(INT2) -# define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21))) -# define SERIAL_PIN_INTERRUPT INT2_vect -# elif SOFT_SERIAL_PIN == D3 -# define EIMSK_BIT _BV(INT3) -# define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31))) -# define SERIAL_PIN_INTERRUPT INT3_vect -# endif +// ATmegaxxU2 specific config +# if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) +// PD4(INT5), PD6(INT6), PD7(INT7), PC7(INT4) +# if SOFT_SERIAL_PIN == D4 +# define EIMSK_BIT _BV(INT5) +# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51))) +# define SERIAL_PIN_INTERRUPT INT5_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == D6 +# define EIMSK_BIT _BV(INT6) +# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) +# define SERIAL_PIN_INTERRUPT INT6_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == D7 +# define EIMSK_BIT _BV(INT7) +# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71))) +# define SERIAL_PIN_INTERRUPT INT7_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == C7 +# define EIMSK_BIT _BV(INT4) +# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41))) +# define SERIAL_PIN_INTERRUPT INT4_vect +# define EICRx EICRB +# endif +# endif + +// ATmegaxxU4 specific config +# if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) +// PE6(INT6) +# if SOFT_SERIAL_PIN == E6 +# define EIMSK_BIT _BV(INT6) +# define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) +# define SERIAL_PIN_INTERRUPT INT6_vect +# define EICRx EICRB +# endif +# endif + +// AT90USBxxx specific config +# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) +// PE4..PE7(INT4..INT7) +# if SOFT_SERIAL_PIN == E4 +# define EIMSK_BIT _BV(INT4) +# define EICRx_BIT (~(_BV(ISC40) | _BV(ISC41))) +# define SERIAL_PIN_INTERRUPT INT4_vect +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == E5 +# define EIMSK_BIT _BV(INT5) +# define EICRx_BIT (~(_BV(ISC50) | _BV(ISC51))) +# define SERIAL_PIN_INTERRUPT INT5_vect +# define EICRx EICRB # elif SOFT_SERIAL_PIN == E6 # define EIMSK_BIT _BV(INT6) # define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) # define SERIAL_PIN_INTERRUPT INT6_vect -# else -# error invalid SOFT_SERIAL_PIN value +# define EICRx EICRB +# elif SOFT_SERIAL_PIN == E7 +# define EIMSK_BIT _BV(INT7) +# define EICRx_BIT (~(_BV(ISC70) | _BV(ISC71))) +# define SERIAL_PIN_INTERRUPT INT7_vect +# define EICRx EICRB # endif +# endif -# else -# error serial.c now support ATmega32U4 only +# ifndef SERIAL_PIN_INTERRUPT +# error invalid SOFT_SERIAL_PIN value # endif +# define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) +# define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF)) +# define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) +# define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) +# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) + # define ALWAYS_INLINE __attribute__((always_inline)) # define NO_INLINE __attribute__((noinline)) # define _delay_sub_us(x) __builtin_avr_delay_cycles(x) @@ -211,15 +272,9 @@ void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) { Transaction_table_size = (uint8_t)sstd_table_size; serial_input_with_pullup(); - // Enable INT0-INT3,INT6 + // Enable INT0-INT7 EIMSK |= EIMSK_BIT; -# if SOFT_SERIAL_PIN == E6 - // Trigger on falling edge of INT6 - EICRB &= EICRx_BIT; -# else - // Trigger on falling edge of INT0-INT3 - EICRA &= EICRx_BIT; -# endif + EICRx &= EICRx_BIT; } // Used by the sender to synchronize timing with the reciver. diff --git a/drivers/chibios/i2c_master.c b/drivers/chibios/i2c_master.c index 4bd8e2af7624..fc4bb2ab3701 100644 --- a/drivers/chibios/i2c_master.c +++ b/drivers/chibios/i2c_master.c @@ -58,18 +58,23 @@ static i2c_status_t chibios_to_qmk(const msg_t* status) { } __attribute__((weak)) void i2c_init(void) { - // Try releasing special pins for a short time - palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT); - palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT); + static bool is_initialised = false; + if (!is_initialised) { + is_initialised = true; - chThdSleepMilliseconds(10); + // Try releasing special pins for a short time + palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT); + palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT); + + chThdSleepMilliseconds(10); #if defined(USE_GPIOV1) - palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, I2C1_SCL_PAL_MODE); - palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, I2C1_SDA_PAL_MODE); + palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, I2C1_SCL_PAL_MODE); + palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, I2C1_SDA_PAL_MODE); #else - palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); - palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); + palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); + palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); #endif + } } i2c_status_t i2c_start(uint8_t address) { diff --git a/drivers/chibios/spi_master.c b/drivers/chibios/spi_master.c index 552ac663c1e9..5aa60742e326 100644 --- a/drivers/chibios/spi_master.c +++ b/drivers/chibios/spi_master.c @@ -22,21 +22,26 @@ static pin_t currentSlavePin = NO_PIN; static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0}; __attribute__((weak)) void spi_init(void) { - // Try releasing special pins for a short time - palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_INPUT); - palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_INPUT); - palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_INPUT); + static bool is_initialised = false; + if (!is_initialised) { + is_initialised = true; - chThdSleepMilliseconds(10); + // Try releasing special pins for a short time + palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_INPUT); + palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_INPUT); + palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_INPUT); + + chThdSleepMilliseconds(10); #if defined(USE_GPIOV1) - palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); - palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); - palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); + palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); + palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); + palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); #else - palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); - palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); - palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); + palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); + palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); + palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); #endif + } } bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { diff --git a/drivers/eeprom/eeprom_i2c.c b/drivers/eeprom/eeprom_i2c.c index ca8af3da51a4..4210f06f9f9a 100644 --- a/drivers/eeprom/eeprom_i2c.c +++ b/drivers/eeprom/eeprom_i2c.c @@ -42,14 +42,6 @@ # include "debug.h" #endif // DEBUG_EEPROM_OUTPUT -static inline void init_i2c_if_required(void) { - static int done = 0; - if (!done) { - i2c_init(); - done = 1; - } -} - static inline void fill_target_address(uint8_t *buffer, const void *addr) { uintptr_t p = (uintptr_t)addr; for (int i = 0; i < EXTERNAL_EEPROM_ADDRESS_SIZE; ++i) { @@ -58,7 +50,7 @@ static inline void fill_target_address(uint8_t *buffer, const void *addr) { } } -void eeprom_driver_init(void) {} +void eeprom_driver_init(void) { i2c_init(); } void eeprom_driver_erase(void) { #if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) @@ -80,7 +72,6 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) { uint8_t complete_packet[EXTERNAL_EEPROM_ADDRESS_SIZE]; fill_target_address(complete_packet, addr); - init_i2c_if_required(); i2c_transmit(EXTERNAL_EEPROM_I2C_ADDRESS((uintptr_t)addr), complete_packet, EXTERNAL_EEPROM_ADDRESS_SIZE, 100); i2c_receive(EXTERNAL_EEPROM_I2C_ADDRESS((uintptr_t)addr), buf, len, 100); @@ -98,7 +89,6 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) { uint8_t * read_buf = (uint8_t *)buf; uintptr_t target_addr = (uintptr_t)addr; - init_i2c_if_required(); while (len > 0) { uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE; int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset; diff --git a/drivers/eeprom/eeprom_spi.c b/drivers/eeprom/eeprom_spi.c index 7b6416eafbf4..182731d82f10 100644 --- a/drivers/eeprom/eeprom_spi.c +++ b/drivers/eeprom/eeprom_spi.c @@ -55,14 +55,6 @@ # include "debug.h" #endif // CONSOLE_ENABLE -static void init_spi_if_required(void) { - static int done = 0; - if (!done) { - spi_init(); - done = 1; - } -} - static bool spi_eeprom_start(void) { return spi_start(EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN, EXTERNAL_EEPROM_SPI_LSBFIRST, EXTERNAL_EEPROM_SPI_MODE, EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR); } static spi_status_t spi_eeprom_wait_while_busy(int timeout) { @@ -91,7 +83,7 @@ static void spi_eeprom_transmit_address(uintptr_t addr) { //---------------------------------------------------------------------------------------------------------------------- -void eeprom_driver_init(void) {} +void eeprom_driver_init(void) { spi_init(); } void eeprom_driver_erase(void) { #if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) @@ -110,8 +102,6 @@ void eeprom_driver_erase(void) { } void eeprom_read_block(void *buf, const void *addr, size_t len) { - init_spi_if_required(); - //------------------------------------------------- // Wait for the write-in-progress bit to be cleared bool res = spi_eeprom_start(); @@ -154,8 +144,6 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) { } void eeprom_write_block(const void *buf, void *addr, size_t len) { - init_spi_if_required(); - bool res; uint8_t * read_buf = (uint8_t *)buf; uintptr_t target_addr = (uintptr_t)addr; diff --git a/drivers/haptic/haptic.c b/drivers/haptic/haptic.c index 989970beeeda..8fef1cb225aa 100644 --- a/drivers/haptic/haptic.c +++ b/drivers/haptic/haptic.c @@ -33,11 +33,18 @@ void haptic_init(void) { eeconfig_init(); } haptic_config.raw = eeconfig_read_haptic(); - if (haptic_config.mode < 1) { - haptic_config.mode = 1; - } - if (!haptic_config.mode) { - dprintf("No haptic config found in eeprom, setting default configs\n"); +#ifdef SOLENOID_ENABLE + solenoid_set_dwell(haptic_config.dwell); +#endif + if ((haptic_config.raw == 0) +#ifdef SOLENOID_ENABLE + || (haptic_config.dwell == 0) +#endif + ) { + // this will be called, if the eeprom is not corrupt, + // but the previous firmware didn't have haptic enabled, + // or the previous firmware didn't have solenoid enabled, + // and the current one has solenoid enabled. haptic_reset(); } #ifdef SOLENOID_ENABLE @@ -118,25 +125,37 @@ void haptic_mode_decrease(void) { } void haptic_dwell_increase(void) { - uint8_t dwell = haptic_config.dwell + 1; #ifdef SOLENOID_ENABLE + int16_t next_dwell = ((int16_t)haptic_config.dwell) + SOLENOID_DWELL_STEP_SIZE; if (haptic_config.dwell >= SOLENOID_MAX_DWELL) { - dwell = 1; + // if it's already at max, we wrap back to min + next_dwell = SOLENOID_MIN_DWELL; + } else if (next_dwell > SOLENOID_MAX_DWELL) { + // if we overshoot the max, then cap at max + next_dwell = SOLENOID_MAX_DWELL; } - solenoid_set_dwell(dwell); + solenoid_set_dwell(next_dwell); +#else + int16_t next_dwell = ((int16_t)haptic_config.dwell) + 1; #endif - haptic_set_dwell(dwell); + haptic_set_dwell(next_dwell); } void haptic_dwell_decrease(void) { - uint8_t dwell = haptic_config.dwell - 1; #ifdef SOLENOID_ENABLE - if (haptic_config.dwell < SOLENOID_MIN_DWELL) { - dwell = SOLENOID_MAX_DWELL; + int16_t next_dwell = ((int16_t)haptic_config.dwell) - SOLENOID_DWELL_STEP_SIZE; + if (haptic_config.dwell <= SOLENOID_MIN_DWELL) { + // if it's already at min, we wrap to max + next_dwell = SOLENOID_MAX_DWELL; + } else if (next_dwell < SOLENOID_MIN_DWELL) { + // if we go below min, then we cap to min + next_dwell = SOLENOID_MIN_DWELL; } - solenoid_set_dwell(dwell); + solenoid_set_dwell(next_dwell); +#else + int16_t next_dwell = ((int16_t)haptic_config.dwell) - 1; #endif - haptic_set_dwell(dwell); + haptic_set_dwell(next_dwell); } void haptic_reset(void) { @@ -150,6 +169,12 @@ void haptic_reset(void) { #ifdef SOLENOID_ENABLE uint8_t dwell = SOLENOID_DEFAULT_DWELL; haptic_config.dwell = dwell; + haptic_config.buzz = SOLENOID_DEFAULT_BUZZ; + solenoid_set_dwell(dwell); +#else + // This is to trigger haptic_reset again, if solenoid is enabled in the future. + haptic_config.dwell = 0; + haptic_config.buzz = 0; #endif eeconfig_update_haptic(haptic_config.raw); xprintf("haptic_config.feedback = %u\n", haptic_config.feedback); diff --git a/drivers/haptic/solenoid.c b/drivers/haptic/solenoid.c index d645c379ae97..2975ef893a9f 100644 --- a/drivers/haptic/solenoid.c +++ b/drivers/haptic/solenoid.c @@ -32,14 +32,6 @@ void solenoid_buzz_off(void) { haptic_set_buzz(0); } void solenoid_set_buzz(int buzz) { haptic_set_buzz(buzz); } -void solenoid_dwell_minus(uint8_t solenoid_dwell) { - if (solenoid_dwell > 0) solenoid_dwell--; -} - -void solenoid_dwell_plus(uint8_t solenoid_dwell) { - if (solenoid_dwell < SOLENOID_MAX_DWELL) solenoid_dwell++; -} - void solenoid_set_dwell(uint8_t dwell) { solenoid_dwell = dwell; } void solenoid_stop(void) { @@ -73,7 +65,7 @@ void solenoid_check(void) { // Check whether to buzz the solenoid on and off if (haptic_config.buzz) { - if (elapsed / SOLENOID_MIN_DWELL % 2 == 0) { + if ((elapsed % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) { if (!solenoid_buzzing) { solenoid_buzzing = true; writePinHigh(SOLENOID_PIN); diff --git a/drivers/haptic/solenoid.h b/drivers/haptic/solenoid.h index dd6ececa685e..f2a3bc4c3094 100644 --- a/drivers/haptic/solenoid.h +++ b/drivers/haptic/solenoid.h @@ -29,6 +29,22 @@ # define SOLENOID_MIN_DWELL 4 #endif +#ifndef SOLENOID_DWELL_STEP_SIZE +# define SOLENOID_DWELL_STEP_SIZE 1 +#endif + +#ifndef SOLENOID_DEFAULT_BUZZ +# define SOLENOID_DEFAULT_BUZZ 0 +#endif + +#ifndef SOLENOID_BUZZ_ACTUATED +# define SOLENOID_BUZZ_ACTUATED SOLENOID_MIN_DWELL +#endif + +#ifndef SOLENOID_BUZZ_NONACTUATED +# define SOLENOID_BUZZ_NONACTUATED SOLENOID_MIN_DWELL +#endif + #ifndef SOLENOID_PIN # error SOLENOID_PIN not defined #endif @@ -37,8 +53,6 @@ void solenoid_buzz_on(void); void solenoid_buzz_off(void); void solenoid_set_buzz(int buzz); -void solenoid_dwell_minus(uint8_t solenoid_dwell); -void solenoid_dwell_plus(uint8_t solenoid_dwell); void solenoid_set_dwell(uint8_t dwell); void solenoid_stop(void); diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c index ba11db1d2ad2..53bb8ca3fa5b 100644 --- a/drivers/oled/oled_driver.c +++ b/drivers/oled/oled_driver.c @@ -119,6 +119,9 @@ uint32_t oled_timeout; #if OLED_SCROLL_TIMEOUT > 0 uint32_t oled_scroll_timeout; #endif +#if OLED_UPDATE_INTERVAL > 0 +uint16_t oled_update_timeout; +#endif // Internal variables to reduce math instructions @@ -468,8 +471,9 @@ void oled_write_raw_byte(const char data, uint16_t index) { } void oled_write_raw(const char *data, uint16_t size) { - if (size > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE; - for (uint16_t i = 0; i < size; i++) { + 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]; oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE)); @@ -511,8 +515,9 @@ void oled_write_ln_P(const char *data, bool invert) { } void oled_write_raw_P(const char *data, uint16_t size) { - if (size > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE; - for (uint16_t i = 0; i < size; i++) { + 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++) { uint8_t c = pgm_read_byte(data++); if (oled_buffer[i] == c) continue; oled_buffer[i] = c; @@ -650,9 +655,16 @@ void oled_task(void) { return; } +#if OLED_UPDATE_INTERVAL > 0 + if (timer_elapsed(oled_update_timeout) >= OLED_UPDATE_INTERVAL) { + oled_update_timeout = timer_read(); + oled_set_cursor(0, 0); + oled_task_user(); + } +#else oled_set_cursor(0, 0); - oled_task_user(); +#endif #if OLED_SCROLL_TIMEOUT > 0 if (oled_dirty && oled_scrolling) { diff --git a/keyboards/ergodox_ez/rules.mk b/keyboards/ergodox_ez/rules.mk index 773737399f69..b7b7b6c1439a 100644 --- a/keyboards/ergodox_ez/rules.mk +++ b/keyboards/ergodox_ez/rules.mk @@ -31,7 +31,8 @@ SWAP_HANDS_ENABLE= yes # Allow swapping hands of keyboard SLEEP_LED_ENABLE = no API_SYSEX_ENABLE = no -RGB_MATRIX_ENABLE = no # enable later +RGB_MATRIX_ENABLE = no # enable later +RGB_MATRIX_DRIVER = IS31FL3731 DEBOUNCE_TYPE = eager_pr # project specific files diff --git a/keyboards/moonlander/rules.mk b/keyboards/moonlander/rules.mk index 3d7d623f76ed..0cff2528f2e1 100644 --- a/keyboards/moonlander/rules.mk +++ b/keyboards/moonlander/rules.mk @@ -15,7 +15,8 @@ NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = yes # Custom matrix file AUDIO_ENABLE = yes SWAP_HANDS_ENABLE = yes -RGB_MATRIX_ENABLE = IS31FL3731 +RGB_MATRIX_ENABLE = yes +RGB_MATRIX_DRIVER = IS31FL3731 #SERIAL_LINK_ENABLE = yes EEPROM_DRIVER = i2c diff --git a/keyboards/planck/ez/glow/rules.mk b/keyboards/planck/ez/glow/rules.mk index 575a9c8fa411..aad92997d0fa 100644 --- a/keyboards/planck/ez/glow/rules.mk +++ b/keyboards/planck/ez/glow/rules.mk @@ -1 +1 @@ -RGB_MATRIX_ENABLE = IS31FL3737 +RGB_MATRIX_ENABLE = yes diff --git a/keyboards/planck/ez/rules.mk b/keyboards/planck/ez/rules.mk index a4a53ceeb45f..a146c65aa90c 100644 --- a/keyboards/planck/ez/rules.mk +++ b/keyboards/planck/ez/rules.mk @@ -17,6 +17,7 @@ AUDIO_ENABLE = yes RGBLIGHT_ENABLE = no # SERIAL_LINK_ENABLE = yes ENCODER_ENABLE = yes +RGB_MATRIX_DRIVER = IS31FL3737 LAYOUTS += ortho_4x12 diff --git a/keyboards/planck/planck.h b/keyboards/planck/planck.h index 1beafa7764a4..d575112d3683 100644 --- a/keyboards/planck/planck.h +++ b/keyboards/planck/planck.h @@ -1,26 +1,9 @@ -#ifndef PLANCK_H -#define PLANCK_H +#pragma once #include "quantum.h" #define encoder_update(clockwise) encoder_update_user(uint8_t index, clockwise) #if defined(KEYBOARD_planck_ez) - #include "ez.h" -#elif defined(KEYBOARD_planck_light) - #include "light.h" -#elif defined(KEYBOARD_planck_rev1) - #include "rev1.h" -#elif defined(KEYBOARD_planck_rev2) - #include "rev2.h" -#elif defined(KEYBOARD_planck_rev3) - #include "rev3.h" -#elif defined(KEYBOARD_planck_rev4) - #include "rev4.h" -#elif defined(KEYBOARD_planck_rev5) - #include "rev5.h" -#elif defined(KEYBOARD_planck_rev6) - #include "rev6.h" -#endif // Planck revisions - -#endif +# include "ez.h" +#endif // Planck revisions diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py index 77724a244800..10536bb230ba 100644 --- a/lib/python/qmk/cli/__init__.py +++ b/lib/python/qmk/cli/__init__.py @@ -8,6 +8,7 @@ from . import c2json from . import cformat +from . import chibios from . import clean from . import compile from . import config diff --git a/lib/python/qmk/cli/chibios/__init__.py b/lib/python/qmk/cli/chibios/__init__.py new file mode 100644 index 000000000000..4301837defda --- /dev/null +++ b/lib/python/qmk/cli/chibios/__init__.py @@ -0,0 +1 @@ +from . import confmigrate diff --git a/lib/python/qmk/cli/chibios/confmigrate.py b/lib/python/qmk/cli/chibios/confmigrate.py new file mode 100644 index 000000000000..eae294a0c69b --- /dev/null +++ b/lib/python/qmk/cli/chibios/confmigrate.py @@ -0,0 +1,161 @@ +"""This script automates the copying of the default keymap into your own keymap. +""" +import re +import sys +import os + +from qmk.constants import QMK_FIRMWARE +from qmk.path import normpath +from milc import cli + + +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + + +fileHeader = """\ +/* Copyright 2020 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * This file was auto-generated by: + * `qmk chibios-confupdate -i {0} -r {1}` + */ + +#pragma once +""" + + +def collect_defines(filepath): + with open(filepath, 'r') as f: + content = f.read() + define_search = re.compile(r'(?m)^#\s*define\s+(?:.*\\\r?\n)*.*$', re.MULTILINE) + value_search = re.compile(r'^#\s*define\s+(?P[a-zA-Z0-9_]+(\([^\)]*\))?)\s*(?P.*)', re.DOTALL) + define_matches = define_search.findall(content) + + defines = {"keys": [], "dict": {}} + for define_match in define_matches: + value_match = value_search.search(define_match) + defines["keys"].append(value_match.group("name")) + defines["dict"][value_match.group("name")] = value_match.group("value") + return defines + + +def check_diffs(input_defs, reference_defs): + not_present_in_input = [] + not_present_in_reference = [] + to_override = [] + + for key in reference_defs["keys"]: + if key not in input_defs["dict"]: + not_present_in_input.append(key) + continue + + for key in input_defs["keys"]: + if key not in input_defs["dict"]: + not_present_in_input.append(key) + continue + + for key in input_defs["keys"]: + if key in reference_defs["keys"] and input_defs["dict"][key] != reference_defs["dict"][key]: + to_override.append((key, input_defs["dict"][key])) + + return (to_override, not_present_in_input, not_present_in_reference) + + +def migrate_chconf_h(to_override, outfile): + print(fileHeader.format(cli.args.input.relative_to(QMK_FIRMWARE), cli.args.reference.relative_to(QMK_FIRMWARE)), file=outfile) + + for override in to_override: + print("#define %s %s" % (override[0], override[1]), file=outfile) + print("", file=outfile) + + print("#include_next \n", file=outfile) + + +def migrate_halconf_h(to_override, outfile): + print(fileHeader.format(cli.args.input.relative_to(QMK_FIRMWARE), cli.args.reference.relative_to(QMK_FIRMWARE)), file=outfile) + + for override in to_override: + print("#define %s %s" % (override[0], override[1]), file=outfile) + print("", file=outfile) + + print("#include_next \n", file=outfile) + + +def migrate_mcuconf_h(to_override, outfile): + print(fileHeader.format(cli.args.input.relative_to(QMK_FIRMWARE), cli.args.reference.relative_to(QMK_FIRMWARE)), file=outfile) + + print("#include_next \n", file=outfile) + + for override in to_override: + print("#undef %s" % (override[0]), file=outfile) + print("#define %s %s" % (override[0], override[1]), file=outfile) + print("", file=outfile) + + +@cli.argument('-i', '--input', type=normpath, arg_only=True, help='Specify input config file.') +@cli.argument('-r', '--reference', type=normpath, arg_only=True, help='Specify the reference file to compare against') +@cli.argument('-o', '--overwrite', arg_only=True, action='store_true', help='Overwrites the input file during migration.') +@cli.argument('-d', '--delete', arg_only=True, action='store_true', help='If the file has no overrides, migration will delete the input file.') +@cli.subcommand('Generates a migrated ChibiOS configuration file, as a result of comparing the input against a reference') +def chibios_confmigrate(cli): + """Generates a usable ChibiOS replacement configuration file, based on a fully-defined conf and a reference config. + """ + + input_defs = collect_defines(cli.args.input) + reference_defs = collect_defines(cli.args.reference) + + (to_override, not_present_in_input, not_present_in_reference) = check_diffs(input_defs, reference_defs) + + if len(not_present_in_input) > 0: + eprint("Keys not in input, but present inside reference (potential manual migration required):") + for key in not_present_in_input: + eprint(" %s" % (key)) + + if len(not_present_in_reference) > 0: + eprint("Keys not in reference, but present inside input (potential manual migration required):") + for key in not_present_in_reference: + eprint(" %s" % (key)) + + if len(to_override) == 0: + eprint('No overrides found! If there were no missing keys above, it should be safe to delete the input file.') + if cli.args.delete: + os.remove(cli.args.input) + else: + eprint('Overrides found:') + for override in to_override: + eprint("%40s: %s -> %s" % (override[0], reference_defs["dict"][override[0]].encode('unicode_escape').decode("utf-8"), override[1].encode('unicode_escape').decode("utf-8"))) + + eprint('--------------------------------------') + + if "CHCONF_H" in input_defs["dict"] or "_CHCONF_H_" in input_defs["dict"]: + migrate_chconf_h(to_override, outfile=sys.stdout) + if cli.args.overwrite: + with open(cli.args.input, "w") as out_file: + migrate_chconf_h(to_override, outfile=out_file) + + elif "HALCONF_H" in input_defs["dict"] or "_HALCONF_H_" in input_defs["dict"]: + migrate_halconf_h(to_override, outfile=sys.stdout) + if cli.args.overwrite: + with open(cli.args.input, "w") as out_file: + migrate_halconf_h(to_override, outfile=out_file) + + elif "MCUCONF_H" in input_defs["dict"] or "_MCUCONF_H_" in input_defs["dict"]: + migrate_mcuconf_h(to_override, outfile=sys.stdout) + if cli.args.overwrite: + with open(cli.args.input, "w") as out_file: + migrate_mcuconf_h(to_override, outfile=out_file) diff --git a/lib/python/qmk/cli/doctor.py b/lib/python/qmk/cli/doctor.py index a5eda555f0cc..4fe318b636a5 100755 --- a/lib/python/qmk/cli/doctor.py +++ b/lib/python/qmk/cli/doctor.py @@ -10,9 +10,9 @@ from enum import Enum from milc import cli +from milc.questions import yesno from qmk import submodules from qmk.constants import QMK_FIRMWARE -from qmk.questions import yesno from qmk.commands import run diff --git a/lib/python/qmk/questions.py b/lib/python/qmk/questions.py deleted file mode 100644 index 865c6bbdc513..000000000000 --- a/lib/python/qmk/questions.py +++ /dev/null @@ -1,183 +0,0 @@ -"""Functions to collect user input. -""" - -from milc import cli - -try: - from milc import format_ansi -except ImportError: - from milc.ansi import format_ansi - - -def yesno(prompt, *args, default=None, **kwargs): - """Displays prompt to the user and gets a yes or no response. - - Returns True for a yes and False for a no. - - If you add `--yes` and `--no` arguments to your program the user can answer questions by passing command line flags. - - @add_argument('-y', '--yes', action='store_true', arg_only=True, help='Answer yes to all questions.') - @add_argument('-n', '--no', action='store_true', arg_only=True, help='Answer no to all questions.') - - Arguments: - prompt - The prompt to present to the user. Can include ANSI and format strings like milc's `cli.echo()`. - - default - Whether to default to a Yes or No when the user presses enter. - - None- force the user to enter Y or N - - True- Default to yes - - False- Default to no - """ - if not args and kwargs: - args = kwargs - - if 'no' in cli.args and cli.args.no: - return False - - if 'yes' in cli.args and cli.args.yes: - return True - - if default is not None: - if default: - prompt = prompt + ' [Y/n] ' - else: - prompt = prompt + ' [y/N] ' - - while True: - cli.echo('') - answer = input(format_ansi(prompt % args)) - cli.echo('') - - if not answer and prompt is not None: - return default - - elif answer.lower() in ['y', 'yes']: - return True - - elif answer.lower() in ['n', 'no']: - return False - - -def question(prompt, *args, default=None, confirm=False, answer_type=str, validate=None, **kwargs): - """Prompt the user to answer a question with a free-form input. - - Arguments: - prompt - The prompt to present to the user. Can include ANSI and format strings like milc's `cli.echo()`. - - default - The value to return when the user doesn't enter any value. Use None to prompt until they enter a value. - - confirm - Present the user with a confirmation dialog before accepting their answer. - - answer_type - Specify a type function for the answer. Will re-prompt the user if the function raises any errors. Common choices here include int, float, and decimal.Decimal. - - validate - This is an optional function that can be used to validate the answer. It should return True or False and have the following signature: - - def function_name(answer, *args, **kwargs): - """ - if not args and kwargs: - args = kwargs - - if default is not None: - prompt = '%s [%s] ' % (prompt, default) - - while True: - cli.echo('') - answer = input(format_ansi(prompt % args)) - cli.echo('') - - if answer: - if validate is not None and not validate(answer, *args, **kwargs): - continue - - elif confirm: - if yesno('Is the answer "%s" correct?', answer, default=True): - try: - return answer_type(answer) - except Exception as e: - cli.log.error('Could not convert answer (%s) to type %s: %s', answer, answer_type.__name__, str(e)) - - else: - try: - return answer_type(answer) - except Exception as e: - cli.log.error('Could not convert answer (%s) to type %s: %s', answer, answer_type.__name__, str(e)) - - elif default is not None: - return default - - -def choice(heading, options, *args, default=None, confirm=False, prompt='Please enter your choice: ', **kwargs): - """Present the user with a list of options and let them pick one. - - Users can enter either the number or the text of their choice. - - This will return the value of the item they choose, not the numerical index. - - Arguments: - heading - The text to place above the list of options. - - options - A sequence of items to choose from. - - default - The index of the item to return when the user doesn't enter any value. Use None to prompt until they enter a value. - - confirm - Present the user with a confirmation dialog before accepting their answer. - - prompt - The prompt to present to the user. Can include ANSI and format strings like milc's `cli.echo()`. - """ - if not args and kwargs: - args = kwargs - - if prompt and default: - prompt = prompt + ' [%s] ' % (default + 1,) - - while True: - # Prompt for an answer. - cli.echo('') - cli.echo(heading % args) - cli.echo('') - for i, option in enumerate(options, 1): - cli.echo('\t{fg_cyan}%d.{fg_reset} %s', i, option) - - cli.echo('') - answer = input(format_ansi(prompt)) - cli.echo('') - - # If the user types in one of the options exactly use that - if answer in options: - return answer - - # Massage the answer into a valid integer - if answer == '' and default: - answer = default - else: - try: - answer = int(answer) - 1 - except Exception: - # Normally we would log the exception here, but in the interest of clean UI we do not. - cli.log.error('Invalid choice: %s', answer + 1) - continue - - # Validate the answer - if answer >= len(options) or answer < 0: - cli.log.error('Invalid choice: %s', answer + 1) - continue - - if confirm and not yesno('Is the answer "%s" correct?', answer + 1, default=True): - continue - - # Return the answer they chose. - return options[answer] diff --git a/message.mk b/message.mk index be04fa9b8104..84b23c1ba871 100644 --- a/message.mk +++ b/message.mk @@ -5,6 +5,7 @@ ifeq ($(COLOR),true) OK_COLOR=\033[32;01m ERROR_COLOR=\033[31;01m WARN_COLOR=\033[33;01m + SKIPPED_COLOR=\033[36;01m BLUE=\033[0;34m BOLD=\033[1m endif @@ -20,6 +21,7 @@ ON_ERROR ?= exit 1 OK_STRING=$(OK_COLOR)[OK]$(NO_COLOR)\n ERROR_STRING=$(ERROR_COLOR)[ERRORS]$(NO_COLOR)\n WARN_STRING=$(WARN_COLOR)[WARNINGS]$(NO_COLOR)\n +SKIPPED_STRING=$(SKIPPED_COLOR)[SKIPPED]$(NO_COLOR)\n TAB_LOG = printf "\n%s\n\n" "$$LOG" | $(AWK) '{ sub(/^/," | "); print }' TAB_LOG_PLAIN = printf "%s\n" "$$LOG" @@ -29,6 +31,7 @@ PRINT_ERROR = ($(SILENT) ||printf " $(ERROR_STRING)" | $(AWK_STATUS)) && $(TAB_L PRINT_WARNING = ($(SILENT) || printf " $(WARN_STRING)" | $(AWK_STATUS)) && $(TAB_LOG) PRINT_ERROR_PLAIN = ($(SILENT) ||printf " $(ERROR_STRING)" | $(AWK_STATUS)) && $(TAB_LOG_PLAIN) && $(ON_ERROR) PRINT_WARNING_PLAIN = ($(SILENT) || printf " $(WARN_STRING)" | $(AWK_STATUS)) && $(TAB_LOG_PLAIN) +PRINT_SKIPPED_PLAIN = ($(SILENT) || printf " $(SKIPPED_STRING)" | $(AWK_STATUS)) PRINT_OK = $(SILENT) || printf " $(OK_STRING)" | $(AWK_STATUS) BUILD_CMD = LOG=$$($(CMD) 2>&1) ; if [ $$? -gt 0 ]; then $(PRINT_ERROR); elif [ "$$LOG" != "" ] ; then $(PRINT_WARNING); else $(PRINT_OK); fi; MAKE_MSG_FORMAT = $(AWK) '{ printf "%-118s", $$0;}' diff --git a/platforms/chibios/BLACKPILL_STM32_F401/configs/config.h b/platforms/chibios/BLACKPILL_STM32_F401/configs/config.h index eb73e72ef282..1c9d9c61263f 100644 --- a/platforms/chibios/BLACKPILL_STM32_F401/configs/config.h +++ b/platforms/chibios/BLACKPILL_STM32_F401/configs/config.h @@ -20,4 +20,6 @@ #define STM32_LSECLK 32768U #define STM32_HSECLK 25000000U -#define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/BLACKPILL_STM32_F411/configs/config.h b/platforms/chibios/BLACKPILL_STM32_F411/configs/config.h index eb73e72ef282..1c9d9c61263f 100644 --- a/platforms/chibios/BLACKPILL_STM32_F411/configs/config.h +++ b/platforms/chibios/BLACKPILL_STM32_F411/configs/config.h @@ -20,4 +20,6 @@ #define STM32_LSECLK 32768U #define STM32_HSECLK 25000000U -#define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/GENERIC_STM32_F042X6/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_F042X6/configs/mcuconf.h new file mode 100644 index 000000000000..4643e9f92e8f --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_F042X6/configs/mcuconf.h @@ -0,0 +1,168 @@ +/* + ChibiOS - Copyright (C) 2006..2015 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_ + +/* + * STM32F0xx 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: + * 3...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F0xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI_ENABLED TRUE +#define STM32_HSI14_ENABLED TRUE +#define STM32_HSI48_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2 +#define STM32_PREDIV_VALUE 1 +#define STM32_PLLMUL_VALUE 12 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE STM32_PPRE_DIV1 +#define STM32_ADCSW STM32_ADCSW_HSI14 +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_ADCSW STM32_ADCSW_HSI14 +#define STM32_USBSW STM32_USBSW_HSI48 +#define STM32_CECSW STM32_CECSW_HSI +#define STM32_I2C1SW STM32_I2C1SW_HSI +#define STM32_USART1SW STM32_USART1SW_PCLK +#define STM32_RTCSEL STM32_RTCSEL_LSI + +/* + * ADC driver system settings. + */ +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 2 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 + +/* + * EXT driver system settings. + */ +#define STM32_EXT_EXTI0_1_IRQ_PRIORITY 3 +#define STM32_EXT_EXTI2_3_IRQ_PRIORITY 3 +#define STM32_EXT_EXTI4_15_IRQ_PRIORITY 3 +#define STM32_EXT_EXTI16_IRQ_PRIORITY 3 +#define STM32_EXT_EXTI17_IRQ_PRIORITY 3 + +/* + * 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_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 2 +#define STM32_GPT_TIM2_IRQ_PRIORITY 2 +#define STM32_GPT_TIM3_IRQ_PRIORITY 2 +#define STM32_GPT_TIM14_IRQ_PRIORITY 2 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 3 +#define STM32_I2C_I2C2_IRQ_PRIORITY 3 +#define STM32_I2C_USE_DMA TRUE +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#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_TIM3 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 3 +#define STM32_ICU_TIM2_IRQ_PRIORITY 3 +#define STM32_ICU_TIM3_IRQ_PRIORITY 3 + +/* + * 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_TIM1_IRQ_PRIORITY 3 +#define STM32_PWM_TIM2_IRQ_PRIORITY 3 +#define STM32_PWM_TIM3_IRQ_PRIORITY 3 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USART1_PRIORITY 3 +#define STM32_SERIAL_USART2_PRIORITY 3 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 2 +#define STM32_SPI_SPI2_IRQ_PRIORITY 2 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 2 +#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_USART1_IRQ_PRIORITY 3 +#define STM32_UART_USART2_IRQ_PRIORITY 3 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#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_LP_IRQ_PRIORITY 3 + +#endif /* _MCUCONF_H_ */ \ No newline at end of file diff --git a/platforms/chibios/GENERIC_STM32_F072XB/board/board.c b/platforms/chibios/GENERIC_STM32_F072XB/board/board.c deleted file mode 100644 index c91136e8f664..000000000000 --- a/platforms/chibios/GENERIC_STM32_F072XB/board/board.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - 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. -*/ - -/* - * This file has been automatically generated using ChibiStudio board - * generator plugin. Do not edit manually. - */ - -#include "hal.h" -#include "stm32_gpio.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief Type of STM32 GPIO port setup. - */ -typedef struct { - uint32_t moder; - uint32_t otyper; - uint32_t ospeedr; - uint32_t pupdr; - uint32_t odr; - uint32_t afrl; - uint32_t afrh; -} gpio_setup_t; - -/** - * @brief Type of STM32 GPIO initialization data. - */ -typedef struct { -#if STM32_HAS_GPIOA || defined(__DOXYGEN__) - gpio_setup_t PAData; -#endif -#if STM32_HAS_GPIOB || defined(__DOXYGEN__) - gpio_setup_t PBData; -#endif -#if STM32_HAS_GPIOC || defined(__DOXYGEN__) - gpio_setup_t PCData; -#endif -#if STM32_HAS_GPIOD || defined(__DOXYGEN__) - gpio_setup_t PDData; -#endif -#if STM32_HAS_GPIOE || defined(__DOXYGEN__) - gpio_setup_t PEData; -#endif -#if STM32_HAS_GPIOF || defined(__DOXYGEN__) - gpio_setup_t PFData; -#endif -#if STM32_HAS_GPIOG || defined(__DOXYGEN__) - gpio_setup_t PGData; -#endif -#if STM32_HAS_GPIOH || defined(__DOXYGEN__) - gpio_setup_t PHData; -#endif -#if STM32_HAS_GPIOI || defined(__DOXYGEN__) - gpio_setup_t PIData; -#endif -#if STM32_HAS_GPIOJ || defined(__DOXYGEN__) - gpio_setup_t PJData; -#endif -#if STM32_HAS_GPIOK || defined(__DOXYGEN__) - gpio_setup_t PKData; -#endif -} gpio_config_t; - -/** - * @brief STM32 GPIO static initialization data. - */ -static const gpio_config_t gpio_default_config = { -#if STM32_HAS_GPIOA - {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, -#endif -#if STM32_HAS_GPIOB - {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, -#endif -#if STM32_HAS_GPIOC - {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, -#endif -#if STM32_HAS_GPIOD - {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, -#endif -#if STM32_HAS_GPIOE - {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, -#endif -#if STM32_HAS_GPIOF - {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, -#endif -#if STM32_HAS_GPIOG - {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, -#endif -#if STM32_HAS_GPIOH - {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, -#endif -#if STM32_HAS_GPIOI - {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}, -#endif -#if STM32_HAS_GPIOJ - {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR, VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH}, -#endif -#if STM32_HAS_GPIOK - {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR, VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH} -#endif -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) { - gpiop->OTYPER = config->otyper; - gpiop->OSPEEDR = config->ospeedr; - gpiop->PUPDR = config->pupdr; - gpiop->ODR = config->odr; - gpiop->AFRL = config->afrl; - gpiop->AFRH = config->afrh; - gpiop->MODER = config->moder; -} - -static void stm32_gpio_init(void) { - /* Enabling GPIO-related clocks, the mask comes from the - registry header file.*/ - rccResetAHB(STM32_GPIO_EN_MASK); - rccEnableAHB(STM32_GPIO_EN_MASK, true); - - /* Initializing all the defined GPIO ports.*/ -#if STM32_HAS_GPIOA - gpio_init(GPIOA, &gpio_default_config.PAData); -#endif -#if STM32_HAS_GPIOB - gpio_init(GPIOB, &gpio_default_config.PBData); -#endif -#if STM32_HAS_GPIOC - gpio_init(GPIOC, &gpio_default_config.PCData); -#endif -#if STM32_HAS_GPIOD - gpio_init(GPIOD, &gpio_default_config.PDData); -#endif -#if STM32_HAS_GPIOE - gpio_init(GPIOE, &gpio_default_config.PEData); -#endif -#if STM32_HAS_GPIOF - gpio_init(GPIOF, &gpio_default_config.PFData); -#endif -#if STM32_HAS_GPIOG - gpio_init(GPIOG, &gpio_default_config.PGData); -#endif -#if STM32_HAS_GPIOH - gpio_init(GPIOH, &gpio_default_config.PHData); -#endif -#if STM32_HAS_GPIOI - gpio_init(GPIOI, &gpio_default_config.PIData); -#endif -#if STM32_HAS_GPIOJ - gpio_init(GPIOJ, &gpio_default_config.PJData); -#endif -#if STM32_HAS_GPIOK - gpio_init(GPIOK, &gpio_default_config.PKData); -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -__attribute__((weak)) void enter_bootloader_mode_if_requested(void) {} - -/** - * @brief Early initialization code. - * @details GPIO ports and system clocks are initialized before everything - * else. - */ -void __early_init(void) { - enter_bootloader_mode_if_requested(); - - stm32_gpio_init(); - stm32_clock_init(); -} - -#if HAL_USE_SDC || defined(__DOXYGEN__) -/** - * @brief SDC card detection. - */ -bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { - (void)sdcp; - /* TODO: Fill the implementation.*/ - return true; -} - -/** - * @brief SDC card write protection detection. - */ -bool sdc_lld_is_write_protected(SDCDriver *sdcp) { - (void)sdcp; - /* TODO: Fill the implementation.*/ - return false; -} -#endif /* HAL_USE_SDC */ - -#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) -/** - * @brief MMC_SPI card detection. - */ -bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { - (void)mmcp; - /* TODO: Fill the implementation.*/ - return true; -} - -/** - * @brief MMC_SPI card write protection detection. - */ -bool mmc_lld_is_write_protected(MMCDriver *mmcp) { - (void)mmcp; - /* TODO: Fill the implementation.*/ - return false; -} -#endif - -/** - * @brief Board-specific initialization code. - * @todo Add your board-specific code, if any. - */ -void boardInit(void) {} diff --git a/platforms/chibios/GENERIC_STM32_F072XB/board/board.h b/platforms/chibios/GENERIC_STM32_F072XB/board/board.h deleted file mode 100644 index 87570e62d2ab..000000000000 --- a/platforms/chibios/GENERIC_STM32_F072XB/board/board.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - 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. -*/ - -/* - * This file has been automatically generated using ChibiStudio board - * generator plugin. Do not edit manually. - */ - -#ifndef BOARD_H -#define BOARD_H - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/* - * Setup for Generic STM32_F072 Board - */ - -/* - * Board identifier. - */ -#define BOARD_GENERIC_STM32_F072XB -#define BOARD_NAME "STM32_F072" - -/* - * Board oscillators-related settings. - * NOTE: LSE not fitted. - * NOTE: HSE not fitted. - */ -#if !defined(STM32_LSECLK) -# define STM32_LSECLK 0U -#endif - -#define STM32_LSEDRV (3U << 3U) - -#if !defined(STM32_HSECLK) -# define STM32_HSECLK 0U -#endif - -#define STM32_HSE_BYPASS - -/* - * MCU type as defined in the ST header. - */ -#define STM32F072xB - -/* - * IO pins assignments. - */ -#define GPIOA_BUTTON 0U -#define GPIOA_PIN1 1U -#define GPIOA_PIN2 2U -#define GPIOA_PIN3 3U -#define GPIOA_PIN4 4U -#define GPIOA_PIN5 5U -#define GPIOA_PIN6 6U -#define GPIOA_PIN7 7U -#define GPIOA_PIN8 8U -#define GPIOA_PIN9 9U -#define GPIOA_PIN10 10U -#define GPIOA_USB_DM 11U -#define GPIOA_USB_DP 12U -#define GPIOA_SWDIO 13U -#define GPIOA_SWCLK 14U -#define GPIOA_PIN15 15U - -#define GPIOB_PIN0 0U -#define GPIOB_PIN1 1U -#define GPIOB_PIN2 2U -#define GPIOB_PIN3 3U -#define GPIOB_PIN4 4U -#define GPIOB_PIN5 5U -#define GPIOB_PIN6 6U -#define GPIOB_PIN7 7U -#define GPIOB_PIN8 8U -#define GPIOB_PIN9 9U -#define GPIOB_PIN10 10U -#define GPIOB_PIN11 11U -#define GPIOB_PIN12 12U -#define GPIOB_SPI2_SCK 13U -#define GPIOB_SPI2_MISO 14U -#define GPIOB_SPI2_MOSI 15U - -#define GPIOC_MEMS_CS 0U -#define GPIOC_PIN1 1U -#define GPIOC_PIN2 2U -#define GPIOC_PIN3 3U -#define GPIOC_PIN4 4U -#define GPIOC_PIN5 5U -#define GPIOC_LED_RED 6U -#define GPIOC_LED_BLUE 7U -#define GPIOC_LED_ORANGE 8U -#define GPIOC_LED_GREEN 9U -#define GPIOC_PIN10 10U -#define GPIOC_PIN11 11U -#define GPIOC_PIN12 12U -#define GPIOC_PIN13 13U -#define GPIOC_OSC32_IN 14U -#define GPIOC_OSC32_OUT 15U - -#define GPIOD_PIN0 0U -#define GPIOD_PIN1 1U -#define GPIOD_PIN2 2U -#define GPIOD_PIN3 3U -#define GPIOD_PIN4 4U -#define GPIOD_PIN5 5U -#define GPIOD_PIN6 6U -#define GPIOD_PIN7 7U -#define GPIOD_PIN8 8U -#define GPIOD_PIN9 9U -#define GPIOD_PIN10 10U -#define GPIOD_PIN11 11U -#define GPIOD_PIN12 12U -#define GPIOD_PIN13 13U -#define GPIOD_PIN14 14U -#define GPIOD_PIN15 15U - -#define GPIOE_PIN0 0U -#define GPIOE_PIN1 1U -#define GPIOE_PIN2 2U -#define GPIOE_PIN3 3U -#define GPIOE_PIN4 4U -#define GPIOE_PIN5 5U -#define GPIOE_PIN6 6U -#define GPIOE_PIN7 7U -#define GPIOE_PIN8 8U -#define GPIOE_PIN9 9U -#define GPIOE_PIN10 10U -#define GPIOE_PIN11 11U -#define GPIOE_PIN12 12U -#define GPIOE_PIN13 13U -#define GPIOE_PIN14 14U -#define GPIOE_PIN15 15U - -#define GPIOF_OSC_IN 0U -#define GPIOF_OSC_OUT 1U -#define GPIOF_PIN2 2U -#define GPIOF_PIN3 3U -#define GPIOF_PIN4 4U -#define GPIOF_PIN5 5U -#define GPIOF_PIN6 6U -#define GPIOF_PIN7 7U -#define GPIOF_PIN8 8U -#define GPIOF_PIN9 9U -#define GPIOF_PIN10 10U -#define GPIOF_PIN11 11U -#define GPIOF_PIN12 12U -#define GPIOF_PIN13 13U -#define GPIOF_PIN14 14U -#define GPIOF_PIN15 15U - -/* - * IO lines assignments. - */ -#define LINE_BUTTON PAL_LINE(GPIOA, 0U) -#define LINE_USB_DM PAL_LINE(GPIOA, 11U) -#define LINE_USB_DP PAL_LINE(GPIOA, 12U) -#define LINE_SWDIO PAL_LINE(GPIOA, 13U) -#define LINE_SWCLK PAL_LINE(GPIOA, 14U) -#define LINE_SPI2_SCK PAL_LINE(GPIOB, 13U) -#define LINE_SPI2_MISO PAL_LINE(GPIOB, 14U) -#define LINE_SPI2_MOSI PAL_LINE(GPIOB, 15U) -#define LINE_MEMS_CS PAL_LINE(GPIOC, 0U) -#define LINE_LED_RED PAL_LINE(GPIOC, 6U) -#define LINE_LED_BLUE PAL_LINE(GPIOC, 7U) -#define LINE_LED_ORANGE PAL_LINE(GPIOC, 8U) -#define LINE_LED_GREEN PAL_LINE(GPIOC, 9U) -#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U) -#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U) -#define LINE_OSC_IN PAL_LINE(GPIOF, 0U) -#define LINE_OSC_OUT PAL_LINE(GPIOF, 1U) - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/* - * I/O ports initial setup, this configuration is established soon after reset - * in the initialization code. - * Please refer to the STM32 Reference Manual for details. - */ -#define PIN_MODE_INPUT(n) (0U << ((n)*2U)) -#define PIN_MODE_OUTPUT(n) (1U << ((n)*2U)) -#define PIN_MODE_ALTERNATE(n) (2U << ((n)*2U)) -#define PIN_MODE_ANALOG(n) (3U << ((n)*2U)) -#define PIN_ODR_LOW(n) (0U << (n)) -#define PIN_ODR_HIGH(n) (1U << (n)) -#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) -#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) -#define PIN_OSPEED_VERYLOW(n) (0U << ((n)*2U)) -#define PIN_OSPEED_LOW(n) (1U << ((n)*2U)) -#define PIN_OSPEED_MEDIUM(n) (2U << ((n)*2U)) -#define PIN_OSPEED_HIGH(n) (3U << ((n)*2U)) -#define PIN_PUPDR_FLOATING(n) (0U << ((n)*2U)) -#define PIN_PUPDR_PULLUP(n) (1U << ((n)*2U)) -#define PIN_PUPDR_PULLDOWN(n) (2U << ((n)*2U)) -#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) - -/* - * GPIOA setup: - * - * PA0 - BUTTON (input floating). - * PA1 - PIN1 (input pullup). - * PA2 - PIN2 (input pullup). - * PA3 - PIN3 (input pullup). - * PA4 - PIN4 (input pullup). - * PA5 - PIN5 (input pullup). - * PA6 - PIN6 (input pullup). - * PA7 - PIN7 (input pullup). - * PA8 - PIN8 (input pullup). - * PA9 - PIN9 (input pullup). - * PA10 - PIN10 (input pullup). - * PA11 - USB_DM (input floating). - * PA12 - USB_DP (input floating). - * PA13 - SWDIO (alternate 0). - * PA14 - SWCLK (alternate 0). - * PA15 - PIN15 (input pullup). - */ -#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_BUTTON) | PIN_MODE_INPUT(GPIOA_PIN1) | PIN_MODE_INPUT(GPIOA_PIN2) | PIN_MODE_INPUT(GPIOA_PIN3) | PIN_MODE_INPUT(GPIOA_PIN4) | PIN_MODE_INPUT(GPIOA_PIN5) | PIN_MODE_INPUT(GPIOA_PIN6) | PIN_MODE_INPUT(GPIOA_PIN7) | PIN_MODE_INPUT(GPIOA_PIN8) | PIN_MODE_INPUT(GPIOA_PIN9) | PIN_MODE_INPUT(GPIOA_PIN10) | PIN_MODE_INPUT(GPIOA_USB_DM) | PIN_MODE_INPUT(GPIOA_USB_DP) | PIN_MODE_ALTERNATE(GPIOA_SWDIO) | PIN_MODE_ALTERNATE(GPIOA_SWCLK) | PIN_MODE_INPUT(GPIOA_PIN15)) -#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_BUTTON) | PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | PIN_OTYPE_PUSHPULL(GPIOA_PIN2) | PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) -#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_BUTTON) | PIN_OSPEED_VERYLOW(GPIOA_PIN1) | PIN_OSPEED_VERYLOW(GPIOA_PIN2) | PIN_OSPEED_VERYLOW(GPIOA_PIN3) | PIN_OSPEED_VERYLOW(GPIOA_PIN4) | PIN_OSPEED_VERYLOW(GPIOA_PIN5) | PIN_OSPEED_VERYLOW(GPIOA_PIN6) | PIN_OSPEED_VERYLOW(GPIOA_PIN7) | PIN_OSPEED_VERYLOW(GPIOA_PIN8) | PIN_OSPEED_VERYLOW(GPIOA_PIN9) | PIN_OSPEED_VERYLOW(GPIOA_PIN10) | PIN_OSPEED_VERYLOW(GPIOA_USB_DM) | PIN_OSPEED_VERYLOW(GPIOA_USB_DP) | PIN_OSPEED_HIGH(GPIOA_SWDIO) | PIN_OSPEED_HIGH(GPIOA_SWCLK) | PIN_OSPEED_HIGH(GPIOA_PIN15)) -#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_BUTTON) | PIN_PUPDR_PULLUP(GPIOA_PIN1) | PIN_PUPDR_PULLUP(GPIOA_PIN2) | PIN_PUPDR_PULLUP(GPIOA_PIN3) | PIN_PUPDR_PULLUP(GPIOA_PIN4) | PIN_PUPDR_PULLUP(GPIOA_PIN5) | PIN_PUPDR_PULLUP(GPIOA_PIN6) | PIN_PUPDR_PULLUP(GPIOA_PIN7) | PIN_PUPDR_PULLUP(GPIOA_PIN8) | PIN_PUPDR_PULLUP(GPIOA_PIN9) | PIN_PUPDR_PULLUP(GPIOA_PIN10) | PIN_PUPDR_FLOATING(GPIOA_USB_DM) | PIN_PUPDR_FLOATING(GPIOA_USB_DP) | PIN_PUPDR_PULLUP(GPIOA_SWDIO) | PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | PIN_PUPDR_PULLUP(GPIOA_PIN15)) -#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_BUTTON) | PIN_ODR_HIGH(GPIOA_PIN1) | PIN_ODR_HIGH(GPIOA_PIN2) | PIN_ODR_HIGH(GPIOA_PIN3) | PIN_ODR_HIGH(GPIOA_PIN4) | PIN_ODR_HIGH(GPIOA_PIN5) | PIN_ODR_HIGH(GPIOA_PIN6) | PIN_ODR_HIGH(GPIOA_PIN7) | PIN_ODR_HIGH(GPIOA_PIN8) | PIN_ODR_HIGH(GPIOA_PIN9) | PIN_ODR_HIGH(GPIOA_PIN10) | PIN_ODR_HIGH(GPIOA_USB_DM) | PIN_ODR_HIGH(GPIOA_USB_DP) | PIN_ODR_HIGH(GPIOA_SWDIO) | PIN_ODR_HIGH(GPIOA_SWCLK) | PIN_ODR_HIGH(GPIOA_PIN15)) -#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_BUTTON, 0U) | PIN_AFIO_AF(GPIOA_PIN1, 0U) | PIN_AFIO_AF(GPIOA_PIN2, 0U) | PIN_AFIO_AF(GPIOA_PIN3, 0U) | PIN_AFIO_AF(GPIOA_PIN4, 0U) | PIN_AFIO_AF(GPIOA_PIN5, 0U) | PIN_AFIO_AF(GPIOA_PIN6, 0U) | PIN_AFIO_AF(GPIOA_PIN7, 0U)) -#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0U) | PIN_AFIO_AF(GPIOA_PIN9, 0U) | PIN_AFIO_AF(GPIOA_PIN10, 0U) | PIN_AFIO_AF(GPIOA_USB_DM, 0U) | PIN_AFIO_AF(GPIOA_USB_DP, 0U) | PIN_AFIO_AF(GPIOA_SWDIO, 0U) | PIN_AFIO_AF(GPIOA_SWCLK, 0U) | PIN_AFIO_AF(GPIOA_PIN15, 0U)) - -/* - * GPIOB setup: - * - * PB0 - PIN0 (input pullup). - * PB1 - PIN1 (input pullup). - * PB2 - PIN2 (input pullup). - * PB3 - PIN3 (input pullup). - * PB4 - PIN4 (input pullup). - * PB5 - PIN5 (input pullup). - * PB6 - PIN6 (input pullup). - * PB7 - PIN7 (input pullup). - * PB8 - PIN8 (input pullup). - * PB9 - PIN9 (input pullup). - * PB10 - PIN10 (input pullup). - * PB11 - PIN11 (input pullup). - * PB12 - PIN12 (input pullup). - * PB13 - SPI2_SCK (alternate 0). - * PB14 - SPI2_MISO (alternate 0). - * PB15 - SPI2_MOSI (alternate 0). - */ -#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | PIN_MODE_INPUT(GPIOB_PIN1) | PIN_MODE_INPUT(GPIOB_PIN2) | PIN_MODE_INPUT(GPIOB_PIN3) | PIN_MODE_INPUT(GPIOB_PIN4) | PIN_MODE_INPUT(GPIOB_PIN5) | PIN_MODE_INPUT(GPIOB_PIN6) | PIN_MODE_INPUT(GPIOB_PIN7) | PIN_MODE_INPUT(GPIOB_PIN8) | PIN_MODE_INPUT(GPIOB_PIN9) | PIN_MODE_INPUT(GPIOB_PIN10) | PIN_MODE_INPUT(GPIOB_PIN11) | PIN_MODE_INPUT(GPIOB_PIN12) | PIN_MODE_ALTERNATE(GPIOB_SPI2_SCK) | PIN_MODE_ALTERNATE(GPIOB_SPI2_MISO) | PIN_MODE_ALTERNATE(GPIOB_SPI2_MOSI)) -#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | PIN_OTYPE_PUSHPULL(GPIOB_PIN6) | PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | PIN_OTYPE_PUSHPULL(GPIOB_SPI2_SCK) | PIN_OTYPE_PUSHPULL(GPIOB_SPI2_MISO) | PIN_OTYPE_PUSHPULL(GPIOB_SPI2_MOSI)) -#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | PIN_OSPEED_VERYLOW(GPIOB_PIN1) | PIN_OSPEED_HIGH(GPIOB_PIN2) | PIN_OSPEED_HIGH(GPIOB_PIN3) | PIN_OSPEED_HIGH(GPIOB_PIN4) | PIN_OSPEED_VERYLOW(GPIOB_PIN5) | PIN_OSPEED_VERYLOW(GPIOB_PIN6) | PIN_OSPEED_VERYLOW(GPIOB_PIN7) | PIN_OSPEED_VERYLOW(GPIOB_PIN8) | PIN_OSPEED_VERYLOW(GPIOB_PIN9) | PIN_OSPEED_VERYLOW(GPIOB_PIN10) | PIN_OSPEED_VERYLOW(GPIOB_PIN11) | PIN_OSPEED_VERYLOW(GPIOB_PIN12) | PIN_OSPEED_VERYLOW(GPIOB_SPI2_SCK) | PIN_OSPEED_VERYLOW(GPIOB_SPI2_MISO) | PIN_OSPEED_VERYLOW(GPIOB_SPI2_MOSI)) -#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | PIN_PUPDR_PULLUP(GPIOB_PIN1) | PIN_PUPDR_PULLUP(GPIOB_PIN2) | PIN_PUPDR_PULLUP(GPIOB_PIN3) | PIN_PUPDR_PULLUP(GPIOB_PIN4) | PIN_PUPDR_PULLUP(GPIOB_PIN5) | PIN_PUPDR_PULLUP(GPIOB_PIN6) | PIN_PUPDR_PULLUP(GPIOB_PIN7) | PIN_PUPDR_PULLUP(GPIOB_PIN8) | PIN_PUPDR_PULLUP(GPIOB_PIN9) | PIN_PUPDR_PULLUP(GPIOB_PIN10) | PIN_PUPDR_PULLUP(GPIOB_PIN11) | PIN_PUPDR_PULLUP(GPIOB_PIN12) | PIN_PUPDR_FLOATING(GPIOB_SPI2_SCK) | PIN_PUPDR_FLOATING(GPIOB_SPI2_MISO) | PIN_PUPDR_FLOATING(GPIOB_SPI2_MOSI)) -#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | PIN_ODR_HIGH(GPIOB_PIN1) | PIN_ODR_HIGH(GPIOB_PIN2) | PIN_ODR_HIGH(GPIOB_PIN3) | PIN_ODR_HIGH(GPIOB_PIN4) | PIN_ODR_HIGH(GPIOB_PIN5) | PIN_ODR_HIGH(GPIOB_PIN6) | PIN_ODR_HIGH(GPIOB_PIN7) | PIN_ODR_HIGH(GPIOB_PIN8) | PIN_ODR_HIGH(GPIOB_PIN9) | PIN_ODR_HIGH(GPIOB_PIN10) | PIN_ODR_HIGH(GPIOB_PIN11) | PIN_ODR_HIGH(GPIOB_PIN12) | PIN_ODR_HIGH(GPIOB_SPI2_SCK) | PIN_ODR_HIGH(GPIOB_SPI2_MISO) | PIN_ODR_HIGH(GPIOB_SPI2_MOSI)) -#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | PIN_AFIO_AF(GPIOB_PIN1, 0U) | PIN_AFIO_AF(GPIOB_PIN2, 0U) | PIN_AFIO_AF(GPIOB_PIN3, 0U) | PIN_AFIO_AF(GPIOB_PIN4, 0U) | PIN_AFIO_AF(GPIOB_PIN5, 0U) | PIN_AFIO_AF(GPIOB_PIN6, 0U) | PIN_AFIO_AF(GPIOB_PIN7, 0U)) -#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0U) | PIN_AFIO_AF(GPIOB_PIN9, 0U) | PIN_AFIO_AF(GPIOB_PIN10, 0U) | PIN_AFIO_AF(GPIOB_PIN11, 0U) | PIN_AFIO_AF(GPIOB_PIN12, 0U) | PIN_AFIO_AF(GPIOB_SPI2_SCK, 0U) | PIN_AFIO_AF(GPIOB_SPI2_MISO, 0U) | PIN_AFIO_AF(GPIOB_SPI2_MOSI, 0U)) - -/* - * GPIOC setup: - * - * PC0 - MEMS_CS (output pushpull maximum). - * PC1 - PIN1 (input pullup). - * PC2 - PIN2 (input pullup). - * PC3 - PIN3 (input pullup). - * PC4 - PIN4 (input pullup). - * PC5 - PIN5 (input pullup). - * PC6 - LED_RED (output pushpull maximum). - * PC7 - LED_BLUE (output pushpull maximum). - * PC8 - LED_ORANGE (output pushpull maximum). - * PC9 - LED_GREEN (output pushpull maximum). - * PC10 - PIN10 (input pullup). - * PC11 - PIN11 (input pullup). - * PC12 - PIN12 (input pullup). - * PC13 - PIN13 (input pullup). - * PC14 - OSC32_IN (input floating). - * PC15 - OSC32_OUT (input floating). - */ -#define VAL_GPIOC_MODER (PIN_MODE_OUTPUT(GPIOC_MEMS_CS) | PIN_MODE_INPUT(GPIOC_PIN1) | PIN_MODE_INPUT(GPIOC_PIN2) | PIN_MODE_INPUT(GPIOC_PIN3) | PIN_MODE_INPUT(GPIOC_PIN4) | PIN_MODE_INPUT(GPIOC_PIN5) | PIN_MODE_OUTPUT(GPIOC_LED_RED) | PIN_MODE_OUTPUT(GPIOC_LED_BLUE) | PIN_MODE_OUTPUT(GPIOC_LED_ORANGE) | PIN_MODE_OUTPUT(GPIOC_LED_GREEN) | PIN_MODE_INPUT(GPIOC_PIN10) | PIN_MODE_INPUT(GPIOC_PIN11) | PIN_MODE_INPUT(GPIOC_PIN12) | PIN_MODE_INPUT(GPIOC_PIN13) | PIN_MODE_INPUT(GPIOC_OSC32_IN) | PIN_MODE_INPUT(GPIOC_OSC32_OUT)) -#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_MEMS_CS) | PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | PIN_OTYPE_PUSHPULL(GPIOC_LED_RED) | PIN_OTYPE_PUSHPULL(GPIOC_LED_BLUE) | PIN_OTYPE_PUSHPULL(GPIOC_LED_ORANGE) | PIN_OTYPE_PUSHPULL(GPIOC_LED_GREEN) | PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT)) -#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_MEMS_CS) | PIN_OSPEED_VERYLOW(GPIOC_PIN1) | PIN_OSPEED_VERYLOW(GPIOC_PIN2) | PIN_OSPEED_VERYLOW(GPIOC_PIN3) | PIN_OSPEED_VERYLOW(GPIOC_PIN4) | PIN_OSPEED_VERYLOW(GPIOC_PIN5) | PIN_OSPEED_HIGH(GPIOC_LED_RED) | PIN_OSPEED_HIGH(GPIOC_LED_BLUE) | PIN_OSPEED_HIGH(GPIOC_LED_ORANGE) | PIN_OSPEED_HIGH(GPIOC_LED_GREEN) | PIN_OSPEED_VERYLOW(GPIOC_PIN10) | PIN_OSPEED_VERYLOW(GPIOC_PIN11) | PIN_OSPEED_VERYLOW(GPIOC_PIN12) | PIN_OSPEED_VERYLOW(GPIOC_PIN13) | PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | PIN_OSPEED_HIGH(GPIOC_OSC32_OUT)) -#define VAL_GPIOC_PUPDR (PIN_PUPDR_FLOATING(GPIOC_MEMS_CS) | PIN_PUPDR_PULLUP(GPIOC_PIN1) | PIN_PUPDR_PULLUP(GPIOC_PIN2) | PIN_PUPDR_PULLUP(GPIOC_PIN3) | PIN_PUPDR_PULLUP(GPIOC_PIN4) | PIN_PUPDR_PULLUP(GPIOC_PIN5) | PIN_PUPDR_FLOATING(GPIOC_LED_RED) | PIN_PUPDR_FLOATING(GPIOC_LED_BLUE) | PIN_PUPDR_FLOATING(GPIOC_LED_ORANGE) | PIN_PUPDR_FLOATING(GPIOC_LED_GREEN) | PIN_PUPDR_PULLUP(GPIOC_PIN10) | PIN_PUPDR_PULLUP(GPIOC_PIN11) | PIN_PUPDR_PULLUP(GPIOC_PIN12) | PIN_PUPDR_PULLUP(GPIOC_PIN13) | PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT)) -#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_MEMS_CS) | PIN_ODR_HIGH(GPIOC_PIN1) | PIN_ODR_HIGH(GPIOC_PIN2) | PIN_ODR_HIGH(GPIOC_PIN3) | PIN_ODR_HIGH(GPIOC_PIN4) | PIN_ODR_HIGH(GPIOC_PIN5) | PIN_ODR_LOW(GPIOC_LED_RED) | PIN_ODR_LOW(GPIOC_LED_BLUE) | PIN_ODR_LOW(GPIOC_LED_ORANGE) | PIN_ODR_LOW(GPIOC_LED_GREEN) | PIN_ODR_HIGH(GPIOC_PIN10) | PIN_ODR_HIGH(GPIOC_PIN11) | PIN_ODR_HIGH(GPIOC_PIN12) | PIN_ODR_HIGH(GPIOC_PIN13) | PIN_ODR_HIGH(GPIOC_OSC32_IN) | PIN_ODR_HIGH(GPIOC_OSC32_OUT)) -#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_MEMS_CS, 0U) | PIN_AFIO_AF(GPIOC_PIN1, 0U) | PIN_AFIO_AF(GPIOC_PIN2, 0U) | PIN_AFIO_AF(GPIOC_PIN3, 0U) | PIN_AFIO_AF(GPIOC_PIN4, 0U) | PIN_AFIO_AF(GPIOC_PIN5, 0U) | PIN_AFIO_AF(GPIOC_LED_RED, 0U) | PIN_AFIO_AF(GPIOC_LED_BLUE, 0U)) -#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_LED_ORANGE, 0U) | PIN_AFIO_AF(GPIOC_LED_GREEN, 0U) | PIN_AFIO_AF(GPIOC_PIN10, 0U) | PIN_AFIO_AF(GPIOC_PIN11, 0U) | PIN_AFIO_AF(GPIOC_PIN12, 0U) | PIN_AFIO_AF(GPIOC_PIN13, 0U) | PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U)) - -/* - * GPIOD setup: - * - * PD0 - PIN0 (input pullup). - * PD1 - PIN1 (input pullup). - * PD2 - PIN2 (input pullup). - * PD3 - PIN3 (input pullup). - * PD4 - PIN4 (input pullup). - * PD5 - PIN5 (input pullup). - * PD6 - PIN6 (input pullup). - * PD7 - PIN7 (input pullup). - * PD8 - PIN8 (input pullup). - * PD9 - PIN9 (input pullup). - * PD10 - PIN10 (input pullup). - * PD11 - PIN11 (input pullup). - * PD12 - PIN12 (input pullup). - * PD13 - PIN13 (input pullup). - * PD14 - PIN14 (input pullup). - * PD15 - PIN15 (input pullup). - */ -#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | PIN_MODE_INPUT(GPIOD_PIN1) | PIN_MODE_INPUT(GPIOD_PIN2) | PIN_MODE_INPUT(GPIOD_PIN3) | PIN_MODE_INPUT(GPIOD_PIN4) | PIN_MODE_INPUT(GPIOD_PIN5) | PIN_MODE_INPUT(GPIOD_PIN6) | PIN_MODE_INPUT(GPIOD_PIN7) | PIN_MODE_INPUT(GPIOD_PIN8) | PIN_MODE_INPUT(GPIOD_PIN9) | PIN_MODE_INPUT(GPIOD_PIN10) | PIN_MODE_INPUT(GPIOD_PIN11) | PIN_MODE_INPUT(GPIOD_PIN12) | PIN_MODE_INPUT(GPIOD_PIN13) | PIN_MODE_INPUT(GPIOD_PIN14) | PIN_MODE_INPUT(GPIOD_PIN15)) -#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) -#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | PIN_OSPEED_VERYLOW(GPIOD_PIN1) | PIN_OSPEED_VERYLOW(GPIOD_PIN2) | PIN_OSPEED_VERYLOW(GPIOD_PIN3) | PIN_OSPEED_VERYLOW(GPIOD_PIN4) | PIN_OSPEED_VERYLOW(GPIOD_PIN5) | PIN_OSPEED_VERYLOW(GPIOD_PIN6) | PIN_OSPEED_VERYLOW(GPIOD_PIN7) | PIN_OSPEED_VERYLOW(GPIOD_PIN8) | PIN_OSPEED_VERYLOW(GPIOD_PIN9) | PIN_OSPEED_VERYLOW(GPIOD_PIN10) | PIN_OSPEED_VERYLOW(GPIOD_PIN11) | PIN_OSPEED_VERYLOW(GPIOD_PIN12) | PIN_OSPEED_VERYLOW(GPIOD_PIN13) | PIN_OSPEED_VERYLOW(GPIOD_PIN14) | PIN_OSPEED_VERYLOW(GPIOD_PIN15)) -#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | PIN_PUPDR_PULLUP(GPIOD_PIN1) | PIN_PUPDR_PULLUP(GPIOD_PIN2) | PIN_PUPDR_PULLUP(GPIOD_PIN3) | PIN_PUPDR_PULLUP(GPIOD_PIN4) | PIN_PUPDR_PULLUP(GPIOD_PIN5) | PIN_PUPDR_PULLUP(GPIOD_PIN6) | PIN_PUPDR_PULLUP(GPIOD_PIN7) | PIN_PUPDR_PULLUP(GPIOD_PIN8) | PIN_PUPDR_PULLUP(GPIOD_PIN9) | PIN_PUPDR_PULLUP(GPIOD_PIN10) | PIN_PUPDR_PULLUP(GPIOD_PIN11) | PIN_PUPDR_PULLUP(GPIOD_PIN12) | PIN_PUPDR_PULLUP(GPIOD_PIN13) | PIN_PUPDR_PULLUP(GPIOD_PIN14) | PIN_PUPDR_PULLUP(GPIOD_PIN15)) -#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | PIN_ODR_HIGH(GPIOD_PIN1) | PIN_ODR_HIGH(GPIOD_PIN2) | PIN_ODR_HIGH(GPIOD_PIN3) | PIN_ODR_HIGH(GPIOD_PIN4) | PIN_ODR_HIGH(GPIOD_PIN5) | PIN_ODR_HIGH(GPIOD_PIN6) | PIN_ODR_HIGH(GPIOD_PIN7) | PIN_ODR_HIGH(GPIOD_PIN8) | PIN_ODR_HIGH(GPIOD_PIN9) | PIN_ODR_HIGH(GPIOD_PIN10) | PIN_ODR_HIGH(GPIOD_PIN11) | PIN_ODR_HIGH(GPIOD_PIN12) | PIN_ODR_HIGH(GPIOD_PIN13) | PIN_ODR_HIGH(GPIOD_PIN14) | PIN_ODR_HIGH(GPIOD_PIN15)) -#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | PIN_AFIO_AF(GPIOD_PIN1, 0U) | PIN_AFIO_AF(GPIOD_PIN2, 0U) | PIN_AFIO_AF(GPIOD_PIN3, 0U) | PIN_AFIO_AF(GPIOD_PIN4, 0U) | PIN_AFIO_AF(GPIOD_PIN5, 0U) | PIN_AFIO_AF(GPIOD_PIN6, 0U) | PIN_AFIO_AF(GPIOD_PIN7, 0U)) -#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | PIN_AFIO_AF(GPIOD_PIN9, 0U) | PIN_AFIO_AF(GPIOD_PIN10, 0U) | PIN_AFIO_AF(GPIOD_PIN11, 0U) | PIN_AFIO_AF(GPIOD_PIN12, 0U) | PIN_AFIO_AF(GPIOD_PIN13, 0U) | PIN_AFIO_AF(GPIOD_PIN14, 0U) | PIN_AFIO_AF(GPIOD_PIN15, 0U)) - -/* - * GPIOE setup: - * - * PE0 - PIN0 (input pullup). - * PE1 - PIN1 (input pullup). - * PE2 - PIN2 (input pullup). - * PE3 - PIN3 (input pullup). - * PE4 - PIN4 (input pullup). - * PE5 - PIN5 (input pullup). - * PE6 - PIN6 (input pullup). - * PE7 - PIN7 (input pullup). - * PE8 - PIN8 (input pullup). - * PE9 - PIN9 (input pullup). - * PE10 - PIN10 (input pullup). - * PE11 - PIN11 (input pullup). - * PE12 - PIN12 (input pullup). - * PE13 - PIN13 (input pullup). - * PE14 - PIN14 (input pullup). - * PE15 - PIN15 (input pullup). - */ -#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | PIN_MODE_INPUT(GPIOE_PIN1) | PIN_MODE_INPUT(GPIOE_PIN2) | PIN_MODE_INPUT(GPIOE_PIN3) | PIN_MODE_INPUT(GPIOE_PIN4) | PIN_MODE_INPUT(GPIOE_PIN5) | PIN_MODE_INPUT(GPIOE_PIN6) | PIN_MODE_INPUT(GPIOE_PIN7) | PIN_MODE_INPUT(GPIOE_PIN8) | PIN_MODE_INPUT(GPIOE_PIN9) | PIN_MODE_INPUT(GPIOE_PIN10) | PIN_MODE_INPUT(GPIOE_PIN11) | PIN_MODE_INPUT(GPIOE_PIN12) | PIN_MODE_INPUT(GPIOE_PIN13) | PIN_MODE_INPUT(GPIOE_PIN14) | PIN_MODE_INPUT(GPIOE_PIN15)) -#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) -#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) | PIN_OSPEED_VERYLOW(GPIOE_PIN1) | PIN_OSPEED_VERYLOW(GPIOE_PIN2) | PIN_OSPEED_VERYLOW(GPIOE_PIN3) | PIN_OSPEED_VERYLOW(GPIOE_PIN4) | PIN_OSPEED_VERYLOW(GPIOE_PIN5) | PIN_OSPEED_VERYLOW(GPIOE_PIN6) | PIN_OSPEED_VERYLOW(GPIOE_PIN7) | PIN_OSPEED_VERYLOW(GPIOE_PIN8) | PIN_OSPEED_VERYLOW(GPIOE_PIN9) | PIN_OSPEED_VERYLOW(GPIOE_PIN10) | PIN_OSPEED_VERYLOW(GPIOE_PIN11) | PIN_OSPEED_VERYLOW(GPIOE_PIN12) | PIN_OSPEED_VERYLOW(GPIOE_PIN13) | PIN_OSPEED_VERYLOW(GPIOE_PIN14) | PIN_OSPEED_VERYLOW(GPIOE_PIN15)) -#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | PIN_PUPDR_PULLUP(GPIOE_PIN1) | PIN_PUPDR_PULLUP(GPIOE_PIN2) | PIN_PUPDR_PULLUP(GPIOE_PIN3) | PIN_PUPDR_PULLUP(GPIOE_PIN4) | PIN_PUPDR_PULLUP(GPIOE_PIN5) | PIN_PUPDR_PULLUP(GPIOE_PIN6) | PIN_PUPDR_PULLUP(GPIOE_PIN7) | PIN_PUPDR_PULLUP(GPIOE_PIN8) | PIN_PUPDR_PULLUP(GPIOE_PIN9) | PIN_PUPDR_PULLUP(GPIOE_PIN10) | PIN_PUPDR_PULLUP(GPIOE_PIN11) | PIN_PUPDR_PULLUP(GPIOE_PIN12) | PIN_PUPDR_PULLUP(GPIOE_PIN13) | PIN_PUPDR_PULLUP(GPIOE_PIN14) | PIN_PUPDR_PULLUP(GPIOE_PIN15)) -#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | PIN_ODR_HIGH(GPIOE_PIN1) | PIN_ODR_HIGH(GPIOE_PIN2) | PIN_ODR_HIGH(GPIOE_PIN3) | PIN_ODR_HIGH(GPIOE_PIN4) | PIN_ODR_HIGH(GPIOE_PIN5) | PIN_ODR_HIGH(GPIOE_PIN6) | PIN_ODR_HIGH(GPIOE_PIN7) | PIN_ODR_HIGH(GPIOE_PIN8) | PIN_ODR_HIGH(GPIOE_PIN9) | PIN_ODR_HIGH(GPIOE_PIN10) | PIN_ODR_HIGH(GPIOE_PIN11) | PIN_ODR_HIGH(GPIOE_PIN12) | PIN_ODR_HIGH(GPIOE_PIN13) | PIN_ODR_HIGH(GPIOE_PIN14) | PIN_ODR_HIGH(GPIOE_PIN15)) -#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | PIN_AFIO_AF(GPIOE_PIN1, 0U) | PIN_AFIO_AF(GPIOE_PIN2, 0U) | PIN_AFIO_AF(GPIOE_PIN3, 0U) | PIN_AFIO_AF(GPIOE_PIN4, 0U) | PIN_AFIO_AF(GPIOE_PIN5, 0U) | PIN_AFIO_AF(GPIOE_PIN6, 0U) | PIN_AFIO_AF(GPIOE_PIN7, 0U)) -#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | PIN_AFIO_AF(GPIOE_PIN9, 0U) | PIN_AFIO_AF(GPIOE_PIN10, 0U) | PIN_AFIO_AF(GPIOE_PIN11, 0U) | PIN_AFIO_AF(GPIOE_PIN12, 0U) | PIN_AFIO_AF(GPIOE_PIN13, 0U) | PIN_AFIO_AF(GPIOE_PIN14, 0U) | PIN_AFIO_AF(GPIOE_PIN15, 0U)) - -/* - * GPIOF setup: - * - * PF0 - OSC_IN (input floating). - * PF1 - OSC_OUT (input floating). - * PF2 - PIN2 (input pullup). - * PF3 - PIN3 (input pullup). - * PF4 - PIN4 (input pullup). - * PF5 - PIN5 (input pullup). - * PF6 - PIN6 (input pullup). - * PF7 - PIN7 (input pullup). - * PF8 - PIN8 (input pullup). - * PF9 - PIN9 (input pullup). - * PF10 - PIN10 (input pullup). - * PF11 - PIN11 (input pullup). - * PF12 - PIN12 (input pullup). - * PF13 - PIN13 (input pullup). - * PF14 - PIN14 (input pullup). - * PF15 - PIN15 (input pullup). - */ -#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_OSC_IN) | PIN_MODE_INPUT(GPIOF_OSC_OUT) | PIN_MODE_INPUT(GPIOF_PIN2) | PIN_MODE_INPUT(GPIOF_PIN3) | PIN_MODE_INPUT(GPIOF_PIN4) | PIN_MODE_INPUT(GPIOF_PIN5) | PIN_MODE_INPUT(GPIOF_PIN6) | PIN_MODE_INPUT(GPIOF_PIN7) | PIN_MODE_INPUT(GPIOF_PIN8) | PIN_MODE_INPUT(GPIOF_PIN9) | PIN_MODE_INPUT(GPIOF_PIN10) | PIN_MODE_INPUT(GPIOF_PIN11) | PIN_MODE_INPUT(GPIOF_PIN12) | PIN_MODE_INPUT(GPIOF_PIN13) | PIN_MODE_INPUT(GPIOF_PIN14) | PIN_MODE_INPUT(GPIOF_PIN15)) -#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_OSC_IN) | PIN_OTYPE_PUSHPULL(GPIOF_OSC_OUT) | PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) -#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOF_OSC_IN) | PIN_OSPEED_VERYLOW(GPIOF_OSC_OUT) | PIN_OSPEED_VERYLOW(GPIOF_PIN2) | PIN_OSPEED_VERYLOW(GPIOF_PIN3) | PIN_OSPEED_VERYLOW(GPIOF_PIN4) | PIN_OSPEED_VERYLOW(GPIOF_PIN5) | PIN_OSPEED_VERYLOW(GPIOF_PIN6) | PIN_OSPEED_VERYLOW(GPIOF_PIN7) | PIN_OSPEED_VERYLOW(GPIOF_PIN8) | PIN_OSPEED_VERYLOW(GPIOF_PIN9) | PIN_OSPEED_VERYLOW(GPIOF_PIN10) | PIN_OSPEED_VERYLOW(GPIOF_PIN11) | PIN_OSPEED_VERYLOW(GPIOF_PIN12) | PIN_OSPEED_VERYLOW(GPIOF_PIN13) | PIN_OSPEED_VERYLOW(GPIOF_PIN14) | PIN_OSPEED_VERYLOW(GPIOF_PIN15)) -#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_OSC_IN) | PIN_PUPDR_FLOATING(GPIOF_OSC_OUT) | PIN_PUPDR_PULLUP(GPIOF_PIN2) | PIN_PUPDR_PULLUP(GPIOF_PIN3) | PIN_PUPDR_PULLUP(GPIOF_PIN4) | PIN_PUPDR_PULLUP(GPIOF_PIN5) | PIN_PUPDR_PULLUP(GPIOF_PIN6) | PIN_PUPDR_PULLUP(GPIOF_PIN7) | PIN_PUPDR_PULLUP(GPIOF_PIN8) | PIN_PUPDR_PULLUP(GPIOF_PIN9) | PIN_PUPDR_PULLUP(GPIOF_PIN10) | PIN_PUPDR_PULLUP(GPIOF_PIN11) | PIN_PUPDR_PULLUP(GPIOF_PIN12) | PIN_PUPDR_PULLUP(GPIOF_PIN13) | PIN_PUPDR_PULLUP(GPIOF_PIN14) | PIN_PUPDR_PULLUP(GPIOF_PIN15)) -#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_OSC_IN) | PIN_ODR_HIGH(GPIOF_OSC_OUT) | PIN_ODR_HIGH(GPIOF_PIN2) | PIN_ODR_HIGH(GPIOF_PIN3) | PIN_ODR_HIGH(GPIOF_PIN4) | PIN_ODR_HIGH(GPIOF_PIN5) | PIN_ODR_HIGH(GPIOF_PIN6) | PIN_ODR_HIGH(GPIOF_PIN7) | PIN_ODR_HIGH(GPIOF_PIN8) | PIN_ODR_HIGH(GPIOF_PIN9) | PIN_ODR_HIGH(GPIOF_PIN10) | PIN_ODR_HIGH(GPIOF_PIN11) | PIN_ODR_HIGH(GPIOF_PIN12) | PIN_ODR_HIGH(GPIOF_PIN13) | PIN_ODR_HIGH(GPIOF_PIN14) | PIN_ODR_HIGH(GPIOF_PIN15)) -#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_OSC_IN, 0U) | PIN_AFIO_AF(GPIOF_OSC_OUT, 0U) | PIN_AFIO_AF(GPIOF_PIN2, 0U) | PIN_AFIO_AF(GPIOF_PIN3, 0U) | PIN_AFIO_AF(GPIOF_PIN4, 0U) | PIN_AFIO_AF(GPIOF_PIN5, 0U) | PIN_AFIO_AF(GPIOF_PIN6, 0U) | PIN_AFIO_AF(GPIOF_PIN7, 0U)) -#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | PIN_AFIO_AF(GPIOF_PIN9, 0U) | PIN_AFIO_AF(GPIOF_PIN10, 0U) | PIN_AFIO_AF(GPIOF_PIN11, 0U) | PIN_AFIO_AF(GPIOF_PIN12, 0U) | PIN_AFIO_AF(GPIOF_PIN13, 0U) | PIN_AFIO_AF(GPIOF_PIN14, 0U) | PIN_AFIO_AF(GPIOF_PIN15, 0U)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(_FROM_ASM_) -# ifdef __cplusplus -extern "C" { -# endif -void boardInit(void); -# ifdef __cplusplus -} -# endif -#endif /* _FROM_ASM_ */ - -#endif /* BOARD_H */ diff --git a/platforms/chibios/GENERIC_STM32_F072XB/board/board.mk b/platforms/chibios/GENERIC_STM32_F072XB/board/board.mk index 842e33590594..3f0e6c46e8c0 100644 --- a/platforms/chibios/GENERIC_STM32_F072XB/board/board.mk +++ b/platforms/chibios/GENERIC_STM32_F072XB/board/board.mk @@ -1,8 +1,8 @@ # List of all the board related files. -BOARDSRC = $(BOARD_PATH)/board/board.c +BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F072RB/board.c # Required include directories -BOARDINC = $(BOARD_PATH)/board +BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_F072RB # Shared variables ALLCSRC += $(BOARDSRC) diff --git a/platforms/chibios/GENERIC_STM32_F072XB/configs/board.h b/platforms/chibios/GENERIC_STM32_F072XB/configs/board.h new file mode 100644 index 000000000000..30af6b0c8608 --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_F072XB/configs/board.h @@ -0,0 +1,20 @@ +/* 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 . + */ +#pragma once + +#include_next "board.h" + +#undef STM32_HSE_BYPASS diff --git a/platforms/chibios/GENERIC_STM32_F072XB/configs/mcuconf.h b/platforms/chibios/GENERIC_STM32_F072XB/configs/mcuconf.h new file mode 100644 index 000000000000..688350e9ce68 --- /dev/null +++ b/platforms/chibios/GENERIC_STM32_F072XB/configs/mcuconf.h @@ -0,0 +1,177 @@ +/* + ChibiOS - Copyright (C) 2006..2015 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_ + +/* + * STM32F0xx 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: + * 3...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F0xx_MCUCONF +// #define STM32F070xB + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI_ENABLED TRUE +#define STM32_HSI14_ENABLED TRUE +#define STM32_HSI48_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED FALSE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2 +#define STM32_PREDIV_VALUE 1 +#define STM32_PLLMUL_VALUE 12 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE STM32_PPRE_DIV1 +#define STM32_ADCSW STM32_ADCSW_HSI14 +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_ADCSW STM32_ADCSW_HSI14 +#define STM32_USBSW STM32_USBSW_HSI48 +#define STM32_CECSW STM32_CECSW_HSI +#define STM32_I2C1SW STM32_I2C1SW_HSI +#define STM32_USART1SW STM32_USART1SW_PCLK +#define STM32_RTCSEL STM32_RTCSEL_LSI + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_1_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI2_3_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI4_15_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI16_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI17_20_IRQ_PRIORITY 3 +#define STM32_IRQ_EXTI21_22_IRQ_PRIORITY 3 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 2 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2 + +/* + * 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_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 2 +#define STM32_GPT_TIM2_IRQ_PRIORITY 2 +#define STM32_GPT_TIM3_IRQ_PRIORITY 2 +#define STM32_GPT_TIM14_IRQ_PRIORITY 2 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 3 +#define STM32_I2C_I2C2_IRQ_PRIORITY 3 +#define STM32_I2C_USE_DMA TRUE +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#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_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_TIM3 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 3 +#define STM32_ICU_TIM2_IRQ_PRIORITY 3 +#define STM32_ICU_TIM3_IRQ_PRIORITY 3 + +/* + * 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 TRUE +#define STM32_PWM_TIM1_IRQ_PRIORITY 3 +#define STM32_PWM_TIM2_IRQ_PRIORITY 3 +#define STM32_PWM_TIM3_IRQ_PRIORITY 3 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USART1_PRIORITY 3 +#define STM32_SERIAL_USART2_PRIORITY 3 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 2 +#define STM32_SPI_SPI2_IRQ_PRIORITY 2 +#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_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 2 +#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_USART1_IRQ_PRIORITY 3 +#define STM32_UART_USART2_IRQ_PRIORITY 3 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#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_LP_IRQ_PRIORITY 3 + +#endif /* _MCUCONF_H_ */ diff --git a/platforms/chibios/GENERIC_STM32_F303XC/configs/config.h b/platforms/chibios/GENERIC_STM32_F303XC/configs/config.h index 48a7a900930a..a73f0c0b475a 100644 --- a/platforms/chibios/GENERIC_STM32_F303XC/configs/config.h +++ b/platforms/chibios/GENERIC_STM32_F303XC/configs/config.h @@ -15,4 +15,6 @@ */ #pragma once -#define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP +# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE +#endif diff --git a/platforms/chibios/STM32_F103_STM32DUINO/configs/mcuconf.h b/platforms/chibios/STM32_F103_STM32DUINO/configs/mcuconf.h new file mode 100644 index 000000000000..9945e7408d12 --- /dev/null +++ b/platforms/chibios/STM32_F103_STM32DUINO/configs/mcuconf.h @@ -0,0 +1,209 @@ +/* + ChibiOS - Copyright (C) 2006..2015 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_ + +#define STM32F103_MCUCONF + +/* + * STM32F103 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. + */ + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED FALSE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 +#define STM32_PLLMUL_VALUE 9 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_USB_CLOCK_REQUIRED TRUE +#define STM32_USBPRE STM32_USBPRE_DIV1P5 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_RTCSEL STM32_RTCSEL_HSEDIV +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC1_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 + +/* + * EXT driver system settings. + */ +#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI17_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI19_IRQ_PRIORITY 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_TIM8 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_TIM8_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_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_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 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 + +/* + * 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_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 + +/* + * RTC driver system settings. + */ +#define STM32_RTC_IRQ_PRIORITY 15 + +/* + * 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_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 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 TRUE +#define STM32_SPI_USE_SPI3 FALSE +#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 + +/* + * 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_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_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_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 + +#endif /* _MCUCONF_H_ */ diff --git a/platforms/chibios/GENERIC_STM32_F303XC/configs/chconf.h b/platforms/chibios/common/configs/chconf.h similarity index 100% rename from platforms/chibios/GENERIC_STM32_F303XC/configs/chconf.h rename to platforms/chibios/common/configs/chconf.h diff --git a/platforms/chibios/GENERIC_STM32_F303XC/configs/halconf.h b/platforms/chibios/common/configs/halconf.h similarity index 100% rename from platforms/chibios/GENERIC_STM32_F303XC/configs/halconf.h rename to platforms/chibios/common/configs/halconf.h diff --git a/platforms/chibios/ld/MKL26Z64.ld b/platforms/chibios/common/ld/MKL26Z64.ld similarity index 100% rename from platforms/chibios/ld/MKL26Z64.ld rename to platforms/chibios/common/ld/MKL26Z64.ld diff --git a/platforms/chibios/ld/STM32F103x8_stm32duino_bootloader.ld b/platforms/chibios/common/ld/STM32F103x8_stm32duino_bootloader.ld similarity index 100% rename from platforms/chibios/ld/STM32F103x8_stm32duino_bootloader.ld rename to platforms/chibios/common/ld/STM32F103x8_stm32duino_bootloader.ld diff --git a/quantum/backlight/backlight_avr.c b/quantum/backlight/backlight_avr.c index b3e882ffe128..4d66da80ba15 100644 --- a/quantum/backlight/backlight_avr.c +++ b/quantum/backlight/backlight_avr.c @@ -3,6 +3,11 @@ #include "backlight_driver_common.h" #include "debug.h" +// Maximum duty cycle limit +#ifndef BACKLIGHT_LIMIT_VAL +# define BACKLIGHT_LIMIT_VAL 255 +#endif + // This logic is a bit complex, we support 3 setups: // // 1. Hardware PWM when backlight is wired to a PWM pin. @@ -240,6 +245,9 @@ static uint16_t cie_lightness(uint16_t v) { } } +// rescale the supplied backlight value to be in terms of the value limit +static uint32_t rescale_limit_val(uint32_t val) { return (val * (BACKLIGHT_LIMIT_VAL + 1)) / 256; } + // range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val. static inline void set_pwm(uint16_t val) { OCRxx = val; } @@ -269,7 +277,7 @@ void backlight_set(uint8_t level) { #endif } // Set the brightness - set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS)); + set_pwm(cie_lightness(rescale_limit_val(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS))); } void backlight_task(void) {} @@ -375,7 +383,7 @@ ISR(TIMERx_OVF_vect) breathing_interrupt_disable(); } - set_pwm(cie_lightness(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * 0x0101U))); + set_pwm(cie_lightness(rescale_limit_val(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * 0x0101U)))); } #endif // BACKLIGHT_BREATHING diff --git a/quantum/backlight/backlight_chibios.c b/quantum/backlight/backlight_chibios.c index 0fe812bf27bc..4d5a69e14e33 100644 --- a/quantum/backlight/backlight_chibios.c +++ b/quantum/backlight/backlight_chibios.c @@ -3,6 +3,11 @@ #include #include "debug.h" +// Maximum duty cycle limit +#ifndef BACKLIGHT_LIMIT_VAL +# define BACKLIGHT_LIMIT_VAL 255 +#endif + // GPIOV2 && GPIOV3 #ifndef BACKLIGHT_PAL_MODE # define BACKLIGHT_PAL_MODE 2 @@ -58,6 +63,11 @@ static uint16_t cie_lightness(uint16_t v) { } } +static uint32_t rescale_limit_val(uint32_t val) { + // rescale the supplied backlight value to be in terms of the value limit + return (val * (BACKLIGHT_LIMIT_VAL + 1)) / 256; +} + void backlight_init_ports(void) { #ifdef USE_GPIOV1 palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); @@ -85,7 +95,7 @@ void backlight_set(uint8_t level) { pwmDisableChannel(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1); } else { // Turn backlight on - uint32_t duty = (uint32_t)(cie_lightness(0xFFFF * (uint32_t)level / BACKLIGHT_LEVELS)); + uint32_t duty = (uint32_t)(cie_lightness(rescale_limit_val(0xFFFF * (uint32_t)level / BACKLIGHT_LEVELS))); pwmEnableChannel(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, 0xFFFF, duty)); } } @@ -129,7 +139,7 @@ void breathing_callback(PWMDriver *pwmp) { static uint16_t breathing_counter = 0; breathing_counter = (breathing_counter + 1) % (breathing_period * 256); uint8_t index = breathing_counter / interval % BREATHING_STEPS; - uint32_t duty = cie_lightness(scale_backlight(breathing_table[index] * 256)); + uint32_t duty = cie_lightness(rescale_limit_val(scale_backlight(breathing_table[index] * 256))); chSysLockFromISR(); pwmEnableChannelI(pwmp, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, 0xFFFF, duty)); diff --git a/quantum/config_common.h b/quantum/config_common.h index c6a96e673c82..53377f2b61c3 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -40,7 +40,7 @@ # define PIND_ADDRESS 0x9 # define PINE_ADDRESS 0xC # define PINF_ADDRESS 0xF -# elif defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) +# elif defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) # define ADDRESS_BASE 0x00 # define PINB_ADDRESS 0x3 # define PINC_ADDRESS 0x6 @@ -59,11 +59,6 @@ # define PINC_ADDRESS 0x3 # define PINB_ADDRESS 0x6 # define PINA_ADDRESS 0x9 -# elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) -# define ADDRESS_BASE 0x00 -# define PINB_ADDRESS 0x3 -# define PINC_ADDRESS 0x6 -# define PIND_ADDRESS 0x9 # elif defined(__AVR_ATtiny85__) # define ADDRESS_BASE 0x10 # define PINB_ADDRESS 0x6 @@ -285,6 +280,91 @@ # define F13 PAL_LINE(GPIOF, 13) # define F14 PAL_LINE(GPIOF, 14) # define F15 PAL_LINE(GPIOF, 15) +# define G0 PAL_LINE(GPIOG, 0) +# define G1 PAL_LINE(GPIOG, 1) +# define G2 PAL_LINE(GPIOG, 2) +# define G3 PAL_LINE(GPIOG, 3) +# define G4 PAL_LINE(GPIOG, 4) +# define G5 PAL_LINE(GPIOG, 5) +# define G6 PAL_LINE(GPIOG, 6) +# define G7 PAL_LINE(GPIOG, 7) +# define G8 PAL_LINE(GPIOG, 8) +# define G9 PAL_LINE(GPIOG, 9) +# define G10 PAL_LINE(GPIOG, 10) +# define G11 PAL_LINE(GPIOG, 11) +# define G12 PAL_LINE(GPIOG, 12) +# define G13 PAL_LINE(GPIOG, 13) +# define G14 PAL_LINE(GPIOG, 14) +# define G15 PAL_LINE(GPIOG, 15) +# define H0 PAL_LINE(GPIOH, 0) +# define H1 PAL_LINE(GPIOH, 1) +# define H2 PAL_LINE(GPIOH, 2) +# define H3 PAL_LINE(GPIOH, 3) +# define H4 PAL_LINE(GPIOH, 4) +# define H5 PAL_LINE(GPIOH, 5) +# define H6 PAL_LINE(GPIOH, 6) +# define H7 PAL_LINE(GPIOH, 7) +# define H8 PAL_LINE(GPIOH, 8) +# define H9 PAL_LINE(GPIOH, 9) +# define H10 PAL_LINE(GPIOH, 10) +# define H11 PAL_LINE(GPIOH, 11) +# define H12 PAL_LINE(GPIOH, 12) +# define H13 PAL_LINE(GPIOH, 13) +# define H14 PAL_LINE(GPIOH, 14) +# define H15 PAL_LINE(GPIOH, 15) +# define I0 PAL_LINE(GPIOI, 0) +# define I1 PAL_LINE(GPIOI, 1) +# define I2 PAL_LINE(GPIOI, 2) +# define I3 PAL_LINE(GPIOI, 3) +# define I4 PAL_LINE(GPIOI, 4) +# define I5 PAL_LINE(GPIOI, 5) +# define I6 PAL_LINE(GPIOI, 6) +# define I7 PAL_LINE(GPIOI, 7) +# define I8 PAL_LINE(GPIOI, 8) +# define I9 PAL_LINE(GPIOI, 9) +# define I10 PAL_LINE(GPIOI, 10) +# define I11 PAL_LINE(GPIOI, 11) +# define I12 PAL_LINE(GPIOI, 12) +# define I13 PAL_LINE(GPIOI, 13) +# define I14 PAL_LINE(GPIOI, 14) +# define I15 PAL_LINE(GPIOI, 15) +# define J0 PAL_LINE(GPIOJ, 0) +# define J1 PAL_LINE(GPIOJ, 1) +# define J2 PAL_LINE(GPIOJ, 2) +# define J3 PAL_LINE(GPIOJ, 3) +# define J4 PAL_LINE(GPIOJ, 4) +# define J5 PAL_LINE(GPIOJ, 5) +# define J6 PAL_LINE(GPIOJ, 6) +# define J7 PAL_LINE(GPIOJ, 7) +# define J8 PAL_LINE(GPIOJ, 8) +# define J9 PAL_LINE(GPIOJ, 9) +# define J10 PAL_LINE(GPIOJ, 10) +# define J11 PAL_LINE(GPIOJ, 11) +# define J12 PAL_LINE(GPIOJ, 12) +# define J13 PAL_LINE(GPIOJ, 13) +# define J14 PAL_LINE(GPIOJ, 14) +# define J15 PAL_LINE(GPIOJ, 15) +// Keyboards can `#define KEYBOARD_REQUIRES_GPIOK` if they need to access GPIO-K pins. These conflict with a whole +// bunch of layout definitions, so it's intentionally left out unless absolutely required -- in that case, the +// keyboard designer should use a different symbol when defining their layout macros. +# ifdef KEYBOARD_REQUIRES_GPIOK +# define K0 PAL_LINE(GPIOK, 0) +# define K1 PAL_LINE(GPIOK, 1) +# define K2 PAL_LINE(GPIOK, 2) +# define K3 PAL_LINE(GPIOK, 3) +# define K4 PAL_LINE(GPIOK, 4) +# define K5 PAL_LINE(GPIOK, 5) +# define K6 PAL_LINE(GPIOK, 6) +# define K7 PAL_LINE(GPIOK, 7) +# define K8 PAL_LINE(GPIOK, 8) +# define K9 PAL_LINE(GPIOK, 9) +# define K10 PAL_LINE(GPIOK, 10) +# define K11 PAL_LINE(GPIOK, 11) +# define K12 PAL_LINE(GPIOK, 12) +# define K13 PAL_LINE(GPIOK, 13) +# define K14 PAL_LINE(GPIOK, 14) +# define K15 PAL_LINE(GPIOK, 15) +# endif # endif #endif diff --git a/quantum/encoder.c b/quantum/encoder.c index 81ec1bb376c8..7ca31afedc2f 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -23,7 +23,7 @@ // for memcpy #include -#ifndef ENCODER_RESOLUTION +#if !defined(ENCODER_RESOLUTIONS) && !defined(ENCODER_RESOLUTION) # define ENCODER_RESOLUTION 4 #endif @@ -34,6 +34,9 @@ #define NUMBER_OF_ENCODERS (sizeof(encoders_pad_a) / sizeof(pin_t)) static pin_t encoders_pad_a[] = ENCODERS_PAD_A; static pin_t encoders_pad_b[] = ENCODERS_PAD_B; +#ifdef ENCODER_RESOLUTIONS +static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS; +#endif #ifndef ENCODER_DIRECTION_FLIP # define ENCODER_CLOCKWISE true @@ -65,9 +68,15 @@ void encoder_init(void) { if (!isLeftHand) { const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT; const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT; +# if defined(ENCODER_RESOLUTIONS_RIGHT) + const uint8_t encoder_resolutions_right[] = ENCODER_RESOLUTIONS_RIGHT; +# endif for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { encoders_pad_a[i] = encoders_pad_a_right[i]; encoders_pad_b[i] = encoders_pad_b_right[i]; +# if defined(ENCODER_RESOLUTIONS_RIGHT) + encoder_resolutions[i] = encoder_resolutions_right[i]; +# endif } } #endif @@ -87,19 +96,26 @@ void encoder_init(void) { static void encoder_update(int8_t index, uint8_t state) { uint8_t i = index; + +#ifdef ENCODER_RESOLUTIONS + int8_t resolution = encoder_resolutions[i]; +#else + int8_t resolution = ENCODER_RESOLUTION; +#endif + #ifdef SPLIT_KEYBOARD index += thisHand; #endif encoder_pulses[i] += encoder_LUT[state & 0xF]; - if (encoder_pulses[i] >= ENCODER_RESOLUTION) { + if (encoder_pulses[i] >= resolution) { encoder_value[index]++; encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE); } - if (encoder_pulses[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise + if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise encoder_value[index]--; encoder_update_kb(index, ENCODER_CLOCKWISE); } - encoder_pulses[i] %= ENCODER_RESOLUTION; + encoder_pulses[i] %= resolution; } void encoder_read(void) { diff --git a/quantum/joystick.h b/quantum/joystick.h index a95472b9fd44..87dbc24aff81 100644 --- a/quantum/joystick.h +++ b/quantum/joystick.h @@ -1,5 +1,9 @@ #pragma once +#include "quantum.h" + +#include + #ifndef JOYSTICK_BUTTON_COUNT # define JOYSTICK_BUTTON_COUNT 8 #endif @@ -8,9 +12,13 @@ # define JOYSTICK_AXES_COUNT 4 #endif -#include "quantum.h" +#ifndef JOYSTICK_AXES_RESOLUTION +# define JOYSTICK_AXES_RESOLUTION 8 +#elif JOYSTICK_AXES_RESOLUTION < 8 || JOYSTICK_AXES_RESOLUTION > 16 +# error JOYSTICK_AXES_RESOLUTION must be between 8 and 16 +#endif -#include +#define JOYSTICK_RESOLUTION ((1L << (JOYSTICK_AXES_RESOLUTION - 1)) - 1) // configure on input_pin of the joystick_axes array entry to JS_VIRTUAL_AXIS // to prevent it from being read from the ADC. This allows outputing forged axis value. diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c index 5c24c797a91f..eb523990a6c1 100644 --- a/quantum/led_matrix.c +++ b/quantum/led_matrix.c @@ -20,7 +20,7 @@ #include #include #include "quantum.h" -#include "ledmatrix.h" +#include "led_matrix.h" #include "progmem.h" #include "config.h" #include "eeprom.h" diff --git a/quantum/ledmatrix.h b/quantum/led_matrix.h similarity index 100% rename from quantum/ledmatrix.h rename to quantum/led_matrix.h diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix_drivers.c index 6877bf4c6bbb..9decaa33c2f2 100644 --- a/quantum/led_matrix_drivers.c +++ b/quantum/led_matrix_drivers.c @@ -18,7 +18,7 @@ #include #include #include "quantum.h" -#include "ledmatrix.h" +#include "led_matrix.h" /* Each driver needs to define a struct: * diff --git a/quantum/matrix.c b/quantum/matrix.c index c68c56cac204..cab0d2ddcafa 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -32,6 +32,19 @@ static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values +static inline void setPinOutput_writeLow(pin_t pin) { + ATOMIC_BLOCK_FORCEON { + setPinOutput(pin); + writePinLow(pin); + } +} + +static inline void setPinInputHigh_atomic(pin_t pin) { + ATOMIC_BLOCK_FORCEON { + setPinInputHigh(pin); + } +} + // matrix code #ifdef DIRECT_PINS @@ -70,22 +83,23 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) # if (DIODE_DIRECTION == COL2ROW) static void select_row(uint8_t row) { - setPinOutput(row_pins[row]); - writePinLow(row_pins[row]); + setPinOutput_writeLow(row_pins[row]); } -static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); } +static void unselect_row(uint8_t row) { + setPinInputHigh_atomic(row_pins[row]); +} static void unselect_rows(void) { for (uint8_t x = 0; x < MATRIX_ROWS; x++) { - setPinInputHigh(row_pins[x]); + setPinInputHigh_atomic(row_pins[x]); } } static void init_pins(void) { unselect_rows(); for (uint8_t x = 0; x < MATRIX_COLS; x++) { - setPinInputHigh(col_pins[x]); + setPinInputHigh_atomic(col_pins[x]); } } @@ -120,22 +134,23 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) # elif (DIODE_DIRECTION == ROW2COL) static void select_col(uint8_t col) { - setPinOutput(col_pins[col]); - writePinLow(col_pins[col]); + setPinOutput_writeLow(col_pins[col]); } -static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); } +static void unselect_col(uint8_t col) { + setPinInputHigh_atomic(col_pins[col]); +} static void unselect_cols(void) { for (uint8_t x = 0; x < MATRIX_COLS; x++) { - setPinInputHigh(col_pins[x]); + setPinInputHigh_atomic(col_pins[x]); } } static void init_pins(void) { unselect_cols(); for (uint8_t x = 0; x < MATRIX_ROWS; x++) { - setPinInputHigh(row_pins[x]); + setPinInputHigh_atomic(row_pins[x]); } } diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index 6fb5f88b0505..ea88d9ab9e4d 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -318,6 +318,9 @@ ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 a ifeq (,$(filter $(NO_INTERRUPT_CONTROL_ENDPOINT),yes)) OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT endif + ifneq (,$(filter $(MCU),atmega16u2 atmega32u2)) + NO_I2C = yes + endif endif ifneq (,$(filter $(MCU),atmega32a)) diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c index 76530959c9cb..41e60496b9a1 100644 --- a/quantum/process_keycode/process_auto_shift.c +++ b/quantum/process_keycode/process_auto_shift.c @@ -16,49 +16,149 @@ #ifdef AUTO_SHIFT_ENABLE +# include # include # include "process_auto_shift.h" -static bool autoshift_enabled = true; -static uint16_t autoshift_time = 0; +static uint16_t autoshift_time = 0; static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; static uint16_t autoshift_lastkey = KC_NO; +static struct { + // Whether autoshift is enabled. + bool enabled : 1; + // Whether the last auto-shifted key was released after the timeout. This + // is used to replicate the last key for a tap-then-hold. + bool lastshifted : 1; + // Whether an auto-shiftable key has been pressed but not processed. + bool in_progress : 1; + // Whether the auto-shifted keypress has been registered. + bool holding_shift : 1; +} autoshift_flags = {true, false, false, false}; + +/** \brief Record the press of an autoshiftable key + * + * \return Whether the record should be further processed. + */ +static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) { + if (!autoshift_flags.enabled) { + return true; + } -void autoshift_flush(void) { - if (autoshift_lastkey != KC_NO) { - uint16_t elapsed = timer_elapsed(autoshift_time); +# ifndef AUTO_SHIFT_MODIFIERS + if (get_mods() & (~MOD_BIT(KC_LSFT))) { + return true; + } +# endif +# ifdef AUTO_SHIFT_REPEAT + const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time); +# ifndef AUTO_SHIFT_NO_AUTO_REPEAT + if (!autoshift_flags.lastshifted) { +# endif + if (elapsed < TAPPING_TERM && keycode == autoshift_lastkey) { + // Allow a tap-then-hold for keyrepeat. + if (!autoshift_flags.lastshifted) { + register_code(autoshift_lastkey); + } else { + // Simulate pressing the shift key. + add_weak_mods(MOD_BIT(KC_LSFT)); + register_code(autoshift_lastkey); + } + return false; + } +# ifndef AUTO_SHIFT_NO_AUTO_REPEAT + } +# endif +# endif + + // Record the keycode so we can simulate it later. + autoshift_lastkey = keycode; + autoshift_time = now; + autoshift_flags.in_progress = true; - if (elapsed > autoshift_timeout) { - tap_code16(LSFT(autoshift_lastkey)); +# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); +# endif + return false; +} + +/** \brief Registers an autoshiftable key under the right conditions + * + * If the autoshift delay has elapsed, register a shift and the key. + * + * If the autoshift key is released before the delay has elapsed, register the + * key without a shift. + */ +static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) { + // Called on key down with KC_NO, auto-shifted key up, and timeout. + if (autoshift_flags.in_progress) { + // Process the auto-shiftable key. + autoshift_flags.in_progress = false; + + // Time since the initial press was recorded. + const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time); + if (elapsed < autoshift_timeout) { + register_code(autoshift_lastkey); + autoshift_flags.lastshifted = false; } else { - tap_code(autoshift_lastkey); + // Simulate pressing the shift key. + add_weak_mods(MOD_BIT(KC_LSFT)); + register_code(autoshift_lastkey); + autoshift_flags.lastshifted = true; +# if defined(AUTO_SHIFT_REPEAT) && !defined(AUTO_SHIFT_NO_AUTO_REPEAT) + if (matrix_trigger) { + // Prevents release. + return; + } +# endif } - autoshift_time = 0; - autoshift_lastkey = KC_NO; +# if TAP_CODE_DELAY > 0 + wait_ms(TAP_CODE_DELAY); +# endif + unregister_code(autoshift_lastkey); + del_weak_mods(MOD_BIT(KC_LSFT)); + } else { + // Release after keyrepeat. + unregister_code(keycode); + if (keycode == autoshift_lastkey) { + // This will only fire when the key was the last auto-shiftable + // pressed. That prevents aaaaBBBB then releasing a from unshifting + // later Bs (if B wasn't auto-shiftable). + del_weak_mods(MOD_BIT(KC_LSFT)); + } } + send_keyboard_report(); // del_weak_mods doesn't send one. + // Roll the autoshift_time forward for detecting tap-and-hold. + autoshift_time = now; } - -void autoshift_on(uint16_t keycode) { - autoshift_time = timer_read(); - autoshift_lastkey = keycode; +/** \brief Simulates auto-shifted key releases when timeout is hit + * + * Can be called from \c matrix_scan_user so that auto-shifted keys are sent + * immediately after the timeout has expired, rather than waiting for the key + * to be released. + */ +void autoshift_matrix_scan(void) { + if (autoshift_flags.in_progress) { + const uint16_t now = timer_read(); + const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time); + if (elapsed >= autoshift_timeout) { + autoshift_end(autoshift_lastkey, now, true); + } + } } void autoshift_toggle(void) { - if (autoshift_enabled) { - autoshift_enabled = false; - autoshift_flush(); - } else { - autoshift_enabled = true; - } + autoshift_flags.enabled = !autoshift_flags.enabled; + del_weak_mods(MOD_BIT(KC_LSFT)); } -void autoshift_enable(void) { autoshift_enabled = true; } +void autoshift_enable(void) { autoshift_flags.enabled = true; } + void autoshift_disable(void) { - autoshift_enabled = false; - autoshift_flush(); + autoshift_flags.enabled = false; + del_weak_mods(MOD_BIT(KC_LSFT)); } # ifndef AUTO_SHIFT_NO_SETUP @@ -71,24 +171,30 @@ void autoshift_timer_report(void) { } # endif -bool get_autoshift_state(void) { return autoshift_enabled; } +bool get_autoshift_state(void) { return autoshift_flags.enabled; } -uint16_t get_autoshift_timeout(void) { - return autoshift_timeout; -} +uint16_t get_autoshift_timeout(void) { return autoshift_timeout; } -void set_autoshift_timeout(uint16_t timeout) { - autoshift_timeout = timeout; -} +void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; } bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { + // Note that record->event.time isn't reliable, see: + // https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550 + const uint16_t now = timer_read(); if (record->event.pressed) { + if (autoshift_flags.in_progress) { + // Evaluate previous key if there is one. Doing this elsewhere is + // more complicated and easier to break. + autoshift_end(KC_NO, now, false); + } + // For pressing another key while keyrepeating shifted autoshift. + del_weak_mods(MOD_BIT(KC_LSFT)); + switch (keycode) { case KC_ASTG: autoshift_toggle(); return true; - case KC_ASON: autoshift_enable(); return true; @@ -108,43 +214,30 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { autoshift_timer_report(); return true; # endif + } + } + + switch (keycode) { # ifndef NO_AUTO_SHIFT_ALPHA - case KC_A ... KC_Z: + case KC_A ... KC_Z: # endif # ifndef NO_AUTO_SHIFT_NUMERIC - case KC_1 ... KC_0: + case KC_1 ... KC_0: # endif # ifndef NO_AUTO_SHIFT_SPECIAL -# ifndef NO_AUTO_SHIFT_TAB - case KC_TAB: -# endif - case KC_MINUS ... KC_SLASH: - case KC_NONUS_BSLASH: -# endif - autoshift_flush(); - if (!autoshift_enabled) return true; - -# ifndef AUTO_SHIFT_MODIFIERS - if (get_mods()) { - return true; - } -# endif - autoshift_on(keycode); - - // We need some extra handling here for OSL edge cases -# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); +# ifndef NO_AUTO_SHIFT_TAB + case KC_TAB: +# endif + 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; - - default: - autoshift_flush(); - return true; - } - } else { - autoshift_flush(); + } } - return true; } diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h index b909d28eef13..5b2718f11ca6 100644 --- a/quantum/process_keycode/process_auto_shift.h +++ b/quantum/process_keycode/process_auto_shift.h @@ -24,9 +24,10 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record); -void autoshift_enable(void); -void autoshift_disable(void); -void autoshift_toggle(void); -bool get_autoshift_state(void); +void autoshift_enable(void); +void autoshift_disable(void); +void autoshift_toggle(void); +bool get_autoshift_state(void); uint16_t get_autoshift_timeout(void); -void set_autoshift_timeout(uint16_t timeout); +void set_autoshift_timeout(uint16_t timeout); +void autoshift_matrix_scan(void); diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c index 5778a7434c1c..3ffaf42bf847 100644 --- a/quantum/process_keycode/process_joystick.c +++ b/quantum/process_keycode/process_joystick.c @@ -129,17 +129,17 @@ bool process_joystick_analogread_quantum() { // test the converted value against the lower range int32_t ref = joystick_axes[axis_index].mid_digit; int32_t range = joystick_axes[axis_index].min_digit; - int32_t ranged_val = ((axis_val - ref) * -127) / (range - ref); + int32_t ranged_val = ((axis_val - ref) * -JOYSTICK_RESOLUTION) / (range - ref); if (ranged_val > 0) { // the value is in the higher range range = joystick_axes[axis_index].max_digit; - ranged_val = ((axis_val - ref) * 127) / (range - ref); + ranged_val = ((axis_val - ref) * JOYSTICK_RESOLUTION) / (range - ref); } // clamp the result in the valid range - ranged_val = ranged_val < -127 ? -127 : ranged_val; - ranged_val = ranged_val > 127 ? 127 : ranged_val; + ranged_val = ranged_val < -JOYSTICK_RESOLUTION ? -JOYSTICK_RESOLUTION : ranged_val; + ranged_val = ranged_val > JOYSTICK_RESOLUTION ? JOYSTICK_RESOLUTION : ranged_val; if (ranged_val != joystick_status.axes[axis_index]) { joystick_status.axes[axis_index] = ranged_val; diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index e52577014432..8e2fb955e7e3 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -41,12 +41,12 @@ static int8_t midi_modulation_step; static uint16_t midi_modulation_timer; midi_config_t midi_config; -inline uint8_t compute_velocity(uint8_t setting) { return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1)); } +inline uint8_t compute_velocity(uint8_t setting) { return setting * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN)); } void midi_init(void) { midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN; midi_config.transpose = 0; - midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN); + midi_config.velocity = 127; midi_config.channel = 0; midi_config.modulation_interval = 8; @@ -66,7 +66,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) { case MIDI_TONE_MIN ... MIDI_TONE_MAX: { uint8_t channel = midi_config.channel; uint8_t tone = keycode - MIDI_TONE_MIN; - uint8_t velocity = compute_velocity(midi_config.velocity); + uint8_t velocity = midi_config.velocity; if (record->event.pressed) { if (tone_status[tone] == MIDI_INVALID_NOTE) { uint8_t note = midi_compute_note(keycode); @@ -124,19 +124,30 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) { return false; case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX: if (record->event.pressed) { - midi_config.velocity = keycode - MIDI_VELOCITY_MIN; + midi_config.velocity = compute_velocity(keycode - MIDI_VELOCITY_MIN); dprintf("midi velocity %d\n", midi_config.velocity); } return false; case MI_VELD: if (record->event.pressed && midi_config.velocity > 0) { - midi_config.velocity--; + if (midi_config.velocity == 127) { + midi_config.velocity -= 10; + } else if (midi_config.velocity > 12) { + midi_config.velocity -= 13; + } else { + midi_config.velocity = 0; + } + dprintf("midi velocity %d\n", midi_config.velocity); } return false; case MI_VELU: - if (record->event.pressed) { - midi_config.velocity++; + if (record->event.pressed && midi_config.velocity < 127) { + if (midi_config.velocity < 115) { + midi_config.velocity += 13; + } else { + midi_config.velocity = 127; + } dprintf("midi velocity %d\n", midi_config.velocity); } return false; diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h index 0007b3ed255a..ef5661dd4d1c 100644 --- a/quantum/process_keycode/process_midi.h +++ b/quantum/process_keycode/process_midi.h @@ -35,7 +35,7 @@ typedef union { struct { uint8_t octave : 4; int8_t transpose : 4; - uint8_t velocity : 4; + uint8_t velocity : 7; uint8_t channel : 4; uint8_t modulation_interval : 4; }; diff --git a/quantum/process_keycode/process_sequencer.c b/quantum/process_keycode/process_sequencer.c new file mode 100644 index 000000000000..334b4c00923f --- /dev/null +++ b/quantum/process_keycode/process_sequencer.c @@ -0,0 +1,62 @@ +/* Copyright 2020 Rodolphe Belouin + * + * 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 . + */ + +#include "process_sequencer.h" + +bool process_sequencer(uint16_t keycode, keyrecord_t *record) { + if (record->event.pressed) { + switch (keycode) { + case SQ_ON: + sequencer_on(); + return false; + case SQ_OFF: + sequencer_off(); + return false; + case SQ_TOG: + sequencer_toggle(); + return false; + case SQ_TMPD: + sequencer_decrease_tempo(); + return false; + case SQ_TMPU: + sequencer_increase_tempo(); + return false; + case SEQUENCER_RESOLUTION_MIN ... SEQUENCER_RESOLUTION_MAX: + sequencer_set_resolution(keycode - SEQUENCER_RESOLUTION_MIN); + return false; + case SQ_RESD: + sequencer_decrease_resolution(); + return false; + case SQ_RESU: + sequencer_increase_resolution(); + return false; + case SQ_SALL: + sequencer_set_all_steps_on(); + return false; + case SQ_SCLR: + sequencer_set_all_steps_off(); + return false; + case SEQUENCER_STEP_MIN ... SEQUENCER_STEP_MAX: + sequencer_toggle_step(keycode - SEQUENCER_STEP_MIN); + return false; + case SEQUENCER_TRACK_MIN ... SEQUENCER_TRACK_MAX: + sequencer_toggle_single_active_track(keycode - SEQUENCER_TRACK_MIN); + return false; + } + } + + return true; +} diff --git a/quantum/process_keycode/process_sequencer.h b/quantum/process_keycode/process_sequencer.h new file mode 100644 index 000000000000..2b85f24299ed --- /dev/null +++ b/quantum/process_keycode/process_sequencer.h @@ -0,0 +1,21 @@ +/* Copyright 2020 Rodolphe Belouin + * + * 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 . + */ + +#pragma once + +#include "quantum.h" + +bool process_sequencer(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/quantum.c b/quantum/quantum.c index 4f21e6eea9d4..0af3f62c4d1d 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -55,6 +55,10 @@ float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS; # endif #endif +#ifdef AUTO_SHIFT_ENABLE +# include "process_auto_shift.h" +#endif + static void do_code16(uint16_t code, void (*f)(uint8_t)) { switch (code) { case QK_MODS ... QK_MODS_MAX: @@ -228,6 +232,9 @@ bool process_record_quantum(keyrecord_t *record) { process_record_via(keycode, record) && #endif process_record_kb(keycode, record) && +#if defined(SEQUENCER_ENABLE) + process_sequencer(keycode, record) && +#endif #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) process_midi(keycode, record) && #endif @@ -649,6 +656,10 @@ void matrix_scan_quantum() { matrix_scan_music(); #endif +#ifdef SEQUENCER_ENABLE + matrix_scan_sequencer(); +#endif + #ifdef TAP_DANCE_ENABLE matrix_scan_tap_dance(); #endif @@ -677,6 +688,10 @@ void matrix_scan_quantum() { dip_switch_read(false); #endif +#ifdef AUTO_SHIFT_ENABLE + autoshift_matrix_scan(); +#endif + matrix_scan_kb(); } diff --git a/quantum/quantum.h b/quantum/quantum.h index 2c0657865294..94188a85432c 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -31,7 +31,7 @@ #ifdef BACKLIGHT_ENABLE # ifdef LED_MATRIX_ENABLE -# include "ledmatrix.h" +# include "led_matrix.h" # else # include "backlight.h" # endif @@ -68,6 +68,11 @@ extern layer_state_t default_layer_state; extern layer_state_t layer_state; #endif +#if defined(SEQUENCER_ENABLE) +# include "sequencer.h" +# include "process_sequencer.h" +#endif + #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) # include "process_midi.h" #endif @@ -229,6 +234,61 @@ typedef ioline_t pin_t; # define togglePin(pin) palToggleLine(pin) #endif +// Atomic macro to help make GPIO and other controls atomic. +#ifdef IGNORE_ATOMIC_BLOCK +/* do nothing atomic macro */ +# define ATOMIC_BLOCK for (uint8_t __ToDo = 1; __ToDo; __ToDo = 0) +# define ATOMIC_BLOCK_RESTORESTATE ATOMIC_BLOCK +# define ATOMIC_BLOCK_FORCEON ATOMIC_BLOCK + +#elif defined(__AVR__) +/* atomic macro for AVR */ +# include + +# define ATOMIC_BLOCK_RESTORESTATE ATOMIC_BLOCK(ATOMIC_RESTORESTATE) +# define ATOMIC_BLOCK_FORCEON ATOMIC_BLOCK(ATOMIC_FORCEON) + +#elif defined(PROTOCOL_CHIBIOS) || defined(PROTOCOL_ARM_ATSAM) +/* atomic macro for ChibiOS / ARM ATSAM */ +# if defined(PROTOCOL_ARM_ATSAM) +# include "arm_atsam_protocol.h" +# endif + +static __inline__ uint8_t __interrupt_disable__(void) { +# if defined(PROTOCOL_CHIBIOS) + chSysLock(); +# endif +# if defined(PROTOCOL_ARM_ATSAM) + __disable_irq(); +# endif + return 1; +} + +static __inline__ void __interrupt_enable__(const uint8_t *__s) { +# if defined(PROTOCOL_CHIBIOS) + chSysUnlock(); +# endif +# if defined(PROTOCOL_ARM_ATSAM) + __enable_irq(); +# endif + __asm__ volatile("" ::: "memory"); + (void)__s; +} + +# define ATOMIC_BLOCK(type) for (type, __ToDo = __interrupt_disable__(); __ToDo; __ToDo = 0) +# define ATOMIC_FORCEON uint8_t sreg_save __attribute__((__cleanup__(__interrupt_enable__))) = 0 + +# define ATOMIC_BLOCK_RESTORESTATE _Static_assert(0, "ATOMIC_BLOCK_RESTORESTATE dose not implement") +# define ATOMIC_BLOCK_FORCEON ATOMIC_BLOCK(ATOMIC_FORCEON) + +/* Other platform */ +#else + +# define ATOMIC_BLOCK_RESTORESTATE _Static_assert(0, "ATOMIC_BLOCK_RESTORESTATE dose not implement") +# define ATOMIC_BLOCK_FORCEON _Static_assert(0, "ATOMIC_BLOCK_FORCEON dose not implement") + +#endif + #define SEND_STRING(string) send_string_P(PSTR(string)) #define SEND_STRING_DELAY(string, interval) send_string_with_delay_P(PSTR(string), interval) diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 38618964e32e..34102aab2d53 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -16,6 +16,10 @@ #ifndef QUANTUM_KEYCODES_H #define QUANTUM_KEYCODES_H +#if defined(SEQUENCER_ENABLE) +# include "sequencer.h" +#endif + #ifndef MIDI_ENABLE_STRICT # define MIDI_ENABLE_STRICT 0 #endif @@ -343,7 +347,8 @@ enum quantum_keycodes { MI_TRNSU, // transpose up MIDI_VELOCITY_MIN, - MI_VEL_1 = MIDI_VELOCITY_MIN, + MI_VEL_0 = MIDI_VELOCITY_MIN, + MI_VEL_1, MI_VEL_2, MI_VEL_3, MI_VEL_4, @@ -551,6 +556,37 @@ enum quantum_keycodes { 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 + + 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) + +#endif + // always leave at the end SAFE_RANGE }; diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index 2a55a8926f72..404e5bc1f9ad 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -31,6 +31,8 @@ const point_t k_rgb_matrix_center = {112, 32}; const 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); } + // Generic effect runners #include "rgb_matrix_runners/effect_runner_dx_dy_dist.h" #include "rgb_matrix_runners/effect_runner_dx_dy.h" @@ -402,6 +404,10 @@ void rgb_matrix_task(void) { break; case RENDERING: rgb_task_render(effect); + if (!suspend_backlight) { + rgb_matrix_indicators(); + rgb_matrix_indicators_advanced(&rgb_effect_params); + } break; case FLUSHING: rgb_task_flush(effect); @@ -410,10 +416,6 @@ void rgb_matrix_task(void) { rgb_task_sync(); break; } - - if (!suspend_backlight) { - rgb_matrix_indicators(); - } } void rgb_matrix_indicators(void) { @@ -425,6 +427,28 @@ __attribute__((weak)) void rgb_matrix_indicators_kb(void) {} __attribute__((weak)) void rgb_matrix_indicators_user(void) {} +void rgb_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 rgb_task_render, but then it's missing a few checks + * and not sure which would be better. Otherwise, this should be called from + * rgb_task_render, right before the iter++ line. + */ +#if defined(RGB_MATRIX_LED_PROCESS_LIMIT) && RGB_MATRIX_LED_PROCESS_LIMIT > 0 && RGB_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL + uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * (params->iter - 1); + uint8_t max = min + RGB_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 + rgb_matrix_indicators_advanced_kb(min, max); + rgb_matrix_indicators_advanced_user(min, max); +} + +__attribute__((weak)) void rgb_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max) {} + +__attribute__((weak)) void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {} + void rgb_matrix_init(void) { rgb_matrix_driver.init(); diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h index 733333349faa..771a1fcd35f6 100644 --- a/quantum/rgb_matrix.h +++ b/quantum/rgb_matrix.h @@ -57,6 +57,11 @@ uint8_t max = DRIVER_LED_TOTAL; #endif +#define RGB_MATRIX_INDICATOR_SET_COLOR(i, r, g, b) \ + if (i >= led_min && i <= led_max) { \ + rgb_matrix_set_color(i, r, g, b); \ + } + #define RGB_MATRIX_TEST_LED_FLAGS() \ if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) continue @@ -103,6 +108,10 @@ void rgb_matrix_indicators(void); void rgb_matrix_indicators_kb(void); void rgb_matrix_indicators_user(void); +void rgb_matrix_indicators_advanced(effect_params_t *params); +void rgb_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max); +void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max); + void rgb_matrix_init(void); void rgb_matrix_set_suspend_state(bool state); diff --git a/quantum/rgb_matrix_animations/alpha_mods_anim.h b/quantum/rgb_matrix_animations/alpha_mods_anim.h index 0778ab2098f4..426d88ef3569 100644 --- a/quantum/rgb_matrix_animations/alpha_mods_anim.h +++ b/quantum/rgb_matrix_animations/alpha_mods_anim.h @@ -7,9 +7,9 @@ bool ALPHAS_MODS(effect_params_t* params) { RGB_MATRIX_USE_LIMITS(led_min, led_max); HSV hsv = rgb_matrix_config.hsv; - RGB rgb1 = hsv_to_rgb(hsv); + RGB rgb1 = rgb_matrix_hsv_to_rgb(hsv); hsv.h += rgb_matrix_config.speed; - RGB rgb2 = hsv_to_rgb(hsv); + RGB rgb2 = rgb_matrix_hsv_to_rgb(hsv); for (uint8_t i = led_min; i < led_max; i++) { RGB_MATRIX_TEST_LED_FLAGS(); diff --git a/quantum/rgb_matrix_animations/breathing_anim.h b/quantum/rgb_matrix_animations/breathing_anim.h index 887425f9dafc..340bd93e5dd0 100644 --- a/quantum/rgb_matrix_animations/breathing_anim.h +++ b/quantum/rgb_matrix_animations/breathing_anim.h @@ -8,7 +8,7 @@ bool BREATHING(effect_params_t* params) { HSV hsv = rgb_matrix_config.hsv; uint16_t time = scale16by8(g_rgb_timer, rgb_matrix_config.speed / 8); hsv.v = scale8(abs8(sin8(time) - 128) * 2, hsv.v); - RGB rgb = hsv_to_rgb(hsv); + RGB rgb = rgb_matrix_hsv_to_rgb(hsv); for (uint8_t i = led_min; i < led_max; i++) { RGB_MATRIX_TEST_LED_FLAGS(); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); diff --git a/quantum/rgb_matrix_animations/gradient_left_right_anim.h b/quantum/rgb_matrix_animations/gradient_left_right_anim.h index 2eab2eb7594f..53dfd04e2c85 100644 --- a/quantum/rgb_matrix_animations/gradient_left_right_anim.h +++ b/quantum/rgb_matrix_animations/gradient_left_right_anim.h @@ -12,7 +12,7 @@ bool GRADIENT_LEFT_RIGHT(effect_params_t* params) { // The x range will be 0..224, map this to 0..7 // Relies on hue being 8-bit and wrapping hsv.h = rgb_matrix_config.hsv.h + (scale * g_led_config.point[i].x >> 5); - RGB rgb = hsv_to_rgb(hsv); + RGB rgb = rgb_matrix_hsv_to_rgb(hsv); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } return led_max < DRIVER_LED_TOTAL; diff --git a/quantum/rgb_matrix_animations/gradient_up_down_anim.h b/quantum/rgb_matrix_animations/gradient_up_down_anim.h index 0f1f8e23cf22..7e0d2898cf7b 100644 --- a/quantum/rgb_matrix_animations/gradient_up_down_anim.h +++ b/quantum/rgb_matrix_animations/gradient_up_down_anim.h @@ -12,7 +12,7 @@ bool GRADIENT_UP_DOWN(effect_params_t* params) { // The y range will be 0..64, map this to 0..4 // Relies on hue being 8-bit and wrapping hsv.h = rgb_matrix_config.hsv.h + scale * (g_led_config.point[i].y >> 4); - RGB rgb = hsv_to_rgb(hsv); + RGB rgb = rgb_matrix_hsv_to_rgb(hsv); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } return led_max < DRIVER_LED_TOTAL; diff --git a/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h b/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h index ef2d1500b06f..9493b3850815 100644 --- a/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h +++ b/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h @@ -5,7 +5,7 @@ RGB_MATRIX_EFFECT(JELLYBEAN_RAINDROPS) static void jellybean_raindrops_set_color(int i, effect_params_t* params) { if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) return; HSV hsv = {rand() & 0xFF, rand() & 0xFF, rgb_matrix_config.hsv.v}; - RGB rgb = hsv_to_rgb(hsv); + RGB rgb = rgb_matrix_hsv_to_rgb(hsv); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } diff --git a/quantum/rgb_matrix_animations/raindrops_anim.h b/quantum/rgb_matrix_animations/raindrops_anim.h index 6e1b5acb0d49..38359cdca78b 100644 --- a/quantum/rgb_matrix_animations/raindrops_anim.h +++ b/quantum/rgb_matrix_animations/raindrops_anim.h @@ -15,7 +15,7 @@ static void raindrops_set_color(int i, effect_params_t* params) { } hsv.h = rgb_matrix_config.hsv.h + (deltaH * (rand() & 0x03)); - RGB rgb = hsv_to_rgb(hsv); + RGB rgb = rgb_matrix_hsv_to_rgb(hsv); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } diff --git a/quantum/rgb_matrix_animations/solid_color_anim.h b/quantum/rgb_matrix_animations/solid_color_anim.h index c8f5e70e7a64..79d63cf133b8 100644 --- a/quantum/rgb_matrix_animations/solid_color_anim.h +++ b/quantum/rgb_matrix_animations/solid_color_anim.h @@ -4,7 +4,7 @@ RGB_MATRIX_EFFECT(SOLID_COLOR) bool SOLID_COLOR(effect_params_t* params) { RGB_MATRIX_USE_LIMITS(led_min, led_max); - RGB rgb = hsv_to_rgb(rgb_matrix_config.hsv); + RGB rgb = rgb_matrix_hsv_to_rgb(rgb_matrix_config.hsv); for (uint8_t i = led_min; i < led_max; i++) { RGB_MATRIX_TEST_LED_FLAGS(); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); diff --git a/quantum/rgb_matrix_animations/typing_heatmap_anim.h b/quantum/rgb_matrix_animations/typing_heatmap_anim.h index e82c1b49eeb9..b855fdc1907b 100644 --- a/quantum/rgb_matrix_animations/typing_heatmap_anim.h +++ b/quantum/rgb_matrix_animations/typing_heatmap_anim.h @@ -51,7 +51,7 @@ bool TYPING_HEATMAP(effect_params_t* params) { if (!HAS_ANY_FLAGS(g_led_config.flags[led[j]], params->flags)) continue; HSV hsv = {170 - qsub8(val, 85), rgb_matrix_config.hsv.s, scale8((qadd8(170, val) - 170) * 3, rgb_matrix_config.hsv.v)}; - RGB rgb = hsv_to_rgb(hsv); + RGB rgb = rgb_matrix_hsv_to_rgb(hsv); rgb_matrix_set_color(led[j], rgb.r, rgb.g, rgb.b); } diff --git a/quantum/rgb_matrix_runners/effect_runner_dx_dy.h b/quantum/rgb_matrix_runners/effect_runner_dx_dy.h index 9d0c9fab194a..4867609c81f9 100644 --- a/quantum/rgb_matrix_runners/effect_runner_dx_dy.h +++ b/quantum/rgb_matrix_runners/effect_runner_dx_dy.h @@ -10,7 +10,7 @@ bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) { RGB_MATRIX_TEST_LED_FLAGS(); int16_t dx = g_led_config.point[i].x - k_rgb_matrix_center.x; int16_t dy = g_led_config.point[i].y - k_rgb_matrix_center.y; - RGB rgb = hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, time)); + RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, time)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } return led_max < DRIVER_LED_TOTAL; diff --git a/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h index 2824c82527bf..9545b418d93b 100644 --- a/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h +++ b/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h @@ -11,7 +11,7 @@ bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func) int16_t dx = g_led_config.point[i].x - k_rgb_matrix_center.x; int16_t dy = g_led_config.point[i].y - k_rgb_matrix_center.y; uint8_t dist = sqrt16(dx * dx + dy * dy); - RGB rgb = hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, dist, time)); + RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, dist, time)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } return led_max < DRIVER_LED_TOTAL; diff --git a/quantum/rgb_matrix_runners/effect_runner_i.h b/quantum/rgb_matrix_runners/effect_runner_i.h index 5e6bf5daaf32..95bfe8b390a7 100644 --- a/quantum/rgb_matrix_runners/effect_runner_i.h +++ b/quantum/rgb_matrix_runners/effect_runner_i.h @@ -8,7 +8,7 @@ bool effect_runner_i(effect_params_t* params, i_f effect_func) { uint8_t time = scale16by8(g_rgb_timer, rgb_matrix_config.speed / 4); for (uint8_t i = led_min; i < led_max; i++) { RGB_MATRIX_TEST_LED_FLAGS(); - RGB rgb = hsv_to_rgb(effect_func(rgb_matrix_config.hsv, i, time)); + RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, i, time)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } return led_max < DRIVER_LED_TOTAL; diff --git a/quantum/rgb_matrix_runners/effect_runner_reactive.h b/quantum/rgb_matrix_runners/effect_runner_reactive.h index 53e77e3fb262..8485b61f3d57 100644 --- a/quantum/rgb_matrix_runners/effect_runner_reactive.h +++ b/quantum/rgb_matrix_runners/effect_runner_reactive.h @@ -20,7 +20,7 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) { } uint16_t offset = scale16by8(tick, rgb_matrix_config.speed); - RGB rgb = hsv_to_rgb(effect_func(rgb_matrix_config.hsv, offset)); + RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, offset)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } return led_max < DRIVER_LED_TOTAL; diff --git a/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h b/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h index b5d284a40fb4..5c69d0fbb9ee 100644 --- a/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h +++ b/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h @@ -20,7 +20,7 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react hsv = effect_func(hsv, dx, dy, dist, tick); } hsv.v = scale8(hsv.v, rgb_matrix_config.hsv.v); - RGB rgb = hsv_to_rgb(hsv); + RGB rgb = rgb_matrix_hsv_to_rgb(hsv); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } return led_max < DRIVER_LED_TOTAL; diff --git a/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h b/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h index 3fb7d4805176..02351de51e2e 100644 --- a/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h +++ b/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h @@ -10,7 +10,7 @@ bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) { int8_t sin_value = sin8(time) - 128; for (uint8_t i = led_min; i < led_max; i++) { RGB_MATRIX_TEST_LED_FLAGS(); - RGB rgb = hsv_to_rgb(effect_func(rgb_matrix_config.hsv, cos_value, sin_value, i, time)); + RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, cos_value, sin_value, i, time)); rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); } return led_max < DRIVER_LED_TOTAL; diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 5ed3e8ac5f76..4aa5cb4ac914 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -123,9 +123,11 @@ void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds) { rgblight_ranges.effect_num_leds = num_leds; } +__attribute__((weak)) RGB rgblight_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } + void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) { HSV hsv = {hue, sat, val}; - RGB rgb = hsv_to_rgb(hsv); + RGB rgb = rgblight_hsv_to_rgb(hsv); setrgb(rgb.r, rgb.g, rgb.b, led1); } diff --git a/quantum/sequencer/sequencer.c b/quantum/sequencer/sequencer.c new file mode 100644 index 000000000000..0eaf3a17aa18 --- /dev/null +++ b/quantum/sequencer/sequencer.c @@ -0,0 +1,275 @@ +/* Copyright 2020 Rodolphe Belouin + * + * 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 . + */ + +#include "sequencer.h" + +#ifdef MIDI_ENABLE +# include "process_midi.h" +#endif + +#ifdef MIDI_MOCKED +# include "tests/midi_mock.h" +#endif + +sequencer_config_t sequencer_config = { + false, // enabled + {false}, // steps + {0}, // track notes + 60, // tempo + SQ_RES_4, // resolution +}; + +sequencer_state_t sequencer_internal_state = {0, 0, 0, 0, SEQUENCER_PHASE_ATTACK}; + +bool is_sequencer_on(void) { return sequencer_config.enabled; } + +void sequencer_on(void) { + dprintln("sequencer on"); + sequencer_config.enabled = true; + sequencer_internal_state.current_track = 0; + sequencer_internal_state.current_step = 0; + sequencer_internal_state.timer = timer_read(); + sequencer_internal_state.phase = SEQUENCER_PHASE_ATTACK; +} + +void sequencer_off(void) { + dprintln("sequencer off"); + sequencer_config.enabled = false; + sequencer_internal_state.current_step = 0; +} + +void sequencer_toggle(void) { + if (is_sequencer_on()) { + sequencer_off(); + } else { + sequencer_on(); + } +} + +void sequencer_set_track_notes(const uint16_t track_notes[SEQUENCER_TRACKS]) { + for (uint8_t i = 0; i < SEQUENCER_TRACKS; i++) { + sequencer_config.track_notes[i] = track_notes[i]; + } +} + +bool is_sequencer_track_active(uint8_t track) { return (sequencer_internal_state.active_tracks >> track) & true; } + +void sequencer_set_track_activation(uint8_t track, bool value) { + if (value) { + sequencer_internal_state.active_tracks |= (1 << track); + } else { + sequencer_internal_state.active_tracks &= ~(1 << track); + } + dprintf("sequencer: track %d is %s\n", track, value ? "active" : "inactive"); +} + +void sequencer_toggle_track_activation(uint8_t track) { sequencer_set_track_activation(track, !is_sequencer_track_active(track)); } + +void sequencer_toggle_single_active_track(uint8_t track) { + if (is_sequencer_track_active(track)) { + sequencer_internal_state.active_tracks = 0; + } else { + sequencer_internal_state.active_tracks = 1 << track; + } +} + +bool is_sequencer_step_on(uint8_t step) { return step < SEQUENCER_STEPS && (sequencer_config.steps[step] & sequencer_internal_state.active_tracks) > 0; } + +bool is_sequencer_step_on_for_track(uint8_t step, uint8_t track) { return step < SEQUENCER_STEPS && (sequencer_config.steps[step] >> track) & true; } + +void sequencer_set_step(uint8_t step, bool value) { + if (step < SEQUENCER_STEPS) { + if (value) { + sequencer_config.steps[step] |= sequencer_internal_state.active_tracks; + } else { + sequencer_config.steps[step] &= ~sequencer_internal_state.active_tracks; + } + dprintf("sequencer: step %d is %s\n", step, value ? "on" : "off"); + } else { + dprintf("sequencer: step %d is out of range\n", step); + } +} + +void sequencer_toggle_step(uint8_t step) { + if (is_sequencer_step_on(step)) { + sequencer_set_step_off(step); + } else { + sequencer_set_step_on(step); + } +} + +void sequencer_set_all_steps(bool value) { + for (uint8_t step = 0; step < SEQUENCER_STEPS; step++) { + if (value) { + sequencer_config.steps[step] |= sequencer_internal_state.active_tracks; + } else { + sequencer_config.steps[step] &= ~sequencer_internal_state.active_tracks; + } + } + dprintf("sequencer: all steps are %s\n", value ? "on" : "off"); +} + +uint8_t sequencer_get_tempo(void) { return sequencer_config.tempo; } + +void sequencer_set_tempo(uint8_t tempo) { + if (tempo > 0) { + sequencer_config.tempo = tempo; + dprintf("sequencer: tempo set to %d bpm\n", tempo); + } else { + dprintln("sequencer: cannot set tempo to 0"); + } +} + +void sequencer_increase_tempo(void) { + // Handling potential uint8_t overflow + if (sequencer_config.tempo < UINT8_MAX) { + sequencer_set_tempo(sequencer_config.tempo + 1); + } else { + dprintf("sequencer: cannot set tempo above %d\n", UINT8_MAX); + } +} + +void sequencer_decrease_tempo(void) { sequencer_set_tempo(sequencer_config.tempo - 1); } + +sequencer_resolution_t sequencer_get_resolution(void) { return sequencer_config.resolution; } + +void sequencer_set_resolution(sequencer_resolution_t resolution) { + if (resolution >= 0 && resolution < SEQUENCER_RESOLUTIONS) { + sequencer_config.resolution = resolution; + dprintf("sequencer: resolution set to %d\n", resolution); + } else { + dprintf("sequencer: resolution %d is out of range\n", resolution); + } +} + +void sequencer_increase_resolution(void) { sequencer_set_resolution(sequencer_config.resolution + 1); } + +void sequencer_decrease_resolution(void) { sequencer_set_resolution(sequencer_config.resolution - 1); } + +uint8_t sequencer_get_current_step(void) { return sequencer_internal_state.current_step; } + +void sequencer_phase_attack(void) { + dprintf("sequencer: step %d\n", sequencer_internal_state.current_step); + dprintf("sequencer: time %d\n", timer_read()); + + if (sequencer_internal_state.current_track == 0) { + sequencer_internal_state.timer = timer_read(); + } + + if (timer_elapsed(sequencer_internal_state.timer) < sequencer_internal_state.current_track * SEQUENCER_TRACK_THROTTLE) { + return; + } + +#if defined(MIDI_ENABLE) || defined(MIDI_MOCKED) + if (is_sequencer_step_on_for_track(sequencer_internal_state.current_step, sequencer_internal_state.current_track)) { + process_midi_basic_noteon(midi_compute_note(sequencer_config.track_notes[sequencer_internal_state.current_track])); + } +#endif + + if (sequencer_internal_state.current_track < SEQUENCER_TRACKS - 1) { + sequencer_internal_state.current_track++; + } else { + sequencer_internal_state.phase = SEQUENCER_PHASE_RELEASE; + } +} + +void sequencer_phase_release(void) { + if (timer_elapsed(sequencer_internal_state.timer) < SEQUENCER_PHASE_RELEASE_TIMEOUT + sequencer_internal_state.current_track * SEQUENCER_TRACK_THROTTLE) { + return; + } +#if defined(MIDI_ENABLE) || defined(MIDI_MOCKED) + if (is_sequencer_step_on_for_track(sequencer_internal_state.current_step, sequencer_internal_state.current_track)) { + process_midi_basic_noteoff(midi_compute_note(sequencer_config.track_notes[sequencer_internal_state.current_track])); + } +#endif + if (sequencer_internal_state.current_track > 0) { + sequencer_internal_state.current_track--; + } else { + sequencer_internal_state.phase = SEQUENCER_PHASE_PAUSE; + } +} + +void sequencer_phase_pause(void) { + if (timer_elapsed(sequencer_internal_state.timer) < sequencer_get_step_duration()) { + return; + } + + sequencer_internal_state.current_step = (sequencer_internal_state.current_step + 1) % SEQUENCER_STEPS; + sequencer_internal_state.phase = SEQUENCER_PHASE_ATTACK; +} + +void matrix_scan_sequencer(void) { + if (!sequencer_config.enabled) { + return; + } + + if (sequencer_internal_state.phase == SEQUENCER_PHASE_PAUSE) { + sequencer_phase_pause(); + } + + if (sequencer_internal_state.phase == SEQUENCER_PHASE_RELEASE) { + sequencer_phase_release(); + } + + if (sequencer_internal_state.phase == SEQUENCER_PHASE_ATTACK) { + sequencer_phase_attack(); + } +} + +uint16_t sequencer_get_beat_duration(void) { return get_beat_duration(sequencer_config.tempo); } + +uint16_t sequencer_get_step_duration(void) { return get_step_duration(sequencer_config.tempo, sequencer_config.resolution); } + +uint16_t get_beat_duration(uint8_t tempo) { + // Don’t crash in the unlikely case where the given tempo is 0 + if (tempo == 0) { + return get_beat_duration(60); + } + + /** + * Given + * t = tempo and d = duration, both strictly greater than 0 + * When + * t beats / minute = 1 beat / d ms + * Then + * t beats / 60000ms = 1 beat / d ms + * d ms = 60000ms / t + */ + return 60000 / tempo; +} + +uint16_t get_step_duration(uint8_t tempo, sequencer_resolution_t resolution) { + /** + * Resolution cheatsheet: + * 1/2 => 2 steps per 4 beats + * 1/2T => 3 steps per 4 beats + * 1/4 => 4 steps per 4 beats + * 1/4T => 6 steps per 4 beats + * 1/8 => 8 steps per 4 beats + * 1/8T => 12 steps per 4 beats + * 1/16 => 16 steps per 4 beats + * 1/16T => 24 steps per 4 beats + * 1/32 => 32 steps per 4 beats + * + * The number of steps for binary resolutions follows the powers of 2. + * The ternary variants are simply 1.5x faster. + */ + bool is_binary = resolution % 2 == 0; + uint8_t binary_steps = 2 << (resolution / 2); + uint16_t binary_step_duration = get_beat_duration(tempo) * 4 / binary_steps; + + return is_binary ? binary_step_duration : 2 * binary_step_duration / 3; +} diff --git a/quantum/sequencer/sequencer.h b/quantum/sequencer/sequencer.h new file mode 100644 index 000000000000..aeca7a1e9b10 --- /dev/null +++ b/quantum/sequencer/sequencer.h @@ -0,0 +1,122 @@ +/* Copyright 2020 Rodolphe Belouin + * + * 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 . + */ + +#pragma once + +#include +#include "debug.h" +#include "timer.h" + +// Maximum number of steps: 256 +#ifndef SEQUENCER_STEPS +# define SEQUENCER_STEPS 16 +#endif + +// Maximum number of tracks: 8 +#ifndef SEQUENCER_TRACKS +# define SEQUENCER_TRACKS 8 +#endif + +#ifndef SEQUENCER_TRACK_THROTTLE +# define SEQUENCER_TRACK_THROTTLE 3 +#endif + +#ifndef SEQUENCER_PHASE_RELEASE_TIMEOUT +# define SEQUENCER_PHASE_RELEASE_TIMEOUT 30 +#endif + +/** + * Make sure that the items of this enumeration follow the powers of 2, separated by a ternary variant. + * Check the implementation of `get_step_duration` for further explanation. + */ +typedef enum { SQ_RES_2, SQ_RES_2T, SQ_RES_4, SQ_RES_4T, SQ_RES_8, SQ_RES_8T, SQ_RES_16, SQ_RES_16T, SQ_RES_32, SEQUENCER_RESOLUTIONS } sequencer_resolution_t; + +typedef struct { + bool enabled; + uint8_t steps[SEQUENCER_STEPS]; + uint16_t track_notes[SEQUENCER_TRACKS]; + uint8_t tempo; // Is a maximum tempo of 255 reasonable? + sequencer_resolution_t resolution; +} sequencer_config_t; + +/** + * Because Digital Audio Workstations get overwhelmed when too many MIDI signals are sent concurrently, + * We use a "phase" state machine to delay some of the events. + */ +typedef enum sequencer_phase_t { + SEQUENCER_PHASE_ATTACK, // t=0ms, send the MIDI note on signal + SEQUENCER_PHASE_RELEASE, // t=SEQUENCER_PHASE_RELEASE_TIMEOUT ms, send the MIDI note off signal + SEQUENCER_PHASE_PAUSE // t=step duration ms, loop +} sequencer_phase_t; + +typedef struct { + uint8_t active_tracks; + uint8_t current_track; + uint8_t current_step; + uint16_t timer; + sequencer_phase_t phase; +} sequencer_state_t; + +extern sequencer_config_t sequencer_config; + +// We expose the internal state to make the feature more "unit-testable" +extern sequencer_state_t sequencer_internal_state; + +bool is_sequencer_on(void); +void sequencer_toggle(void); +void sequencer_on(void); +void sequencer_off(void); + +void sequencer_set_track_notes(const uint16_t track_notes[SEQUENCER_TRACKS]); + +bool is_sequencer_track_active(uint8_t track); +void sequencer_set_track_activation(uint8_t track, bool value); +void sequencer_toggle_track_activation(uint8_t track); +void sequencer_toggle_single_active_track(uint8_t track); + +#define sequencer_activate_track(track) sequencer_set_track_activation(track, true) +#define sequencer_deactivate_track(track) sequencer_set_track_activation(track, false) + +bool is_sequencer_step_on(uint8_t step); +bool is_sequencer_step_on_for_track(uint8_t step, uint8_t track); +void sequencer_set_step(uint8_t step, bool value); +void sequencer_toggle_step(uint8_t step); +void sequencer_set_all_steps(bool value); + +#define sequencer_set_step_on(step) sequencer_set_step(step, true) +#define sequencer_set_step_off(step) sequencer_set_step(step, false) +#define sequencer_set_all_steps_on() sequencer_set_all_steps(true) +#define sequencer_set_all_steps_off() sequencer_set_all_steps(false) + +uint8_t sequencer_get_tempo(void); +void sequencer_set_tempo(uint8_t tempo); +void sequencer_increase_tempo(void); +void sequencer_decrease_tempo(void); + +sequencer_resolution_t sequencer_get_resolution(void); +void sequencer_set_resolution(sequencer_resolution_t resolution); +void sequencer_increase_resolution(void); +void sequencer_decrease_resolution(void); + +uint8_t sequencer_get_current_step(void); + +uint16_t sequencer_get_beat_duration(void); +uint16_t sequencer_get_step_duration(void); + +uint16_t get_beat_duration(uint8_t tempo); +uint16_t get_step_duration(uint8_t tempo, sequencer_resolution_t resolution); + +void matrix_scan_sequencer(void); diff --git a/quantum/sequencer/tests/midi_mock.c b/quantum/sequencer/tests/midi_mock.c new file mode 100644 index 000000000000..236e16f9d70e --- /dev/null +++ b/quantum/sequencer/tests/midi_mock.c @@ -0,0 +1,26 @@ +/* Copyright 2020 Rodolphe Belouin + * + * 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 . + */ + +#include "midi_mock.h" + +uint16_t last_noteon = 0; +uint16_t last_noteoff = 0; + +uint16_t midi_compute_note(uint16_t keycode) { return keycode; } + +void process_midi_basic_noteon(uint16_t note) { last_noteon = note; } + +void process_midi_basic_noteoff(uint16_t note) { last_noteoff = note; } diff --git a/quantum/sequencer/tests/midi_mock.h b/quantum/sequencer/tests/midi_mock.h new file mode 100644 index 000000000000..4d8c2eb307b4 --- /dev/null +++ b/quantum/sequencer/tests/midi_mock.h @@ -0,0 +1,26 @@ +/* Copyright 2020 Rodolphe Belouin + * + * 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 . + */ + +#pragma once + +#include + +extern uint16_t last_noteon; +extern uint16_t last_noteoff; + +uint16_t midi_compute_note(uint16_t keycode); +void process_midi_basic_noteon(uint16_t note); +void process_midi_basic_noteoff(uint16_t note); diff --git a/quantum/sequencer/tests/rules.mk b/quantum/sequencer/tests/rules.mk new file mode 100644 index 000000000000..76c221cf92aa --- /dev/null +++ b/quantum/sequencer/tests/rules.mk @@ -0,0 +1,11 @@ +# The letter case of these variables might seem odd. However: +# - it is consistent with the serial_link example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features) +# - Neither `make test:sequencer` or `make test:SEQUENCER` work when using SCREAMING_SNAKE_CASE + +sequencer_DEFS := -DNO_DEBUG -DMIDI_MOCKED + +sequencer_SRC := \ + $(QUANTUM_PATH)/sequencer/tests/midi_mock.c \ + $(QUANTUM_PATH)/sequencer/tests/sequencer_tests.cpp \ + $(QUANTUM_PATH)/sequencer/sequencer.c \ + $(TMK_PATH)/common/test/timer.c diff --git a/quantum/sequencer/tests/sequencer_tests.cpp b/quantum/sequencer/tests/sequencer_tests.cpp new file mode 100644 index 000000000000..e81984e5b51b --- /dev/null +++ b/quantum/sequencer/tests/sequencer_tests.cpp @@ -0,0 +1,590 @@ +/* Copyright 2020 Rodolphe Belouin + * + * 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 . + */ + +#include "gtest/gtest.h" + +extern "C" { +#include "sequencer.h" +#include "midi_mock.h" +#include "quantum/quantum_keycodes.h" +} + +extern "C" { +void set_time(uint32_t t); +void advance_time(uint32_t ms); +} + +class SequencerTest : public ::testing::Test { + protected: + void SetUp() override { + config_copy.enabled = sequencer_config.enabled; + + for (int i = 0; i < SEQUENCER_STEPS; i++) { + config_copy.steps[i] = sequencer_config.steps[i]; + } + + for (int i = 0; i < SEQUENCER_TRACKS; i++) { + config_copy.track_notes[i] = sequencer_config.track_notes[i]; + } + + config_copy.tempo = sequencer_config.tempo; + config_copy.resolution = sequencer_config.resolution; + + state_copy.active_tracks = sequencer_internal_state.active_tracks; + state_copy.current_track = sequencer_internal_state.current_track; + state_copy.current_step = sequencer_internal_state.current_step; + state_copy.timer = sequencer_internal_state.timer; + + last_noteon = 0; + last_noteoff = 0; + + set_time(0); + } + + void TearDown() override { + sequencer_config.enabled = config_copy.enabled; + + for (int i = 0; i < SEQUENCER_STEPS; i++) { + sequencer_config.steps[i] = config_copy.steps[i]; + } + + for (int i = 0; i < SEQUENCER_TRACKS; i++) { + sequencer_config.track_notes[i] = config_copy.track_notes[i]; + } + + sequencer_config.tempo = config_copy.tempo; + sequencer_config.resolution = config_copy.resolution; + + sequencer_internal_state.active_tracks = state_copy.active_tracks; + sequencer_internal_state.current_track = state_copy.current_track; + sequencer_internal_state.current_step = state_copy.current_step; + sequencer_internal_state.timer = state_copy.timer; + } + + sequencer_config_t config_copy; + sequencer_state_t state_copy; +}; + +TEST_F(SequencerTest, TestOffByDefault) { EXPECT_EQ(is_sequencer_on(), false); } + +TEST_F(SequencerTest, TestOn) { + sequencer_config.enabled = false; + + sequencer_on(); + EXPECT_EQ(is_sequencer_on(), true); + + // sequencer_on is idempotent + sequencer_on(); + EXPECT_EQ(is_sequencer_on(), true); +} + +TEST_F(SequencerTest, TestOff) { + sequencer_config.enabled = true; + + sequencer_off(); + EXPECT_EQ(is_sequencer_on(), false); + + // sequencer_off is idempotent + sequencer_off(); + EXPECT_EQ(is_sequencer_on(), false); +} + +TEST_F(SequencerTest, TestToggle) { + sequencer_config.enabled = false; + + sequencer_toggle(); + EXPECT_EQ(is_sequencer_on(), true); + + sequencer_toggle(); + EXPECT_EQ(is_sequencer_on(), false); +} + +TEST_F(SequencerTest, TestNoActiveTrackByDefault) { + for (int i = 0; i < SEQUENCER_TRACKS; i++) { + EXPECT_EQ(is_sequencer_track_active(i), false); + } +} + +TEST_F(SequencerTest, TestGetActiveTracks) { + sequencer_internal_state.active_tracks = (1 << 7) + (1 << 6) + (1 << 3) + (1 << 1) + (1 << 0); + + EXPECT_EQ(is_sequencer_track_active(0), true); + EXPECT_EQ(is_sequencer_track_active(1), true); + EXPECT_EQ(is_sequencer_track_active(2), false); + EXPECT_EQ(is_sequencer_track_active(3), true); + EXPECT_EQ(is_sequencer_track_active(4), false); + EXPECT_EQ(is_sequencer_track_active(5), false); + EXPECT_EQ(is_sequencer_track_active(6), true); + EXPECT_EQ(is_sequencer_track_active(7), true); +} + +TEST_F(SequencerTest, TestGetActiveTracksOutOfBound) { + sequencer_set_track_activation(-1, true); + sequencer_set_track_activation(8, true); + + EXPECT_EQ(is_sequencer_track_active(-1), false); + EXPECT_EQ(is_sequencer_track_active(8), false); +} + +TEST_F(SequencerTest, TestToggleTrackActivation) { + sequencer_internal_state.active_tracks = (1 << 7) + (1 << 6) + (1 << 3) + (1 << 1) + (1 << 0); + + sequencer_toggle_track_activation(6); + + EXPECT_EQ(is_sequencer_track_active(0), true); + EXPECT_EQ(is_sequencer_track_active(1), true); + EXPECT_EQ(is_sequencer_track_active(2), false); + EXPECT_EQ(is_sequencer_track_active(3), true); + EXPECT_EQ(is_sequencer_track_active(4), false); + EXPECT_EQ(is_sequencer_track_active(5), false); + EXPECT_EQ(is_sequencer_track_active(6), false); + EXPECT_EQ(is_sequencer_track_active(7), true); +} + +TEST_F(SequencerTest, TestToggleSingleTrackActivation) { + sequencer_internal_state.active_tracks = (1 << 7) + (1 << 6) + (1 << 3) + (1 << 1) + (1 << 0); + + sequencer_toggle_single_active_track(2); + + EXPECT_EQ(is_sequencer_track_active(0), false); + EXPECT_EQ(is_sequencer_track_active(1), false); + EXPECT_EQ(is_sequencer_track_active(2), true); + EXPECT_EQ(is_sequencer_track_active(3), false); + EXPECT_EQ(is_sequencer_track_active(4), false); + EXPECT_EQ(is_sequencer_track_active(5), false); + EXPECT_EQ(is_sequencer_track_active(6), false); + EXPECT_EQ(is_sequencer_track_active(7), false); +} + +TEST_F(SequencerTest, TestStepOffByDefault) { + for (int i = 0; i < SEQUENCER_STEPS; i++) { + EXPECT_EQ(is_sequencer_step_on(i), false); + } +} + +TEST_F(SequencerTest, TestIsStepOffWithNoActiveTracks) { + sequencer_config.steps[3] = 0xFF; + EXPECT_EQ(is_sequencer_step_on(3), false); +} + +TEST_F(SequencerTest, TestIsStepOffWithGivenActiveTracks) { + sequencer_set_track_activation(2, true); + sequencer_set_track_activation(3, true); + + sequencer_config.steps[3] = (1 << 0) + (1 << 1); + + // No active tracks have the step enabled, so it is off + EXPECT_EQ(is_sequencer_step_on(3), false); +} + +TEST_F(SequencerTest, TestIsStepOnWithGivenActiveTracks) { + sequencer_set_track_activation(2, true); + sequencer_set_track_activation(3, true); + + sequencer_config.steps[3] = (1 << 2); + + // Track 2 has the step enabled, so it is on + EXPECT_EQ(is_sequencer_step_on(3), true); +} + +TEST_F(SequencerTest, TestIsStepOffForGivenTrack) { + sequencer_config.steps[3] = 0x00; + EXPECT_EQ(is_sequencer_step_on_for_track(3, 5), false); +} + +TEST_F(SequencerTest, TestIsStepOnForGivenTrack) { + sequencer_config.steps[3] = (1 << 5); + EXPECT_EQ(is_sequencer_step_on_for_track(3, 5), true); +} + +TEST_F(SequencerTest, TestSetStepOn) { + sequencer_internal_state.active_tracks = (1 << 6) + (1 << 3) + (1 << 2); + sequencer_config.steps[2] = (1 << 5) + (1 << 2); + + sequencer_set_step(2, true); + + EXPECT_EQ(sequencer_config.steps[2], (1 << 6) + (1 << 5) + (1 << 3) + (1 << 2)); +} + +TEST_F(SequencerTest, TestSetStepOff) { + sequencer_internal_state.active_tracks = (1 << 6) + (1 << 3) + (1 << 2); + sequencer_config.steps[2] = (1 << 5) + (1 << 2); + + sequencer_set_step(2, false); + + EXPECT_EQ(sequencer_config.steps[2], (1 << 5)); +} + +TEST_F(SequencerTest, TestToggleStepOff) { + sequencer_internal_state.active_tracks = (1 << 6) + (1 << 3) + (1 << 2); + sequencer_config.steps[2] = (1 << 5) + (1 << 2); + + sequencer_toggle_step(2); + + EXPECT_EQ(sequencer_config.steps[2], (1 << 5)); +} + +TEST_F(SequencerTest, TestToggleStepOn) { + sequencer_internal_state.active_tracks = (1 << 6) + (1 << 3) + (1 << 2); + sequencer_config.steps[2] = 0; + + sequencer_toggle_step(2); + + EXPECT_EQ(sequencer_config.steps[2], (1 << 6) + (1 << 3) + (1 << 2)); +} + +TEST_F(SequencerTest, TestSetAllStepsOn) { + sequencer_internal_state.active_tracks = (1 << 6) + (1 << 3) + (1 << 2); + sequencer_config.steps[2] = (1 << 7) + (1 << 6); + sequencer_config.steps[4] = (1 << 3) + (1 << 1); + + sequencer_set_all_steps(true); + + EXPECT_EQ(sequencer_config.steps[2], (1 << 7) + (1 << 6) + (1 << 3) + (1 << 2)); + EXPECT_EQ(sequencer_config.steps[4], (1 << 6) + (1 << 3) + (1 << 2) + (1 << 1)); +} + +TEST_F(SequencerTest, TestSetAllStepsOff) { + sequencer_internal_state.active_tracks = (1 << 6) + (1 << 3) + (1 << 2); + sequencer_config.steps[2] = (1 << 7) + (1 << 6); + sequencer_config.steps[4] = (1 << 3) + (1 << 1); + + sequencer_set_all_steps(false); + + EXPECT_EQ(sequencer_config.steps[2], (1 << 7)); + EXPECT_EQ(sequencer_config.steps[4], (1 << 1)); +} + +TEST_F(SequencerTest, TestSetTempoZero) { + sequencer_config.tempo = 123; + + sequencer_set_tempo(0); + + EXPECT_EQ(sequencer_config.tempo, 123); +} + +TEST_F(SequencerTest, TestIncreaseTempoMax) { + sequencer_config.tempo = UINT8_MAX; + + sequencer_increase_tempo(); + + EXPECT_EQ(sequencer_config.tempo, UINT8_MAX); +} + +TEST_F(SequencerTest, TestSetResolutionLowerBound) { + sequencer_config.resolution = SQ_RES_4; + + sequencer_set_resolution((sequencer_resolution_t)-1); + + EXPECT_EQ(sequencer_config.resolution, SQ_RES_4); +} + +TEST_F(SequencerTest, TestSetResolutionUpperBound) { + sequencer_config.resolution = SQ_RES_4; + + sequencer_set_resolution(SEQUENCER_RESOLUTIONS); + + EXPECT_EQ(sequencer_config.resolution, SQ_RES_4); +} + +TEST_F(SequencerTest, TestGetBeatDuration) { + EXPECT_EQ(get_beat_duration(60), 1000); + EXPECT_EQ(get_beat_duration(120), 500); + EXPECT_EQ(get_beat_duration(240), 250); + EXPECT_EQ(get_beat_duration(0), 1000); +} + +TEST_F(SequencerTest, TestGetStepDuration60) { + /** + * Resolution cheatsheet: + * 1/2 => 2 steps per 4 beats + * 1/2T => 3 steps per 4 beats + * 1/4 => 4 steps per 4 beats + * 1/4T => 6 steps per 4 beats + * 1/8 => 8 steps per 4 beats + * 1/8T => 12 steps per 4 beats + * 1/16 => 16 steps per 4 beats + * 1/16T => 24 steps per 4 beats + * 1/32 => 32 steps per 4 beats + * + * The number of steps for binary resolutions follows the powers of 2. + * The ternary variants are simply 1.5x faster. + */ + EXPECT_EQ(get_step_duration(60, SQ_RES_2), 2000); + EXPECT_EQ(get_step_duration(60, SQ_RES_4), 1000); + EXPECT_EQ(get_step_duration(60, SQ_RES_8), 500); + EXPECT_EQ(get_step_duration(60, SQ_RES_16), 250); + EXPECT_EQ(get_step_duration(60, SQ_RES_32), 125); + + EXPECT_EQ(get_step_duration(60, SQ_RES_2T), 1333); + EXPECT_EQ(get_step_duration(60, SQ_RES_4T), 666); + EXPECT_EQ(get_step_duration(60, SQ_RES_8T), 333); + EXPECT_EQ(get_step_duration(60, SQ_RES_16T), 166); +} + +TEST_F(SequencerTest, TestGetStepDuration120) { + /** + * Resolution cheatsheet: + * 1/2 => 2 steps per 4 beats + * 1/2T => 3 steps per 4 beats + * 1/4 => 4 steps per 4 beats + * 1/4T => 6 steps per 4 beats + * 1/8 => 8 steps per 4 beats + * 1/8T => 12 steps per 4 beats + * 1/16 => 16 steps per 4 beats + * 1/16T => 24 steps per 4 beats + * 1/32 => 32 steps per 4 beats + * + * The number of steps for binary resolutions follows the powers of 2. + * The ternary variants are simply 1.5x faster. + */ + EXPECT_EQ(get_step_duration(30, SQ_RES_2), 4000); + EXPECT_EQ(get_step_duration(30, SQ_RES_4), 2000); + EXPECT_EQ(get_step_duration(30, SQ_RES_8), 1000); + EXPECT_EQ(get_step_duration(30, SQ_RES_16), 500); + EXPECT_EQ(get_step_duration(30, SQ_RES_32), 250); + + EXPECT_EQ(get_step_duration(30, SQ_RES_2T), 2666); + EXPECT_EQ(get_step_duration(30, SQ_RES_4T), 1333); + EXPECT_EQ(get_step_duration(30, SQ_RES_8T), 666); + EXPECT_EQ(get_step_duration(30, SQ_RES_16T), 333); +} + +void setUpMatrixScanSequencerTest(void) { + sequencer_config.enabled = true; + sequencer_config.tempo = 120; + sequencer_config.resolution = SQ_RES_16; + + // Configure the notes for each track + sequencer_config.track_notes[0] = MI_C; + sequencer_config.track_notes[1] = MI_D; + sequencer_config.track_notes[2] = MI_E; + sequencer_config.track_notes[3] = MI_F; + sequencer_config.track_notes[4] = MI_G; + sequencer_config.track_notes[5] = MI_A; + sequencer_config.track_notes[6] = MI_B; + sequencer_config.track_notes[7] = MI_C; + + // Turn on some steps + sequencer_config.steps[0] = (1 << 0); + sequencer_config.steps[2] = (1 << 1) + (1 << 0); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldAttackFirstTrackOfFirstStep) { + setUpMatrixScanSequencerTest(); + + matrix_scan_sequencer(); + EXPECT_EQ(last_noteon, MI_C); + EXPECT_EQ(last_noteoff, 0); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldAttackSecondTrackAfterFirstTrackOfFirstStep) { + setUpMatrixScanSequencerTest(); + + matrix_scan_sequencer(); + EXPECT_EQ(sequencer_internal_state.current_step, 0); + EXPECT_EQ(sequencer_internal_state.current_track, 1); + EXPECT_EQ(sequencer_internal_state.phase, SEQUENCER_PHASE_ATTACK); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldNotAttackInactiveTrackFirstStep) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 0; + sequencer_internal_state.current_track = 1; + + // Wait some time after the first track has been attacked + advance_time(SEQUENCER_TRACK_THROTTLE); + + matrix_scan_sequencer(); + EXPECT_EQ(last_noteon, 0); + EXPECT_EQ(last_noteoff, 0); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldAttackThirdTrackAfterSecondTrackOfFirstStep) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 0; + sequencer_internal_state.current_track = 1; + + // Wait some time after the second track has been attacked + advance_time(2 * SEQUENCER_TRACK_THROTTLE); + + matrix_scan_sequencer(); + EXPECT_EQ(sequencer_internal_state.current_step, 0); + EXPECT_EQ(sequencer_internal_state.current_track, 2); + EXPECT_EQ(sequencer_internal_state.phase, SEQUENCER_PHASE_ATTACK); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldEnterReleasePhaseAfterLastTrackHasBeenProcessedFirstStep) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 0; + sequencer_internal_state.current_track = SEQUENCER_TRACKS - 1; + + // Wait until all notes have been attacked + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + + matrix_scan_sequencer(); + EXPECT_EQ(last_noteon, 0); + EXPECT_EQ(last_noteoff, 0); + EXPECT_EQ(sequencer_internal_state.current_step, 0); + EXPECT_EQ(sequencer_internal_state.current_track, SEQUENCER_TRACKS - 1); + EXPECT_EQ(sequencer_internal_state.phase, SEQUENCER_PHASE_RELEASE); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldReleaseBackwards) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 0; + sequencer_internal_state.current_track = SEQUENCER_TRACKS - 1; + sequencer_internal_state.phase = SEQUENCER_PHASE_RELEASE; + + // Wait until all notes have been attacked + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + // + the release timeout + advance_time(SEQUENCER_PHASE_RELEASE_TIMEOUT); + + matrix_scan_sequencer(); + EXPECT_EQ(sequencer_internal_state.current_step, 0); + EXPECT_EQ(sequencer_internal_state.current_track, SEQUENCER_TRACKS - 2); + EXPECT_EQ(sequencer_internal_state.phase, SEQUENCER_PHASE_RELEASE); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldNotReleaseInactiveTrackFirstStep) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 0; + sequencer_internal_state.current_track = SEQUENCER_TRACKS - 1; + sequencer_internal_state.phase = SEQUENCER_PHASE_RELEASE; + + // Wait until all notes have been attacked + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + // + the release timeout + advance_time(SEQUENCER_PHASE_RELEASE_TIMEOUT); + + matrix_scan_sequencer(); + EXPECT_EQ(last_noteon, 0); + EXPECT_EQ(last_noteoff, 0); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldReleaseFirstTrackFirstStep) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 0; + sequencer_internal_state.current_track = 0; + sequencer_internal_state.phase = SEQUENCER_PHASE_RELEASE; + + // Wait until all notes have been attacked + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + // + the release timeout + advance_time(SEQUENCER_PHASE_RELEASE_TIMEOUT); + // + all the other notes have been released + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + + matrix_scan_sequencer(); + EXPECT_EQ(last_noteon, 0); + EXPECT_EQ(last_noteoff, MI_C); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldEnterPausePhaseAfterRelease) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 0; + sequencer_internal_state.current_track = 0; + sequencer_internal_state.phase = SEQUENCER_PHASE_RELEASE; + + // Wait until all notes have been attacked + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + // + the release timeout + advance_time(SEQUENCER_PHASE_RELEASE_TIMEOUT); + // + all the other notes have been released + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + + matrix_scan_sequencer(); + EXPECT_EQ(sequencer_internal_state.current_step, 0); + EXPECT_EQ(sequencer_internal_state.current_track, 0); + EXPECT_EQ(sequencer_internal_state.phase, SEQUENCER_PHASE_PAUSE); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldProcessFirstTrackOfSecondStepAfterPause) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 0; + sequencer_internal_state.current_track = 0; + sequencer_internal_state.phase = SEQUENCER_PHASE_PAUSE; + + // Wait until all notes have been attacked + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + // + the release timeout + advance_time(SEQUENCER_PHASE_RELEASE_TIMEOUT); + // + all the other notes have been released + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + // + the step duration (one 16th at tempo=120 lasts 125ms) + advance_time(125); + + matrix_scan_sequencer(); + EXPECT_EQ(sequencer_internal_state.current_step, 1); + EXPECT_EQ(sequencer_internal_state.current_track, 1); + EXPECT_EQ(sequencer_internal_state.phase, SEQUENCER_PHASE_ATTACK); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldProcessSecondTrackTooEarly) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 2; + sequencer_internal_state.current_track = 1; + + matrix_scan_sequencer(); + EXPECT_EQ(last_noteon, 0); + EXPECT_EQ(last_noteoff, 0); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldProcessSecondTrackOnTime) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = 2; + sequencer_internal_state.current_track = 1; + + // Wait until first track has been attacked + advance_time(SEQUENCER_TRACK_THROTTLE); + + matrix_scan_sequencer(); + EXPECT_EQ(last_noteon, MI_D); + EXPECT_EQ(last_noteoff, 0); +} + +TEST_F(SequencerTest, TestMatrixScanSequencerShouldLoopOnceSequenceIsOver) { + setUpMatrixScanSequencerTest(); + + sequencer_internal_state.current_step = SEQUENCER_STEPS - 1; + sequencer_internal_state.current_track = 0; + sequencer_internal_state.phase = SEQUENCER_PHASE_PAUSE; + + // Wait until all notes have been attacked + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + // + the release timeout + advance_time(SEQUENCER_PHASE_RELEASE_TIMEOUT); + // + all the other notes have been released + advance_time((SEQUENCER_TRACKS - 1) * SEQUENCER_TRACK_THROTTLE); + // + the step duration (one 16th at tempo=120 lasts 125ms) + advance_time(125); + + matrix_scan_sequencer(); + EXPECT_EQ(sequencer_internal_state.current_step, 0); + EXPECT_EQ(sequencer_internal_state.current_track, 1); + EXPECT_EQ(sequencer_internal_state.phase, SEQUENCER_PHASE_ATTACK); +} diff --git a/quantum/sequencer/tests/testlist.mk b/quantum/sequencer/tests/testlist.mk new file mode 100644 index 000000000000..bb3899110922 --- /dev/null +++ b/quantum/sequencer/tests/testlist.mk @@ -0,0 +1 @@ +TEST_LIST += sequencer diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 5bad9db08f8a..cd5a024c3df4 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -45,6 +45,19 @@ uint8_t thisHand, thatHand; // user-defined overridable functions __attribute__((weak)) void matrix_slave_scan_user(void) {} +static inline void setPinOutput_writeLow(pin_t pin) { + ATOMIC_BLOCK_FORCEON { + setPinOutput(pin); + writePinLow(pin); + } +} + +static inline void setPinInputHigh_atomic(pin_t pin) { + ATOMIC_BLOCK_FORCEON { + setPinInputHigh(pin); + } +} + // matrix code #ifdef DIRECT_PINS @@ -83,22 +96,23 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) # if (DIODE_DIRECTION == COL2ROW) static void select_row(uint8_t row) { - setPinOutput(row_pins[row]); - writePinLow(row_pins[row]); + setPinOutput_writeLow(row_pins[row]); } -static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); } +static void unselect_row(uint8_t row) { + setPinInputHigh_atomic(row_pins[row]); +} static void unselect_rows(void) { for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { - setPinInputHigh(row_pins[x]); + setPinInputHigh_atomic(row_pins[x]); } } static void init_pins(void) { unselect_rows(); for (uint8_t x = 0; x < MATRIX_COLS; x++) { - setPinInputHigh(col_pins[x]); + setPinInputHigh_atomic(col_pins[x]); } } @@ -133,22 +147,23 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) # elif (DIODE_DIRECTION == ROW2COL) static void select_col(uint8_t col) { - setPinOutput(col_pins[col]); - writePinLow(col_pins[col]); + setPinOutput_writeLow(col_pins[col]); } -static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); } +static void unselect_col(uint8_t col) { + setPinInputHigh_atomic(col_pins[col]); +} static void unselect_cols(void) { for (uint8_t x = 0; x < MATRIX_COLS; x++) { - setPinInputHigh(col_pins[x]); + setPinInputHigh_atomic(col_pins[x]); } } static void init_pins(void) { unselect_cols(); for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { - setPinInputHigh(row_pins[x]); + setPinInputHigh_atomic(row_pins[x]); } } diff --git a/requirements.txt b/requirements.txt index d20803577eab..6e907cf8e83c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Python requirements -# milc FIXME(skullydazed): Included in the repo for now. appdirs argcomplete colorama hjson +milc pygments diff --git a/show_options.mk b/show_options.mk index 8eef25877828..15407dfd2a04 100644 --- a/show_options.mk +++ b/show_options.mk @@ -20,6 +20,7 @@ HARDWARE_OPTION_NAMES = \ RGBLIGHT_ENABLE \ RGBLIGHT_CUSTOM_DRIVER \ RGB_MATRIX_ENABLE \ + RGB_MATRIX_DRIVER \ SERIAL_LINK_ENABLE \ CIE1931_CURVE \ MIDI_ENABLE \ diff --git a/testlist.mk b/testlist.mk index d949fb3eae01..ca1408806c9a 100644 --- a/testlist.mk +++ b/testlist.mk @@ -1,6 +1,7 @@ TEST_LIST = $(notdir $(patsubst %/rules.mk,%,$(wildcard $(ROOT_DIR)/tests/*/rules.mk))) FULL_TESTS := $(TEST_LIST) +include $(ROOT_DIR)/quantum/sequencer/tests/testlist.mk include $(ROOT_DIR)/quantum/serial_link/tests/testlist.mk define VALIDATE_TEST_LIST diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 2bd53f0dc8c9..e53edccee21f 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -123,6 +123,8 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/chconf.h)","") CHCONFDIR = $(KEYBOARD_PATH_1) else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/configs/chconf.h)","") CHCONFDIR = $(TOP_DIR)/platforms/chibios/$(BOARD)/configs +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/configs/chconf.h)","") + CHCONFDIR = $(TOP_DIR)/platforms/chibios/common/configs endif ifneq ("$(wildcard $(KEYBOARD_PATH_5)/halconf.h)","") @@ -137,6 +139,8 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/halconf.h)","") HALCONFDIR = $(KEYBOARD_PATH_1) else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/configs/halconf.h)","") HALCONFDIR = $(TOP_DIR)/platforms/chibios/$(BOARD)/configs +else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/configs/halconf.h)","") + HALCONFDIR = $(TOP_DIR)/platforms/chibios/common/configs endif # HAL-OSAL files (optional). @@ -183,8 +187,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/ld/$(MCU_LDSCRIPT).ld)","") - LDSCRIPT = $(TOP_DIR)/platforms/chibios/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)","") LDSCRIPT = $(STARTUPLD_CONTRIB)/$(MCU_LDSCRIPT).ld USE_CHIBIOS_CONTRIB = yes @@ -209,6 +213,8 @@ CHIBISRC := $(patsubst $(TOP_DIR)/%,%,$(CHIBISRC)) EXTRAINCDIRS += $(CHIBIOS)/os/license $(CHIBIOS)/os/oslib/include \ $(TOP_DIR)/platforms/chibios/$(BOARD)/configs \ + $(TOP_DIR)/platforms/chibios/common/configs \ + $(HALCONFDIR) $(CHCONFDIR) \ $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \ $(STREAMSINC) $(CHIBIOS)/os/various $(COMMON_VPATH) diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index aa1a2999e02b..fa87433db22b 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -37,9 +37,13 @@ along with this program. If not, see . # include "nodebug.h" #endif +#ifdef POINTING_DEVICE_ENABLE +# include "pointing_device.h" +#endif + int tp_buttons; -#ifdef RETRO_TAPPING +#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) int retro_tapping_counter = 0; #endif @@ -51,6 +55,10 @@ int retro_tapping_counter = 0; __attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; } #endif +#ifdef RETRO_TAPPING_PER_KEY +__attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { return false; } +#endif + #ifndef TAP_CODE_DELAY # define TAP_CODE_DELAY 0 #endif @@ -67,7 +75,7 @@ void action_exec(keyevent_t event) { dprint("EVENT: "); debug_event(event); dprintln(); -#ifdef RETRO_TAPPING +#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) retro_tapping_counter++; #endif } @@ -220,6 +228,19 @@ void process_record_handler(keyrecord_t *record) { process_action(record, action); } +#if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) +void register_button(bool pressed, enum mouse_buttons button) { +# ifdef PS2_MOUSE_ENABLE + tp_buttons = pressed ? tp_buttons | button : tp_buttons & ~button; +# endif +# ifdef POINTING_DEVICE_ENABLE + report_mouse_t currentReport = pointing_device_get_report(); + currentReport.buttons = pressed ? currentReport.buttons | button : currentReport.buttons & ~button; + pointing_device_set_report(currentReport); +# endif +} +#endif + /** \brief Take an action and processes it. * * FIXME: Needs documentation. @@ -404,15 +425,23 @@ void process_action(keyrecord_t *record, action_t action) { if (event.pressed) { mousekey_on(action.key.code); switch (action.key.code) { -# ifdef PS2_MOUSE_ENABLE +# if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) case KC_MS_BTN1: - tp_buttons |= (1 << 0); + register_button(true, MOUSE_BTN1); break; case KC_MS_BTN2: - tp_buttons |= (1 << 1); + register_button(true, MOUSE_BTN2); break; case KC_MS_BTN3: - tp_buttons |= (1 << 2); + register_button(true, MOUSE_BTN3); + break; +# endif +# ifdef POINTING_DEVICE_ENABLE + case KC_MS_BTN4: + register_button(true, MOUSE_BTN4); + break; + case KC_MS_BTN5: + register_button(true, MOUSE_BTN5); break; # endif default: @@ -422,15 +451,23 @@ void process_action(keyrecord_t *record, action_t action) { } else { mousekey_off(action.key.code); switch (action.key.code) { -# ifdef PS2_MOUSE_ENABLE +# if defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE) case KC_MS_BTN1: - tp_buttons &= ~(1 << 0); + register_button(false, MOUSE_BTN1); break; case KC_MS_BTN2: - tp_buttons &= ~(1 << 1); + register_button(false, MOUSE_BTN2); break; case KC_MS_BTN3: - tp_buttons &= ~(1 << 2); + register_button(false, MOUSE_BTN3); + break; +# endif +# ifdef POINTING_DEVICE_ENABLE + case KC_MS_BTN4: + register_button(false, MOUSE_BTN4); + break; + case KC_MS_BTN5: + register_button(false, MOUSE_BTN5); break; # endif default: @@ -692,20 +729,23 @@ void process_action(keyrecord_t *record, action_t action) { #endif #ifndef NO_ACTION_TAPPING -# ifdef RETRO_TAPPING +# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) if (!is_tap_action(action)) { retro_tapping_counter = 0; } else { if (event.pressed) { if (tap_count > 0) { retro_tapping_counter = 0; - } else { } } else { if (tap_count > 0) { retro_tapping_counter = 0; } else { - if (retro_tapping_counter == 2) { + if ( +# ifdef RETRO_TAPPING_PER_KEY + get_retro_tapping(get_event_keycode(record->event, false), record) && +# endif + retro_tapping_counter == 2) { tap_code(action.layer_tap.code); } retro_tapping_counter = 0; diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c index fd0e4409f0a3..000503b0821a 100644 --- a/tmk_core/common/action_util.c +++ b/tmk_core/common/action_util.c @@ -290,6 +290,32 @@ void set_macro_mods(uint8_t mods) { macro_mods = mods; } void clear_macro_mods(void) { macro_mods = 0; } #ifndef NO_ACTION_ONESHOT +/** \brief get oneshot mods + * + * FIXME: needs doc + */ +uint8_t get_oneshot_mods(void) { return oneshot_mods; } + +void add_oneshot_mods(uint8_t mods) { + if ((oneshot_mods & mods) != mods) { +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_time = timer_read(); +# endif + oneshot_mods |= mods; + oneshot_mods_changed_kb(mods); + } +} + +void del_oneshot_mods(uint8_t mods) { + if (oneshot_mods & mods) { + oneshot_mods &= ~mods; +# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + oneshot_time = oneshot_mods ? timer_read() : 0; +# endif + oneshot_mods_changed_kb(oneshot_mods); + } +} + /** \brief set oneshot mods * * FIXME: needs doc @@ -316,11 +342,6 @@ void clear_oneshot_mods(void) { oneshot_mods_changed_kb(oneshot_mods); } } -/** \brief get oneshot mods - * - * FIXME: needs doc - */ -uint8_t get_oneshot_mods(void) { return oneshot_mods; } #endif /** \brief Called when the one shot modifiers have been changed. diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h index 5dd8393da48e..743ff1406b46 100644 --- a/tmk_core/common/action_util.h +++ b/tmk_core/common/action_util.h @@ -57,12 +57,11 @@ void set_macro_mods(uint8_t mods); void clear_macro_mods(void); /* oneshot modifier */ -void set_oneshot_mods(uint8_t mods); uint8_t get_oneshot_mods(void); +void add_oneshot_mods(uint8_t mods); +void del_oneshot_mods(uint8_t mods); +void set_oneshot_mods(uint8_t mods); void clear_oneshot_mods(void); -void oneshot_toggle(void); -void oneshot_enable(void); -void oneshot_disable(void); bool has_oneshot_mods_timed_out(void); uint8_t get_oneshot_locked_mods(void); diff --git a/tmk_core/common/arm_atsam/suspend.c b/tmk_core/common/arm_atsam/suspend.c index 2dad005706cd..6a36740658cc 100644 --- a/tmk_core/common/arm_atsam/suspend.c +++ b/tmk_core/common/arm_atsam/suspend.c @@ -1,6 +1,6 @@ #include "matrix.h" #include "i2c_master.h" -#include "led_matrix.h" +#include "md_rgb_matrix.h" #include "suspend.h" /** \brief Suspend idle diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 7b2cf5c435aa..f6d016ec9d13 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -32,7 +32,7 @@ extern uint32_t __ram0_end__; -void bootloader_jump(void) { +__attribute__((weak)) void bootloader_jump(void) { // For STM32 MCUs with dual-bank flash, and we're incapable of jumping to the bootloader. The first valid flash // bank is executed unconditionally after a reset, so it doesn't enter DFU unless BOOT0 is high. Instead, we do // it with hardware...in this case, we pull a GPIO high/low depending on the configuration, connects 3.3V to @@ -58,7 +58,7 @@ void enter_bootloader_mode_if_requested(void) {} // not needed at all, but if a extern uint32_t __ram0_end__; -void bootloader_jump(void) { +__attribute__((weak)) void bootloader_jump(void) { *MAGIC_ADDR = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader NVIC_SystemReset(); } @@ -85,8 +85,8 @@ void enter_bootloader_mode_if_requested(void) { # if defined(BOOTLOADER_KIIBOHD) /* Kiibohd Bootloader (MCHCK and Infinity KB) */ # define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000 -const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff"; -void bootloader_jump(void) { +const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff"; +__attribute__((weak)) void bootloader_jump(void) { __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic)); // request reset SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk; @@ -95,7 +95,7 @@ void bootloader_jump(void) { # else /* defined(BOOTLOADER_KIIBOHD) */ /* Default for Kinetis - expecting an ARM Teensy */ # include "wait.h" -void bootloader_jump(void) { +__attribute__((weak)) void bootloader_jump(void) { wait_ms(100); __BKPT(0); } diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index 3c26b8f6130f..8ae4c30519f7 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c @@ -15,7 +15,10 @@ # include "eeprom_driver.h" #endif -extern layer_state_t default_layer_state; +#if defined(HAPTIC_ENABLE) +# include "haptic.h" +#endif + /** \brief eeconfig enable * * FIXME: needs doc @@ -70,6 +73,16 @@ void eeconfig_init_quantum(void) { #ifdef ORYX_ENABLE eeconfig_init_oryx(); #endif + +#if defined(HAPTIC_ENABLE) + haptic_reset(); +#else + // this is used in case haptic is disabled, but we still want sane defaults + // in the haptic configuration eeprom. All zero will trigger a haptic_reset + // when a haptic-enabled firmware is loaded onto the keyboard. + eeprom_update_dword(EECONFIG_HAPTIC, 0); +#endif + eeconfig_init_kb(); } diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 4b241b7b3ded..aefdd2bfb669 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -230,6 +230,20 @@ __attribute__((weak)) bool is_keyboard_left(void) { return true; } */ __attribute__((weak)) bool should_process_keypress(void) { return is_keyboard_master(); } +/** \brief housekeeping_task_kb + * + * Override this function if you have a need to execute code for every keyboard main loop iteration. + * This is specific to keyboard-level functionality. + */ +__attribute__((weak)) void housekeeping_task_kb(void) {} + +/** \brief housekeeping_task_user + * + * Override this function if you have a need to execute code for every keyboard main loop iteration. + * This is specific to user/keymap-level functionality. + */ +__attribute__((weak)) void housekeeping_task_user(void) {} + /** \brief keyboard_init * * FIXME: needs doc @@ -286,6 +300,10 @@ void keyboard_init(void) { dip_switch_init(); #endif +#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE) + debug_enable = true; +#endif + keyboard_post_init_kb(); /* Always keep this last */ } @@ -310,6 +328,9 @@ void keyboard_task(void) { uint8_t keys_processed = 0; #endif + housekeeping_task_kb(); + housekeeping_task_user(); + #if defined(OLED_DRIVER_ENABLE) && !defined(OLED_DISABLE_TIMEOUT) uint8_t ret = matrix_scan(); #else diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index d5836c40f922..1e16a3f489f3 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -73,6 +73,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); + #ifdef __cplusplus } #endif diff --git a/tmk_core/common/matrix.h b/tmk_core/common/matrix.h index 78506059e6ac..31ec844302c8 100644 --- a/tmk_core/common/matrix.h +++ b/tmk_core/common/matrix.h @@ -30,16 +30,6 @@ typedef uint32_t matrix_row_t; # error "MATRIX_COLS: invalid value" #endif -#if (MATRIX_ROWS <= 8) -typedef uint8_t matrix_col_t; -#elif (MATRIX_ROWS <= 16) -typedef uint16_t matrix_col_t; -#elif (MATRIX_ROWS <= 32) -typedef uint32_t matrix_col_t; -#else -# error "MATRIX_ROWS: invalid value" -#endif - #define MATRIX_ROW_SHIFTER ((matrix_row_t)1) #define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1 << col)) diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h index 1aa33c998d1e..610addf4319b 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h @@ -192,7 +192,11 @@ typedef struct { typedef struct { #if JOYSTICK_AXES_COUNT > 0 +# if JOYSTICK_AXES_RESOLUTION > 8 + int16_t axes[JOYSTICK_AXES_COUNT]; +# else int8_t axes[JOYSTICK_AXES_COUNT]; +# endif #endif #if JOYSTICK_BUTTON_COUNT > 0 diff --git a/tmk_core/protocol/arm_atsam.mk b/tmk_core/protocol/arm_atsam.mk index 8d6f724f0996..5bb45d658e51 100644 --- a/tmk_core/protocol/arm_atsam.mk +++ b/tmk_core/protocol/arm_atsam.mk @@ -4,9 +4,9 @@ SRC += $(ARM_ATSAM_DIR)/adc.c SRC += $(ARM_ATSAM_DIR)/clks.c SRC += $(ARM_ATSAM_DIR)/d51_util.c SRC += $(ARM_ATSAM_DIR)/i2c_master.c -ifeq ($(RGB_MATRIX_ENABLE),custom) - SRC += $(ARM_ATSAM_DIR)/led_matrix_programs.c - SRC += $(ARM_ATSAM_DIR)/led_matrix.c +ifeq ($(RGB_MATRIX_DRIVER),custom) + SRC += $(ARM_ATSAM_DIR)/md_rgb_matrix_programs.c + SRC += $(ARM_ATSAM_DIR)/md_rgb_matrix.c endif SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c SRC += $(ARM_ATSAM_DIR)/spi.c diff --git a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h index 8cb00b872ae9..d126c66e7d11 100644 --- a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h +++ b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h @@ -35,7 +35,7 @@ along with this program. If not, see . # include "main_arm_atsam.h" # ifdef RGB_MATRIX_ENABLE -# include "led_matrix.h" +# include "md_rgb_matrix.h" # include "rgb_matrix.h" # endif # include "issi3733_driver.h" diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index e4e79d351044..e10be52fb809 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -305,6 +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_kb(); + housekeeping_task_user(); } return 1; diff --git a/tmk_core/protocol/arm_atsam/led_matrix.c b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c similarity index 98% rename from tmk_core/protocol/arm_atsam/led_matrix.c rename to tmk_core/protocol/arm_atsam/md_rgb_matrix.c index 4b8cc7c5e16f..b337df76275c 100644 --- a/tmk_core/protocol/arm_atsam/led_matrix.c +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c @@ -23,7 +23,7 @@ along with this program. If not, see . #ifdef USE_MASSDROP_CONFIGURATOR __attribute__((weak)) led_instruction_t led_instructions[] = {{.end = 1}}; -static void led_matrix_massdrop_config_override(int i); +static void md_rgb_matrix_config_override(int i); #endif // USE_MASSDROP_CONFIGURATOR void SERCOM1_0_Handler(void) { @@ -188,7 +188,7 @@ void issi3733_prepare_arrays(void) { } } -void led_matrix_prepare(void) { +void md_rgb_matrix_prepare(void) { for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) { *led_map[i].rgb.r = 0; *led_map[i].rgb.g = 0; @@ -199,7 +199,7 @@ void led_matrix_prepare(void) { void led_set_one(int i, uint8_t r, uint8_t g, uint8_t b) { if (i < ISSI3733_LED_COUNT) { #ifdef USE_MASSDROP_CONFIGURATOR - led_matrix_massdrop_config_override(i); + md_rgb_matrix_config_override(i); #else led_buffer[i].r = r; led_buffer[i].g = g; @@ -219,7 +219,7 @@ void init(void) { issi3733_prepare_arrays(); - led_matrix_prepare(); + md_rgb_matrix_prepare(); gcr_min_counter = 0; v_5v_cat_hit = 0; @@ -290,7 +290,7 @@ void flush(void) { i2c_led_q_run(); } -void led_matrix_indicators(void) { +void md_rgb_matrix_indicators(void) { uint8_t kbled = keyboard_leds(); if (kbled && rgb_matrix_config.enable) { for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) { @@ -395,7 +395,7 @@ static void led_run_pattern(led_setup_t* f, float* ro, float* go, float* bo, flo } } -static void led_matrix_massdrop_config_override(int i) { +static void md_rgb_matrix_config_override(int i) { float ro = 0; float go = 0; float bo = 0; diff --git a/tmk_core/protocol/arm_atsam/led_matrix.h b/tmk_core/protocol/arm_atsam/md_rgb_matrix.h similarity index 99% rename from tmk_core/protocol/arm_atsam/led_matrix.h rename to tmk_core/protocol/arm_atsam/md_rgb_matrix.h index 8eaa5623bda5..322b0f99d163 100644 --- a/tmk_core/protocol/arm_atsam/led_matrix.h +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.h @@ -86,7 +86,7 @@ extern uint8_t gcr_actual_last; void gcr_compute(void); -void led_matrix_indicators(void); +void md_rgb_matrix_indicators(void); /*------------------------- Legacy Lighting Support ------------------------*/ diff --git a/tmk_core/protocol/arm_atsam/led_matrix_programs.c b/tmk_core/protocol/arm_atsam/md_rgb_matrix_programs.c similarity index 99% rename from tmk_core/protocol/arm_atsam/led_matrix_programs.c rename to tmk_core/protocol/arm_atsam/md_rgb_matrix_programs.c index 360102ba8455..b43008cc5b52 100644 --- a/tmk_core/protocol/arm_atsam/led_matrix_programs.c +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix_programs.c @@ -17,7 +17,7 @@ along with this program. If not, see . #ifdef USE_MASSDROP_CONFIGURATOR -# include "led_matrix.h" +# include "md_rgb_matrix.h" // Teal <-> Salmon led_setup_t leds_teal_salmon[] = { diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index 2c4bf4b8965c..ea8279d7c31a 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c @@ -54,6 +54,9 @@ #ifdef STM32_EEPROM_ENABLE # include "eeprom_stm32.h" #endif +#ifdef EEPROM_DRIVER +# include "eeprom_driver.h" +#endif #include "suspend.h" #include "wait.h" @@ -154,6 +157,9 @@ int main(void) { #ifdef STM32_EEPROM_ENABLE EEPROM_Init(); #endif +#ifdef EEPROM_DRIVER + eeprom_driver_init(); +#endif // TESTING // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); @@ -234,6 +240,7 @@ int main(void) { /* Remote wakeup */ if (suspend_wakeup_condition()) { usbWakeupHost(&USB_DRIVER); + restart_usb_driver(&USB_DRIVER); } } /* Woken up */ @@ -266,5 +273,8 @@ int main(void) { webusb_task(); #endif + // Run housekeeping + housekeeping_task_kb(); + housekeeping_task_user(); } } diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 037aa077ce12..2ecaaf65dc59 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -184,6 +184,19 @@ const MS_OS_20_Descriptor_t PROGMEM MS_OS_20_Descriptor = MS_OS_20_DESCRIPTOR; const WebUSB_URL_Descriptor_t PROGMEM WebUSB_LandingPage = WEBUSB_URL_DESCRIPTOR(WEBUSB_LANDING_PAGE_URL); #endif +#if STM32_USB_USE_OTG1 +typedef struct { + size_t queue_capacity_in; + size_t queue_capacity_out; + USBInEndpointState in_ep_state; + USBOutEndpointState out_ep_state; + USBInEndpointState int_ep_state; + USBEndpointConfig inout_ep_config; + USBEndpointConfig int_ep_config; + const QMKUSBConfig config; + QMKUSBDriver driver; +} usb_driver_config_t; +#else typedef struct { size_t queue_capacity_in; size_t queue_capacity_out; @@ -196,7 +209,54 @@ typedef struct { const QMKUSBConfig config; QMKUSBDriver driver; } usb_driver_config_t; +#endif +#if STM32_USB_USE_OTG1 +/* Reusable initialization structure - see USBEndpointConfig comment at top of file */ +#define QMK_USB_DRIVER_CONFIG(stream, notification, fixedsize) \ + { \ + .queue_capacity_in = stream##_IN_CAPACITY, .queue_capacity_out = stream##_OUT_CAPACITY, \ + .inout_ep_config = \ + { \ + stream##_IN_MODE, /* Interrupt EP */ \ + NULL, /* SETUP packet notification callback */ \ + qmkusbDataTransmitted, /* IN notification callback */ \ + qmkusbDataReceived, /* OUT notification callback */ \ + stream##_EPSIZE, /* IN maximum packet size */ \ + stream##_EPSIZE, /* OUT maximum packet size */ \ + NULL, /* IN Endpoint state */ \ + NULL, /* OUT endpoint state */ \ + 2, /* IN multiplier */ \ + NULL /* SETUP buffer (not a SETUP endpoint) */ \ + }, \ + .int_ep_config = \ + { \ + USB_EP_MODE_TYPE_INTR, /* Interrupt EP */ \ + NULL, /* SETUP packet notification callback */ \ + qmkusbInterruptTransmitted, /* IN notification callback */ \ + NULL, /* OUT notification callback */ \ + CDC_NOTIFICATION_EPSIZE, /* IN maximum packet size */ \ + 0, /* OUT maximum packet size */ \ + NULL, /* IN Endpoint state */ \ + NULL, /* OUT endpoint state */ \ + 2, /* IN multiplier */ \ + NULL, /* SETUP buffer (not a SETUP endpoint) */ \ + }, \ + .config = { \ + .usbp = &USB_DRIVER, \ + .bulk_in = stream##_IN_EPNUM, \ + .bulk_out = stream##_OUT_EPNUM, \ + .int_in = notification, \ + .in_buffers = stream##_IN_CAPACITY, \ + .out_buffers = stream##_OUT_CAPACITY, \ + .in_size = stream##_EPSIZE, \ + .out_size = stream##_EPSIZE, \ + .fixed_size = fixedsize, \ + .ib = (__attribute__((aligned(4))) uint8_t[BQ_BUFFER_SIZE(stream##_IN_CAPACITY, stream##_EPSIZE)]){}, \ + .ob = (__attribute__((aligned(4))) uint8_t[BQ_BUFFER_SIZE(stream##_OUT_CAPACITY, stream##_EPSIZE)]){}, \ + } \ + } +#else /* Reusable initialization structure - see USBEndpointConfig comment at top of file */ #define QMK_USB_DRIVER_CONFIG(stream, notification, fixedsize) \ { \ @@ -254,6 +314,7 @@ typedef struct { .ob = (__attribute__((aligned(4))) uint8_t[BQ_BUFFER_SIZE(stream##_OUT_CAPACITY, stream##_EPSIZE)]){}, \ } \ } +#endif typedef struct { union { @@ -356,8 +417,12 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { usbInitEndpointI(usbp, SHARED_IN_EPNUM, &shared_ep_config); #endif for (int i = 0; i < NUM_USB_DRIVERS; i++) { + #if STM32_USB_USE_OTG1 + usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].inout_ep_config); + #else usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config); usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config); + #endif if (drivers.array[i].config.int_in) { usbInitEndpointI(usbp, drivers.array[i].config.int_in, &drivers.array[i].int_ep_config); } @@ -603,12 +668,21 @@ static const USBConfig usbcfg = { */ void init_usb_driver(USBDriver *usbp) { for (int i = 0; i < NUM_USB_DRIVERS; i++) { + #if STM32_USB_USE_OTG1 + QMKUSBDriver *driver = &drivers.array[i].driver; + drivers.array[i].inout_ep_config.in_state = &drivers.array[i].in_ep_state; + drivers.array[i].inout_ep_config.out_state = &drivers.array[i].out_ep_state; + drivers.array[i].int_ep_config.in_state = &drivers.array[i].int_ep_state; + qmkusbObjectInit(driver, &drivers.array[i].config); + qmkusbStart(driver, &drivers.array[i].config); + #else QMKUSBDriver *driver = &drivers.array[i].driver; drivers.array[i].in_ep_config.in_state = &drivers.array[i].in_ep_state; drivers.array[i].out_ep_config.out_state = &drivers.array[i].out_ep_state; drivers.array[i].int_ep_config.in_state = &drivers.array[i].int_ep_state; qmkusbObjectInit(driver, &drivers.array[i].config); qmkusbStart(driver, &drivers.array[i].config); + #endif } /* @@ -624,6 +698,13 @@ void init_usb_driver(USBDriver *usbp) { chVTObjectInit(&keyboard_idle_timer); } +void restart_usb_driver(USBDriver *usbp) { + usbStop(usbp); + usbDisconnectBus(usbp); + usbStart(usbp, &usbcfg); + usbConnectBus(usbp); +} + /* --------------------------------------------------------- * Keyboard functions * --------------------------------------------------------- diff --git a/tmk_core/protocol/chibios/usb_main.h b/tmk_core/protocol/chibios/usb_main.h index 94baf9b35e06..d8813f480134 100644 --- a/tmk_core/protocol/chibios/usb_main.h +++ b/tmk_core/protocol/chibios/usb_main.h @@ -35,6 +35,9 @@ /* Initialize the USB driver and bus */ void init_usb_driver(USBDriver *usbp); +/* Restart the USB driver and bus */ +void restart_usb_driver(USBDriver *usbp); + /* --------------- * Keyboard header * --------------- diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 1cd9b1eae1f0..568d1dd501a2 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -1219,6 +1219,10 @@ int main(void) { #if !defined(INTERRUPT_CONTROL_ENDPOINT) USB_USBTask(); #endif + + // Run housekeeping + housekeeping_task_kb(); + housekeeping_task_user(); } } diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 764824f4dc24..1d5a62aaa1bb 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -44,6 +44,10 @@ #endif #include "usb_descriptor_common.h" +#ifdef JOYSTICK_ENABLE +# include "joystick.h" +#endif + // clang-format off /* @@ -317,10 +321,17 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = { HID_RI_USAGE(8, 0x35), // Rz # endif # if JOYSTICK_AXES_COUNT >= 1 - HID_RI_LOGICAL_MINIMUM(8, -127), - HID_RI_LOGICAL_MAXIMUM(8, 127), + # if JOYSTICK_AXES_RESOLUTION == 8 + HID_RI_LOGICAL_MINIMUM(8, -JOYSTICK_RESOLUTION), + HID_RI_LOGICAL_MAXIMUM(8, JOYSTICK_RESOLUTION), HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), HID_RI_REPORT_SIZE(8, 0x08), + # else + HID_RI_LOGICAL_MINIMUM(16, -JOYSTICK_RESOLUTION), + HID_RI_LOGICAL_MAXIMUM(16, JOYSTICK_RESOLUTION), + HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), + HID_RI_REPORT_SIZE(8, 0x10), + # endif HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), # endif diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h index 41579065448e..ac897720f59b 100644 --- a/tmk_core/protocol/usb_descriptor.h +++ b/tmk_core/protocol/usb_descriptor.h @@ -218,7 +218,11 @@ enum usb_endpoints { #ifdef RAW_ENABLE RAW_IN_EPNUM = NEXT_EPNUM, + #if STM32_USB_USE_OTG1 + #define RAW_OUT_EPNUM RAW_IN_EPNUM + #else RAW_OUT_EPNUM = NEXT_EPNUM, + #endif #endif #ifdef SHARED_EP_ENABLE @@ -232,7 +236,11 @@ enum usb_endpoints { // ChibiOS has enough memory and descriptor to actually enable the endpoint // It could use the same endpoint numbers, as that's supported by ChibiOS // But the QMK code currently assumes that the endpoint numbers are different + #if STM32_USB_USE_OTG1 + #define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM + #else CONSOLE_OUT_EPNUM = NEXT_EPNUM, + #endif # else # define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM # endif @@ -240,13 +248,21 @@ enum usb_endpoints { #ifdef MIDI_ENABLE MIDI_STREAM_IN_EPNUM = NEXT_EPNUM, + #if STM32_USB_USE_OTG1 + #define MIDI_STREAM_OUT_EPNUM MIDI_STREAM_IN_EPNUM + #else MIDI_STREAM_OUT_EPNUM = NEXT_EPNUM, + #endif #endif #ifdef VIRTSER_ENABLE CDC_NOTIFICATION_EPNUM = NEXT_EPNUM, CDC_IN_EPNUM = NEXT_EPNUM, + #if STM32_USB_USE_OTG1 + #define CDC_OUT_EPNUM CDC_IN_EPNUM + #else CDC_OUT_EPNUM = NEXT_EPNUM, + #endif #endif #ifdef WEBUSB_ENABLE @@ -257,7 +273,11 @@ enum usb_endpoints { #endif #ifdef JOYSTICK_ENABLE JOYSTICK_IN_EPNUM = NEXT_EPNUM, + #if STM32_USB_USE_OTG1 + JOYSTICK_OUT_EPNUM = JOYSTICK_IN_EPNUM, + #else JOYSTICK_OUT_EPNUM = NEXT_EPNUM, + #endif #endif }; diff --git a/tmk_core/protocol/vusb/main.c b/tmk_core/protocol/vusb/main.c index a57df5ce06a7..0e3447d926d1 100644 --- a/tmk_core/protocol/vusb/main.c +++ b/tmk_core/protocol/vusb/main.c @@ -153,6 +153,10 @@ int main(void) { console_task(); } #endif + + // Run housekeeping + housekeeping_task_kb(); + housekeeping_task_user(); } else if (suspend_wakeup_condition()) { usb_remote_wakeup(); }