summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrashna Jael're <drashna@live.com>2021-12-07 09:27:44 -0800
committerDrashna Jael're <drashna@live.com>2021-12-07 09:27:44 -0800
commit7c18b1c9d3d968ded45e072af3483547c3ec7859 (patch)
treeed7c8a4176033046eacff21228364290b44fcfdb
parent43002bdf77ab0f48af6b04e87edcc37f7cb7b905 (diff)
parent6d0a62920410f50d7f6707960ca1ca0c8fd1d1fa (diff)
Merge commit '6d0a62920410f50d7f6707960ca1ca0c8fd1d1fa' into firmware21
-rw-r--r--.github/labeler.yml1
-rw-r--r--.github/workflows/cli.yml3
-rw-r--r--.github/workflows/format.yaml23
-rw-r--r--.github/workflows/format_push.yaml49
-rw-r--r--.github/workflows/unit_test.yml30
-rw-r--r--.gitignore5
-rw-r--r--.gitmodules4
-rw-r--r--Makefile46
-rwxr-xr-xbin/qmk58
-rw-r--r--build_full_test.mk23
-rw-r--r--build_keyboard.mk66
-rw-r--r--build_test.mk32
-rw-r--r--builddefs/bootloader.mk (renamed from bootloader.mk)9
-rw-r--r--builddefs/disable_features.mk (renamed from disable_features.mk)3
-rw-r--r--builddefs/generic_features.mk52
-rw-r--r--builddefs/mcu_selection.mk (renamed from quantum/mcu_selection.mk)124
-rw-r--r--builddefs/message.mk (renamed from message.mk)0
-rw-r--r--builddefs/show_options.mk (renamed from show_options.mk)12
-rw-r--r--common_features.mk274
-rw-r--r--data/mappings/info_config.json3
-rw-r--r--data/schemas/keyboard.jsonschema5
-rw-r--r--data/schemas/keymap.jsonschema35
-rw-r--r--data/templates/avr/config.h22
-rw-r--r--data/templates/avr/readme.md10
-rw-r--r--data/templates/avr/rules.mk2
-rw-r--r--data/templates/base/%(KEYBOARD)s.c4
-rw-r--r--data/templates/base/%(KEYBOARD)s.h22
-rw-r--r--data/templates/base/info.json4
-rw-r--r--data/templates/base/keymaps/default/keymap.c51
-rw-r--r--data/templates/base/keymaps/default/readme.md2
-rw-r--r--data/templates/ps2avrgb/config.h22
-rw-r--r--data/templates/ps2avrgb/readme.md10
-rw-r--r--data/templates/ps2avrgb/rules.mk2
-rw-r--r--doxygen-todo14
-rw-r--r--drivers/bluetooth/adafruit_ble.cpp (renamed from tmk_core/protocol/lufa/adafruit_ble.cpp)44
-rw-r--r--drivers/bluetooth/adafruit_ble.h (renamed from tmk_core/protocol/lufa/adafruit_ble.h)0
-rw-r--r--drivers/bluetooth/outputselect.c (renamed from tmk_core/protocol/lufa/outputselect.c)0
-rw-r--r--drivers/bluetooth/outputselect.h (renamed from tmk_core/protocol/lufa/outputselect.h)0
-rw-r--r--drivers/bluetooth/ringbuffer.hpp (renamed from tmk_core/protocol/lufa/ringbuffer.hpp)0
-rw-r--r--drivers/haptic/solenoid.c16
-rw-r--r--drivers/haptic/solenoid.h8
-rw-r--r--drivers/led/apa102.c4
-rw-r--r--drivers/led/aw20216.c3
-rw-r--r--drivers/led/aw20216.h2
-rw-r--r--drivers/led/ckled2001.c228
-rw-r--r--drivers/led/ckled2001.h339
-rw-r--r--drivers/led/issi/is31fl3731-simple.c13
-rw-r--r--drivers/led/issi/is31fl3731-simple.h2
-rw-r--r--drivers/led/issi/is31fl3731.c13
-rw-r--r--drivers/led/issi/is31fl3731.h2
-rw-r--r--drivers/led/issi/is31fl3733.c25
-rw-r--r--drivers/led/issi/is31fl3733.h11
-rw-r--r--drivers/led/issi/is31fl3736.c19
-rw-r--r--drivers/led/issi/is31fl3736.h12
-rw-r--r--drivers/led/issi/is31fl3737.c19
-rw-r--r--drivers/led/issi/is31fl3737.h12
-rw-r--r--drivers/led/issi/is31fl3741.c16
-rw-r--r--drivers/led/issi/is31fl3741.h11
-rw-r--r--drivers/oled/oled_driver.h4
-rw-r--r--drivers/oled/ssd1306_sh1106.c10
-rw-r--r--drivers/ps2/ps2.h (renamed from tmk_core/protocol/ps2.h)0
-rw-r--r--drivers/ps2/ps2_busywait.c (renamed from tmk_core/protocol/ps2_busywait.c)0
-rw-r--r--drivers/ps2/ps2_interrupt.c (renamed from tmk_core/protocol/ps2_interrupt.c)18
-rw-r--r--drivers/ps2/ps2_io.h (renamed from tmk_core/protocol/ps2_io.h)0
-rw-r--r--drivers/ps2/ps2_mouse.c (renamed from tmk_core/protocol/ps2_mouse.c)10
-rw-r--r--drivers/ps2/ps2_mouse.h (renamed from tmk_core/protocol/ps2_mouse.h)0
-rw-r--r--drivers/qwiic/micro_oled.c482
-rw-r--r--drivers/qwiic/micro_oled.h134
-rw-r--r--drivers/qwiic/qwiic.mk17
-rw-r--r--drivers/qwiic/util/font5x7.h39
-rw-r--r--drivers/qwiic/util/font8x16.h39
-rw-r--r--drivers/sensors/adns5050.c166
-rw-r--r--drivers/sensors/adns5050.h75
-rw-r--r--drivers/sensors/adns9800.c201
-rw-r--r--drivers/sensors/adns9800.h42
-rw-r--r--drivers/sensors/adns9800_srom_A6.h3268
-rw-r--r--drivers/sensors/analog_joystick.c94
-rw-r--r--drivers/sensors/analog_joystick.h51
-rw-r--r--drivers/sensors/cirque_pinnacle.c232
-rw-r--r--drivers/sensors/cirque_pinnacle.h74
-rw-r--r--drivers/sensors/cirque_pinnacle_i2c.c43
-rw-r--r--drivers/sensors/cirque_pinnacle_spi.c52
-rw-r--r--drivers/sensors/pimoroni_trackball.c187
-rw-r--r--drivers/sensors/pimoroni_trackball.h48
-rw-r--r--drivers/sensors/pmw3360.c46
-rw-r--r--drivers/sensors/pmw3360.h43
-rw-r--r--drivers/sensors/pmw3360_firmware.h542
-rw-r--r--drivers/sensors/pmw3389_firmware.h303
-rw-r--r--drivers/ugfx/gdisp/is31fl3731c/board_is31fl3731c_template.h105
-rw-r--r--drivers/ugfx/gdisp/is31fl3731c/driver.mk3
-rw-r--r--drivers/ugfx/gdisp/is31fl3731c/gdisp_is31fl3731c.c302
-rw-r--r--drivers/ugfx/gdisp/is31fl3731c/gdisp_lld_config.h36
-rw-r--r--drivers/ugfx/gdisp/st7565/board_st7565_template.h96
-rw-r--r--drivers/ugfx/gdisp/st7565/driver.mk3
-rw-r--r--drivers/ugfx/gdisp/st7565/gdisp_lld_ST7565.c314
-rw-r--r--drivers/ugfx/gdisp/st7565/gdisp_lld_config.h27
-rw-r--r--drivers/ugfx/gdisp/st7565/st7565.h39
-rw-r--r--drivers/usb2422.c (renamed from tmk_core/protocol/arm_atsam/usb/usb2422.h)216
-rw-r--r--drivers/usb2422.h59
-rw-r--r--drivers/ws2812.h32
-rw-r--r--keyboards/ergodox_ez/config.h48
-rw-r--r--keyboards/ergodox_ez/ergodox_ez.c2
-rw-r--r--keyboards/ergodox_ez/rules.mk2
-rw-r--r--keyboards/moonlander/config.h48
-rw-r--r--keyboards/moonlander/moonlander.c6
-rw-r--r--keyboards/moonlander/rules.mk2
-rw-r--r--keyboards/planck/config.h5
-rw-r--r--keyboards/planck/ez/config.h53
-rw-r--r--keyboards/planck/ez/ez.c2
-rwxr-xr-xkeyboards/planck/ez/rules.mk3
m---------lib/chibios0
m---------lib/chibios-contrib0
-rw-r--r--lib/python/qmk/cli/__init__.py4
-rwxr-xr-xlib/python/qmk/cli/cd.py46
-rw-r--r--lib/python/qmk/cli/console.py303
-rw-r--r--lib/python/qmk/cli/docs.py32
-rw-r--r--lib/python/qmk/cli/doctor/check.py1
-rw-r--r--lib/python/qmk/cli/flash.py14
-rw-r--r--lib/python/qmk/cli/format/c.py2
-rwxr-xr-xlib/python/qmk/cli/format/python.py67
-rw-r--r--lib/python/qmk/cli/format/text.py64
-rwxr-xr-xlib/python/qmk/cli/generate/compilation_database.py133
-rwxr-xr-xlib/python/qmk/cli/generate/develop_pr_list.py119
-rw-r--r--lib/python/qmk/cli/generate/dfu_header.py2
-rwxr-xr-xlib/python/qmk/cli/generate/rules_mk.py9
-rwxr-xr-xlib/python/qmk/cli/json2c.py2
-rw-r--r--lib/python/qmk/cli/lint.py145
-rw-r--r--lib/python/qmk/cli/list/keymaps.py5
-rw-r--r--lib/python/qmk/cli/list/layouts.py5
-rw-r--r--lib/python/qmk/cli/new/keyboard.py79
-rw-r--r--lib/python/qmk/cli/pytest.py2
-rw-r--r--lib/python/qmk/commands.py18
-rw-r--r--lib/python/qmk/constants.py2
-rw-r--r--lib/python/qmk/info.py17
-rw-r--r--lib/python/qmk/keymap.py100
-rw-r--r--lib/python/qmk/tests/minimal_info.json2
-rw-r--r--lib/python/qmk/tests/test_cli_commands.py22
-rw-r--r--lib/python/qmk/tests/test_qmk_keymap.py8
m---------lib/ugfx0
-rw-r--r--paths.mk (renamed from common.mk)9
-rw-r--r--platforms/arm_atsam/_timer.h (renamed from tmk_core/common/arm_atsam/_timer.h)0
-rw-r--r--platforms/arm_atsam/_wait.h (renamed from tmk_core/common/arm_atsam/_wait.h)0
-rw-r--r--platforms/arm_atsam/atomic_util.h (renamed from tmk_core/common/arm_atsam/atomic_util.h)0
-rw-r--r--platforms/arm_atsam/bootloader.c (renamed from tmk_core/common/arm_atsam/bootloader.c)0
-rw-r--r--platforms/arm_atsam/eeprom.c (renamed from tmk_core/common/arm_atsam/eeprom.c)94
-rw-r--r--platforms/arm_atsam/flash.mk11
-rw-r--r--platforms/arm_atsam/gpio.h (renamed from tmk_core/common/arm_atsam/gpio.h)8
-rw-r--r--platforms/arm_atsam/pin_defs.h (renamed from tmk_core/common/arm_atsam/pin_defs.h)0
-rw-r--r--platforms/arm_atsam/platform.c (renamed from tmk_core/common/arm_atsam/platform.c)0
-rw-r--r--platforms/arm_atsam/platform.mk (renamed from tmk_core/arm_atsam.mk)2
-rw-r--r--platforms/arm_atsam/platform_deps.h (renamed from tmk_core/common/arm_atsam/platform_deps.h)0
-rw-r--r--platforms/arm_atsam/suspend.c (renamed from tmk_core/common/arm_atsam/suspend.c)0
-rw-r--r--platforms/arm_atsam/timer.c (renamed from tmk_core/common/arm_atsam/timer.c)0
-rw-r--r--platforms/atomic_util.h (renamed from tmk_core/common/atomic_util.h)0
-rw-r--r--platforms/avr/_print.h (renamed from tmk_core/common/avr/_print.h)0
-rw-r--r--platforms/avr/_timer.h (renamed from tmk_core/common/avr/_timer.h)0
-rw-r--r--platforms/avr/_wait.h (renamed from tmk_core/common/avr/_wait.h)0
-rw-r--r--platforms/avr/atomic_util.h (renamed from tmk_core/common/avr/atomic_util.h)0
-rw-r--r--platforms/avr/bootloader.c (renamed from tmk_core/common/avr/bootloader.c)0
-rw-r--r--platforms/avr/bootloader_size.c (renamed from tmk_core/common/avr/bootloader_size.c)0
-rw-r--r--platforms/avr/drivers/analog.c23
-rw-r--r--platforms/avr/drivers/analog.h3
-rw-r--r--platforms/avr/drivers/audio_pwm.h (renamed from quantum/audio/driver_avr_pwm.h)0
-rw-r--r--platforms/avr/drivers/audio_pwm_hardware.c (renamed from quantum/audio/driver_avr_pwm_hardware.c)0
-rw-r--r--platforms/avr/drivers/i2c_master.c56
-rw-r--r--platforms/avr/drivers/i2c_master.h2
-rw-r--r--platforms/avr/drivers/ps2/ps2_io.c51
-rw-r--r--platforms/avr/drivers/ps2/ps2_usart.c (renamed from tmk_core/protocol/ps2_usart.c)14
-rw-r--r--platforms/avr/drivers/uart.c26
-rw-r--r--platforms/avr/drivers/uart.h8
-rw-r--r--platforms/avr/drivers/ws2812.c11
-rw-r--r--platforms/avr/flash.mk9
-rw-r--r--platforms/avr/gpio.h (renamed from tmk_core/common/avr/gpio.h)0
-rw-r--r--platforms/avr/pin_defs.h (renamed from tmk_core/common/avr/pin_defs.h)0
-rw-r--r--platforms/avr/platform.c (renamed from tmk_core/common/avr/platform.c)0
-rw-r--r--platforms/avr/platform.mk (renamed from tmk_core/avr.mk)4
-rw-r--r--platforms/avr/platform_deps.h (renamed from tmk_core/common/avr/platform_deps.h)0
-rw-r--r--platforms/avr/printf.c (renamed from tmk_core/common/avr/printf.c)0
-rw-r--r--platforms/avr/printf.mk (renamed from tmk_core/common/avr/printf.mk)0
-rw-r--r--platforms/avr/sleep_led.c (renamed from tmk_core/common/avr/sleep_led.c)0
-rw-r--r--platforms/avr/suspend.c (renamed from tmk_core/common/avr/suspend.c)98
-rw-r--r--platforms/avr/timer.c (renamed from tmk_core/common/avr/timer.c)0
-rw-r--r--platforms/avr/timer_avr.h (renamed from tmk_core/common/avr/timer_avr.h)0
-rw-r--r--platforms/avr/xprintf.S (renamed from tmk_core/common/avr/xprintf.S)0
-rw-r--r--platforms/avr/xprintf.h (renamed from tmk_core/common/avr/xprintf.h)0
-rw-r--r--platforms/bootloader.h (renamed from tmk_core/common/bootloader.h)0
-rw-r--r--platforms/chibios/_timer.h (renamed from tmk_core/common/chibios/_timer.h)0
-rw-r--r--platforms/chibios/_wait.c (renamed from tmk_core/common/chibios/_wait.c)0
-rw-r--r--platforms/chibios/_wait.h (renamed from tmk_core/common/chibios/_wait.h)2
-rw-r--r--platforms/chibios/atomic_util.h (renamed from tmk_core/common/chibios/atomic_util.h)0
-rw-r--r--platforms/chibios/boards/BLACKPILL_STM32_F401/configs/mcuconf.h71
-rw-r--r--platforms/chibios/boards/BLACKPILL_STM32_F411/configs/mcuconf.h65
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_F405XG/board/board.mk9
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_F405XG/configs/board.h28
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_F405XG/configs/config.h (renamed from drivers/qwiic/qwiic.c)22
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_F405XG/configs/mcuconf.h352
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_F407XE/configs/mcuconf.h3
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_F446XE/configs/mcuconf.h108
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_G431XB/configs/mcuconf.h15
-rw-r--r--platforms/chibios/boards/GENERIC_STM32_G474XE/configs/mcuconf.h15
-rw-r--r--platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.c82
-rw-r--r--platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.h56
-rw-r--r--platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.mk9
-rw-r--r--platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/bootloader_defs.h12
-rw-r--r--platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/chconf.h (renamed from quantum/api/api_sysex.h)15
-rw-r--r--platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/config.h20
-rw-r--r--platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/mcuconf.h168
-rw-r--r--platforms/chibios/boards/QMK_PROTON_C/configs/chconf.h2
-rw-r--r--platforms/chibios/boards/QMK_PROTON_C/configs/config.h9
-rw-r--r--platforms/chibios/boards/SIPEED_LONGAN_NANO/board/board.mk9
-rw-r--r--platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/chconf.h (renamed from quantum/visualizer/visualizer_keyframes.c)14
-rw-r--r--platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/mcuconf.h302
-rw-r--r--platforms/chibios/boards/common/configs/chconf.h2
-rw-r--r--platforms/chibios/boards/common/ld/STM32F401xC.ld85
-rw-r--r--platforms/chibios/boards/common/ld/STM32F401xE.ld85
-rw-r--r--platforms/chibios/boards/common/ld/STM32F405xG.ld86
-rw-r--r--platforms/chibios/boards/common/ld/STM32F411xE.ld85
-rw-r--r--platforms/chibios/bootloader.c (renamed from tmk_core/common/chibios/bootloader.c)22
-rw-r--r--platforms/chibios/chibios_config.h90
-rw-r--r--platforms/chibios/drivers/analog.c10
-rw-r--r--platforms/chibios/drivers/audio_dac.h (renamed from quantum/audio/driver_chibios_dac.h)0
-rw-r--r--platforms/chibios/drivers/audio_dac_additive.c (renamed from quantum/audio/driver_chibios_dac_additive.c)0
-rw-r--r--platforms/chibios/drivers/audio_dac_basic.c (renamed from quantum/audio/driver_chibios_dac_basic.c)0
-rw-r--r--platforms/chibios/drivers/audio_pwm.h (renamed from quantum/audio/driver_chibios_pwm.h)0
-rw-r--r--platforms/chibios/drivers/audio_pwm_hardware.c (renamed from quantum/audio/driver_chibios_pwm_hardware.c)4
-rw-r--r--platforms/chibios/drivers/audio_pwm_software.c (renamed from quantum/audio/driver_chibios_pwm_software.c)0
-rw-r--r--platforms/chibios/drivers/i2c_master.c40
-rw-r--r--platforms/chibios/drivers/i2c_master.h27
-rw-r--r--platforms/chibios/drivers/ps2/ps2_io.c55
-rw-r--r--platforms/chibios/drivers/serial.c2
-rw-r--r--platforms/chibios/drivers/serial_usart.c10
-rw-r--r--platforms/chibios/drivers/spi_master.c64
-rw-r--r--platforms/chibios/drivers/spi_master.h6
-rw-r--r--platforms/chibios/drivers/uart.c20
-rw-r--r--platforms/chibios/drivers/uart.h24
-rw-r--r--platforms/chibios/drivers/ws2812.c33
-rw-r--r--platforms/chibios/drivers/ws2812_pwm.c50
-rw-r--r--platforms/chibios/drivers/ws2812_spi.c29
-rw-r--r--platforms/chibios/drivers/wt_rgb_backlight.c18
-rw-r--r--platforms/chibios/eeprom_stm32.c (renamed from tmk_core/common/chibios/eeprom_stm32.c)57
-rw-r--r--platforms/chibios/eeprom_stm32.h (renamed from tmk_core/common/chibios/eeprom_stm32.h)0
-rw-r--r--platforms/chibios/eeprom_stm32_defs.h (renamed from tmk_core/common/chibios/eeprom_stm32_defs.h)25
-rw-r--r--platforms/chibios/eeprom_teensy.c (renamed from tmk_core/common/chibios/eeprom_teensy.c)213
-rw-r--r--platforms/chibios/flash.mk18
-rw-r--r--platforms/chibios/flash_stm32.c (renamed from tmk_core/common/chibios/flash_stm32.c)48
-rw-r--r--platforms/chibios/flash_stm32.h (renamed from tmk_core/common/chibios/flash_stm32.h)0
-rw-r--r--platforms/chibios/gd32v_compatibility.h120
-rw-r--r--platforms/chibios/gpio.h (renamed from tmk_core/common/chibios/gpio.h)0
-rw-r--r--platforms/chibios/pin_defs.h (renamed from tmk_core/common/chibios/pin_defs.h)0
-rw-r--r--platforms/chibios/platform.c (renamed from tmk_core/common/chibios/platform.c)0
-rw-r--r--platforms/chibios/platform.mk (renamed from tmk_core/chibios.mk)329
-rw-r--r--platforms/chibios/platform_deps.h (renamed from tmk_core/common/chibios/platform_deps.h)0
-rw-r--r--platforms/chibios/sleep_led.c (renamed from tmk_core/common/chibios/sleep_led.c)4
-rw-r--r--platforms/chibios/suspend.c92
-rw-r--r--platforms/chibios/syscall-fallbacks.c (renamed from tmk_core/common/chibios/syscall-fallbacks.c)7
-rw-r--r--platforms/chibios/timer.c (renamed from tmk_core/common/chibios/timer.c)0
-rw-r--r--platforms/chibios/wait.c (renamed from tmk_core/common/chibios/wait.c)0
-rw-r--r--platforms/common.mk12
-rw-r--r--platforms/eeprom.h (renamed from tmk_core/common/eeprom.h)0
-rw-r--r--platforms/gpio.h (renamed from tmk_core/common/gpio.h)0
-rw-r--r--platforms/pin_defs.h (renamed from tmk_core/common/pin_defs.h)0
-rw-r--r--platforms/progmem.h (renamed from tmk_core/common/progmem.h)1
-rw-r--r--platforms/sleep_led.h (renamed from tmk_core/common/sleep_led.h)0
-rw-r--r--platforms/suspend.h (renamed from tmk_core/common/suspend.h)2
-rw-r--r--platforms/test/_wait.h (renamed from tmk_core/common/test/_wait.h)0
-rw-r--r--platforms/test/bootloader.c (renamed from tmk_core/common/test/bootloader.c)0
-rw-r--r--platforms/test/eeprom.c (renamed from tmk_core/common/test/eeprom.c)0
-rw-r--r--platforms/test/eeprom_stm32_tests.cpp (renamed from tmk_core/common/test/eeprom_stm32_tests.cpp)0
-rw-r--r--platforms/test/flash_stm32_mock.c (renamed from tmk_core/common/test/flash_stm32_mock.c)0
-rw-r--r--platforms/test/hal.h (renamed from tmk_core/common/test/hal.h)0
-rw-r--r--platforms/test/platform.c (renamed from tmk_core/common/test/platform.c)0
-rw-r--r--platforms/test/platform.h (renamed from tmk_core/common/test/platform.h)0
-rw-r--r--platforms/test/platform.mk (renamed from tmk_core/native.mk)2
-rw-r--r--platforms/test/platform_deps.h (renamed from tmk_core/common/test/platform_deps.h)0
-rw-r--r--platforms/test/rules.mk (renamed from tmk_core/common/test/rules.mk)9
-rw-r--r--platforms/test/suspend.c (renamed from tmk_core/common/test/suspend.c)0
-rw-r--r--platforms/test/testlist.mk (renamed from tmk_core/common/test/testlist.mk)0
-rw-r--r--platforms/test/timer.c (renamed from tmk_core/common/test/timer.c)0
-rw-r--r--platforms/timer.h (renamed from tmk_core/common/timer.h)0
-rw-r--r--platforms/wait.h (renamed from tmk_core/common/wait.h)0
-rw-r--r--platforms/webusb.c (renamed from tmk_core/common/webusb.c)0
-rw-r--r--platforms/webusb.h (renamed from tmk_core/common/webusb.h)0
-rw-r--r--quantum/action.c325
-rw-r--r--quantum/action.h2
-rw-r--r--quantum/action_tapping.c150
-rw-r--r--quantum/action_tapping.h4
-rw-r--r--quantum/action_util.c3
-rw-r--r--quantum/api.c182
-rw-r--r--quantum/api.h55
-rw-r--r--quantum/api/api_sysex.c72
-rw-r--r--quantum/audio/audio.h13
-rw-r--r--quantum/audio/song_list.h8
-rw-r--r--quantum/backlight/backlight_avr.c88
-rw-r--r--quantum/backlight/backlight_chibios.c10
-rw-r--r--quantum/config_common.h3
-rw-r--r--quantum/debounce/asym_eager_defer_pk.c22
-rw-r--r--quantum/debounce/sym_defer_g.c2
-rw-r--r--quantum/debounce/sym_defer_pk.c6
-rw-r--r--quantum/debounce/sym_eager_pk.c8
-rw-r--r--quantum/debounce/sym_eager_pr.c8
-rw-r--r--quantum/debounce/tests/asym_eager_defer_pk_tests.cpp66
-rw-r--r--quantum/debounce/tests/debounce_test_common.cpp72
-rw-r--r--quantum/debounce/tests/debounce_test_common.h24
-rw-r--r--quantum/debounce/tests/rules.mk2
-rw-r--r--quantum/debounce/tests/sym_defer_g_tests.cpp45
-rw-r--r--quantum/debounce/tests/sym_defer_pk_tests.cpp45
-rw-r--r--quantum/debounce/tests/sym_eager_pk_tests.cpp48
-rw-r--r--quantum/debounce/tests/sym_eager_pr_tests.cpp57
-rw-r--r--quantum/deferred_exec.c152
-rw-r--r--quantum/deferred_exec.h38
-rw-r--r--quantum/dynamic_keymap.c6
-rw-r--r--quantum/eeconfig.c11
-rw-r--r--quantum/eeconfig.h26
-rw-r--r--quantum/encoder/tests/encoder_tests.cpp144
-rw-r--r--quantum/encoder/tests/encoder_tests_split.cpp143
-rw-r--r--quantum/encoder/tests/mock.c34
-rw-r--r--quantum/encoder/tests/mock.h (renamed from quantum/visualizer/default_animations.h)29
-rw-r--r--quantum/encoder/tests/mock_split.c36
-rw-r--r--quantum/encoder/tests/mock_split.h48
-rw-r--r--quantum/encoder/tests/rules.mk13
-rw-r--r--quantum/encoder/tests/testlist.mk3
-rw-r--r--quantum/haptic.c51
-rw-r--r--quantum/haptic.h27
-rw-r--r--quantum/keyboard.c70
-rw-r--r--quantum/keycode.h272
-rw-r--r--quantum/keycode_config.c66
-rw-r--r--quantum/keycode_legacy.h53
-rw-r--r--quantum/keymap_common.c4
-rw-r--r--quantum/keymap_extras/keymap_korean.h4
-rw-r--r--quantum/keymap_extras/keymap_steno.h3
-rw-r--r--quantum/keymap_extras/keymap_turkish_f.h2
-rw-r--r--quantum/led_matrix/animations/alpha_mods_anim.h4
-rw-r--r--quantum/led_matrix/animations/band_anim.h2
-rw-r--r--quantum/led_matrix/animations/band_pinwheel_anim.h2
-rw-r--r--quantum/led_matrix/animations/band_spiral_anim.h2
-rw-r--r--quantum/led_matrix/animations/breathing_anim.h4
-rw-r--r--quantum/led_matrix/animations/cycle_left_right_anim.h2
-rw-r--r--quantum/led_matrix/animations/cycle_out_in_anim.h2
-rw-r--r--quantum/led_matrix/animations/cycle_up_down_anim.h2
-rw-r--r--quantum/led_matrix/animations/dual_beacon_anim.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_dx_dy.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_i.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_reactive.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h2
-rw-r--r--quantum/led_matrix/animations/solid_anim.h2
-rw-r--r--quantum/led_matrix/animations/solid_reactive_cross.h4
-rw-r--r--quantum/led_matrix/animations/solid_reactive_nexus.h2
-rw-r--r--quantum/led_matrix/animations/solid_reactive_simple_anim.h2
-rw-r--r--quantum/led_matrix/animations/solid_reactive_wide.h4
-rw-r--r--quantum/led_matrix/animations/solid_splash_anim.h4
-rw-r--r--quantum/led_matrix/animations/wave_left_right_anim.h2
-rw-r--r--quantum/led_matrix/animations/wave_up_down_anim.h2
-rw-r--r--quantum/led_matrix/led_matrix.c50
-rw-r--r--quantum/led_matrix/led_matrix.h46
-rw-r--r--quantum/led_matrix/led_matrix_drivers.c133
-rw-r--r--quantum/led_matrix/led_matrix_legacy_enables.h82
-rw-r--r--quantum/main.c36
-rw-r--r--quantum/matrix.c51
-rw-r--r--quantum/pointing_device.c124
-rw-r--r--quantum/pointing_device.h59
-rw-r--r--quantum/pointing_device_drivers.c262
-rw-r--r--quantum/process_keycode/process_auto_shift.c427
-rw-r--r--quantum/process_keycode/process_auto_shift.h22
-rw-r--r--quantum/process_keycode/process_combo.c184
-rw-r--r--quantum/process_keycode/process_combo.h4
-rw-r--r--quantum/process_keycode/process_dynamic_tapping_term.c50
-rw-r--r--quantum/process_keycode/process_dynamic_tapping_term.h (renamed from drivers/qwiic/qwiic.h)16
-rw-r--r--quantum/process_keycode/process_haptic.c30
-rw-r--r--quantum/process_keycode/process_music.c6
-rw-r--r--quantum/process_keycode/process_printer.c32
-rw-r--r--quantum/process_keycode/process_printer_bb.c32
-rw-r--r--quantum/process_keycode/process_programmable_button.c31
-rw-r--r--quantum/process_keycode/process_programmable_button.h (renamed from tmk_core/protocol/serial_mouse.h)12
-rw-r--r--quantum/process_keycode/process_space_cadet.c24
-rw-r--r--quantum/process_keycode/process_steno.c9
-rw-r--r--quantum/process_keycode/process_terminal.c10
-rw-r--r--quantum/process_keycode/process_ucis.c18
-rw-r--r--quantum/process_keycode/process_unicode_common.c54
-rw-r--r--quantum/process_keycode/process_unicode_common.h4
-rw-r--r--quantum/programmable_button.c37
-rw-r--r--quantum/programmable_button.h30
-rw-r--r--quantum/quantum.c205
-rw-r--r--quantum/quantum.h22
-rw-r--r--quantum/quantum_keycodes.h203
-rw-r--r--quantum/raw_hid.h (renamed from tmk_core/common/raw_hid.h)0
-rw-r--r--quantum/rgb_matrix/animations/alpha_mods_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/breathing_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_sat_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_spiral_val_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_val_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_all_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_left_right_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_out_in_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_pinwheel_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_spiral_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_up_down_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/digital_rain_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/dual_beacon_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/gradient_left_right_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/gradient_up_down_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/hue_breathing_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/jellybean_raindrops_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/pixel_fractal_anim.h74
-rw-r--r--quantum/rgb_matrix/animations/pixel_rain_anim.h48
-rw-r--r--quantum/rgb_matrix/animations/rainbow_beacon_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/raindrops_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/rgb_matrix_effects.inc2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_i.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_reactive.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h2
-rw-r--r--quantum/rgb_matrix/animations/solid_color_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_cross.h12
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_nexus.h12
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_simple_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_wide.h12
-rw-r--r--quantum/rgb_matrix/animations/solid_splash_anim.h12
-rw-r--r--quantum/rgb_matrix/animations/splash_anim.h12
-rw-r--r--quantum/rgb_matrix/animations/typing_heatmap_anim.h2
-rw-r--r--quantum/rgb_matrix/rgb_matrix.c41
-rw-r--r--quantum/rgb_matrix/rgb_matrix.h48
-rw-r--r--quantum/rgb_matrix/rgb_matrix_drivers.c184
-rw-r--r--quantum/rgb_matrix/rgb_matrix_legacy_enables.h153
-rw-r--r--quantum/sequencer/tests/rules.mk4
-rw-r--r--quantum/serial_link/LICENSE19
-rw-r--r--quantum/serial_link/README.md1
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.c135
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.h34
-rw-r--r--quantum/serial_link/protocol/frame_router.c64
-rw-r--r--quantum/serial_link/protocol/frame_router.h35
-rw-r--r--quantum/serial_link/protocol/frame_validator.c57
-rw-r--r--quantum/serial_link/protocol/frame_validator.h31
-rw-r--r--quantum/serial_link/protocol/physical.h27
-rw-r--r--quantum/serial_link/protocol/transport.c121
-rw-r--r--quantum/serial_link/protocol/transport.h139
-rw-r--r--quantum/serial_link/protocol/triple_buffered_object.c77
-rw-r--r--quantum/serial_link/protocol/triple_buffered_object.h44
-rw-r--r--quantum/serial_link/system/serial_link.c250
-rw-r--r--quantum/serial_link/system/serial_link.h54
-rw-r--r--quantum/serial_link/tests/Makefile61
-rw-r--r--quantum/serial_link/tests/byte_stuffer_tests.cpp450
-rw-r--r--quantum/serial_link/tests/frame_router_tests.cpp204
-rw-r--r--quantum/serial_link/tests/frame_validator_tests.cpp100
-rw-r--r--quantum/serial_link/tests/rules.mk22
-rw-r--r--quantum/serial_link/tests/testlist.mk6
-rw-r--r--quantum/serial_link/tests/transport_tests.cpp184
-rw-r--r--quantum/serial_link/tests/triple_buffered_object_tests.cpp80
-rw-r--r--quantum/split_common/transactions.c48
-rw-r--r--quantum/sync_timer.c (renamed from tmk_core/common/sync_timer.c)2
-rw-r--r--quantum/sync_timer.h (renamed from tmk_core/common/sync_timer.h)2
-rw-r--r--quantum/via.c2
-rw-r--r--quantum/via_ensure_keycode.h670
-rw-r--r--quantum/virtser.h (renamed from tmk_core/common/virtser.h)2
-rw-r--r--quantum/visualizer/LICENSE.md29
-rw-r--r--quantum/visualizer/common_gfxconf.h354
-rw-r--r--quantum/visualizer/default_animations.c177
-rw-r--r--quantum/visualizer/lcd_backlight.c87
-rw-r--r--quantum/visualizer/lcd_backlight.h43
-rw-r--r--quantum/visualizer/lcd_backlight_keyframes.c69
-rw-r--r--quantum/visualizer/lcd_backlight_keyframes.h27
-rw-r--r--quantum/visualizer/lcd_keyframes.c184
-rw-r--r--quantum/visualizer/lcd_keyframes.h35
-rw-r--r--quantum/visualizer/led_backlight_keyframes.c143
-rw-r--r--quantum/visualizer/led_backlight_keyframes.h40
-rw-r--r--quantum/visualizer/readme.md18
-rw-r--r--quantum/visualizer/resources/lcd_logo.c45
-rw-r--r--quantum/visualizer/resources/lcd_logo.pngbin271 -> 0 bytes
-rw-r--r--quantum/visualizer/visualizer.c483
-rw-r--r--quantum/visualizer/visualizer.h154
-rw-r--r--quantum/visualizer/visualizer.mk123
-rw-r--r--quantum/wpm.c100
-rw-r--r--quantum/wpm.h7
-rw-r--r--requirements-dev.txt1
-rw-r--r--shell.nix2
-rw-r--r--testlist.mk11
-rw-r--r--tests/auto_shift/config.h (renamed from data/templates/base/keyboard.c)6
-rw-r--r--tests/auto_shift/test.mk20
-rw-r--r--tests/auto_shift/test_auto_shift.cpp73
-rw-r--r--tests/basic/config.h3
-rw-r--r--tests/basic/keymap.c45
-rw-r--r--tests/basic/test.mk18
-rw-r--r--tests/basic/test_action_layer.cpp427
-rw-r--r--tests/basic/test_keypress.cpp197
-rw-r--r--tests/basic/test_macro.cpp37
-rw-r--r--tests/basic/test_one_shot_keys.cpp197
-rw-r--r--tests/basic/test_tapping.cpp50
-rw-r--r--tests/tap_hold_configurations/default_mod_tap/config.h21
-rw-r--r--tests/tap_hold_configurations/default_mod_tap/test.mk18
-rw-r--r--tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp230
-rw-r--r--tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h21
-rw-r--r--tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk18
-rw-r--r--tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp136
-rw-r--r--tests/tap_hold_configurations/permissive_hold/config.h21
-rw-r--r--tests/tap_hold_configurations/permissive_hold/test.mk18
-rw-r--r--tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp76
-rw-r--r--tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp132
-rw-r--r--tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h (renamed from quantum/visualizer/resources/resources.h)9
-rw-r--r--tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk18
-rw-r--r--tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp134
-rw-r--r--tests/tap_hold_configurations/retro_tapping/config.h21
-rw-r--r--tests/tap_hold_configurations/retro_tapping/test.mk18
-rw-r--r--tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp52
-rw-r--r--tests/tap_hold_configurations/retro_tapping/test_tapping.cpp112
-rw-r--r--tests/tap_hold_configurations/tapping_force_hold/config.h21
-rw-r--r--tests/tap_hold_configurations/tapping_force_hold/test.mk18
-rw-r--r--tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp81
-rw-r--r--tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp215
-rw-r--r--tests/test_common/build.mk (renamed from tests/basic/rules.mk)4
-rw-r--r--tests/test_common/keyboard_report_util.cpp21
-rw-r--r--tests/test_common/keymap.c33
-rw-r--r--tests/test_common/test_common.h4
-rw-r--r--tests/test_common/test_driver.cpp5
-rw-r--r--tests/test_common/test_driver.hpp29
-rw-r--r--tests/test_common/test_fixture.cpp142
-rw-r--r--tests/test_common/test_fixture.hpp21
-rw-r--r--tests/test_common/test_keymap_key.cpp (renamed from data/templates/base/keyboard.h)31
-rw-r--r--tests/test_common/test_keymap_key.hpp46
-rw-r--r--tests/test_common/test_logger.cpp39
-rw-r--r--tests/test_common/test_logger.hpp (renamed from quantum/visualizer/visualizer_keyframes.h)22
-rw-r--r--tmk_core/common.mk144
-rw-r--r--tmk_core/common/chibios/chibios_config.h40
-rw-r--r--tmk_core/common/chibios/suspend.c169
-rw-r--r--tmk_core/protocol.mk92
-rw-r--r--tmk_core/protocol/adb.c535
-rw-r--r--tmk_core/protocol/adb.h106
-rw-r--r--tmk_core/protocol/arm_atsam.mk7
-rw-r--r--tmk_core/protocol/arm_atsam/arm_atsam_protocol.h4
-rw-r--r--tmk_core/protocol/arm_atsam/i2c_master.c19
-rw-r--r--tmk_core/protocol/arm_atsam/i2c_master.h9
-rw-r--r--tmk_core/protocol/arm_atsam/main_arm_atsam.c13
-rw-r--r--tmk_core/protocol/arm_atsam/md_rgb_matrix.c98
-rw-r--r--tmk_core/protocol/arm_atsam/md_rgb_matrix.h64
-rw-r--r--tmk_core/protocol/arm_atsam/shift_register.c118
-rw-r--r--tmk_core/protocol/arm_atsam/shift_register.h (renamed from tmk_core/protocol/arm_atsam/spi.h)25
-rw-r--r--tmk_core/protocol/arm_atsam/spi.c92
-rw-r--r--tmk_core/protocol/arm_atsam/spi_master.c109
-rw-r--r--tmk_core/protocol/arm_atsam/spi_master.h48
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_hub.c (renamed from tmk_core/protocol/arm_atsam/usb/usb2422.c)98
-rw-r--r--tmk_core/protocol/arm_atsam/usb/usb_hub.h51
-rw-r--r--tmk_core/protocol/chibios/chibios.c63
-rw-r--r--tmk_core/protocol/chibios/usb_main.c40
-rw-r--r--tmk_core/protocol/host.c (renamed from tmk_core/common/host.c)15
-rw-r--r--tmk_core/protocol/host.h (renamed from tmk_core/common/host.h)2
-rw-r--r--tmk_core/protocol/host_driver.h (renamed from tmk_core/common/host_driver.h)1
-rw-r--r--tmk_core/protocol/ibm4704.c185
-rw-r--r--tmk_core/protocol/ibm4704.h103
-rw-r--r--tmk_core/protocol/lufa.mk27
-rw-r--r--tmk_core/protocol/lufa/lufa.c71
-rw-r--r--tmk_core/protocol/lufa/lufa.h11
-rw-r--r--tmk_core/protocol/m0110.c583
-rw-r--r--tmk_core/protocol/m0110.h81
-rw-r--r--tmk_core/protocol/midi/qmk_midi.c41
-rw-r--r--tmk_core/protocol/news.c161
-rw-r--r--tmk_core/protocol/news.h48
-rw-r--r--tmk_core/protocol/next_kbd.c219
-rw-r--r--tmk_core/protocol/next_kbd.h60
-rw-r--r--tmk_core/protocol/ps2_io_avr.c58
-rw-r--r--tmk_core/protocol/ps2_io_chibios.c55
-rw-r--r--tmk_core/protocol/report.c (renamed from tmk_core/common/report.c)4
-rw-r--r--tmk_core/protocol/report.h (renamed from tmk_core/common/report.h)6
-rw-r--r--tmk_core/protocol/serial_mouse_microsoft.c113
-rw-r--r--tmk_core/protocol/serial_mouse_mousesystems.c119
-rw-r--r--tmk_core/protocol/usb_descriptor.c19
-rw-r--r--tmk_core/protocol/usb_device_state.c59
-rw-r--r--tmk_core/protocol/usb_device_state.h39
-rw-r--r--tmk_core/protocol/usb_hid/override_wiring.c2
-rw-r--r--tmk_core/protocol/usb_hid/parser.h5
-rw-r--r--tmk_core/protocol/usb_hid/usb_hid.h6
-rw-r--r--tmk_core/protocol/usb_util.c (renamed from tmk_core/common/usb_util.c)0
-rw-r--r--tmk_core/protocol/usb_util.h (renamed from tmk_core/common/usb_util.h)0
-rw-r--r--tmk_core/protocol/vusb/protocol.c12
-rw-r--r--tmk_core/protocol/vusb/vusb.c39
-rw-r--r--tmk_core/protocol/xt.h73
-rw-r--r--tmk_core/protocol/xt_interrupt.c166
-rw-r--r--tmk_core/readme.md11
-rw-r--r--tmk_core/rules.mk70
-rwxr-xr-xutil/chibios_conf_updater.sh103
-rwxr-xr-xutil/install/arch.sh3
-rwxr-xr-xutil/install/debian.sh11
-rwxr-xr-xutil/size_regression.sh79
-rw-r--r--util/udev/50-qmk.rules3
-rwxr-xr-xutil/update_chibios_mirror.sh4
593 files changed, 14872 insertions, 17520 deletions
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 53921f7f95..41b2475f67 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -22,7 +22,6 @@ keymap:
via:
- keyboards/**/keymaps/via/*
cli:
- - bin/qmk
- requirements.txt
- lib/python/**/*
python:
diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml
index 7a8dc8540f..2ea810958b 100644
--- a/.github/workflows/cli.yml
+++ b/.github/workflows/cli.yml
@@ -4,11 +4,10 @@ on:
push:
branches:
- master
- - future
+ - develop
pull_request:
paths:
- 'lib/python/**'
- - 'bin/qmk'
- 'requirements.txt'
- '.github/workflows/cli.yml'
diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml
index 0bb8701068..f1525526ce 100644
--- a/.github/workflows/format.yaml
+++ b/.github/workflows/format.yaml
@@ -19,7 +19,9 @@ jobs:
container: qmkfm/qmk_cli
steps:
- - uses: rlespinasse/github-slug-action@v3.x
+ - name: Install dependencies
+ run: |
+ apt-get update && apt-get install -y dos2unix
- uses: actions/checkout@v2
with:
@@ -31,12 +33,19 @@ jobs:
output: ' '
fileOutput: ' '
- - name: Run qmk format-c and qmk format-python
+ - name: Run qmk formatters
shell: 'bash {0}'
run: |
- qmk format-c --core-only -n $(< ~/files.txt)
- format_c_exit=$?
- qmk format-python -n
- format_python_exit=$?
+ cat ~/files_added.txt ~/files_modified.txt > ~/files_changed.txt
+ qmk format-c --core-only $(< ~/files_changed.txt) || true
+ qmk format-python $(< ~/files_changed.txt) || true
+ qmk format-text $(< ~/files_changed.txt) || true
- exit $((format_c_exit + format_python_exit))
+ - name: Fail when formatting required
+ run: |
+ git diff
+ for file in $(git diff --name-only); do
+ echo "File '${file}' Requires Formatting"
+ echo "::error file=${file}::Requires Formatting"
+ done
+ test -z "$(git diff --name-only)"
diff --git a/.github/workflows/format_push.yaml b/.github/workflows/format_push.yaml
new file mode 100644
index 0000000000..b79130f17a
--- /dev/null
+++ b/.github/workflows/format_push.yaml
@@ -0,0 +1,49 @@
+name: Lint Format
+
+on:
+ push:
+ branches:
+ - master
+ - develop
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ container: qmkfm/qmk_cli
+
+ steps:
+ - name: Install dependencies
+ run: |
+ apt-get update && apt-get install -y dos2unix
+
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ - name: Run qmk formatters
+ shell: 'bash {0}'
+ run: |
+ qmk format-c -a
+ qmk format-python -a
+ qmk format-text -a
+ git diff
+
+ - uses: rlespinasse/github-slug-action@v3.x
+
+ - name: Become QMK Bot
+ run: |
+ git config user.name 'QMK Bot'
+ git config user.email 'hello@qmk.fm'
+
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v3
+ if: ${{ github.repository == 'qmk/qmk_firmware'}}
+ with:
+ token: ${{ secrets.QMK_BOT_TOKEN }}
+ delete-branch: true
+ branch: bugfix/format_${{ env.GITHUB_REF_SLUG }}
+ author: QMK Bot <hello@qmk.fm>
+ committer: QMK Bot <hello@qmk.fm>
+ commit-message: Format code according to conventions
+ title: '[CI] Format code according to conventions'
diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml
new file mode 100644
index 0000000000..26bcb2f511
--- /dev/null
+++ b/.github/workflows/unit_test.yml
@@ -0,0 +1,30 @@
+name: Unit Tests
+
+on:
+ push:
+ branches:
+ - master
+ - develop
+ pull_request:
+ paths:
+ - 'builddefs/**'
+ - 'quantum/**'
+ - 'platforms/**'
+ - 'tmk_core/**'
+ - 'tests/**'
+ - '*.mk'
+ - 'Makefile'
+ - '.github/workflows/unit_test.yml'
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+
+ container: qmkfm/base_container
+
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: recursive
+ - name: Run tests
+ run: make test:all
diff --git a/.gitignore b/.gitignore
index e69e41ed96..0eaf911d6f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,3 +84,8 @@ user_song_list.h
/util/win_downloaded
/users/
/layouts/
+
+# clangd
+compile_commands.json
+.clangd/
+.cache/
diff --git a/.gitmodules b/.gitmodules
index 92bc99ce86..82b3c2a79b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -6,10 +6,6 @@
path = lib/chibios-contrib
url = https://github.com/qmk/ChibiOS-Contrib
branch = master
-[submodule "lib/ugfx"]
- path = lib/ugfx
- url = https://github.com/qmk/uGFX
- branch = master
[submodule "lib/googletest"]
path = lib/googletest
url = https://github.com/qmk/googletest
diff --git a/Makefile b/Makefile
index 1763611ab8..1b978fbcf8 100644
--- a/Makefile
+++ b/Makefile
@@ -30,11 +30,7 @@ endif
endif
# Determine which qmk cli to use
-ifeq (,$(shell which qmk))
- QMK_BIN = bin/qmk
-else
- QMK_BIN = qmk
-endif
+QMK_BIN := qmk
# avoid 'Entering|Leaving directory' messages
MAKEFLAGS += --no-print-directory
@@ -58,8 +54,6 @@ BUILD_DIR := $(ROOT_DIR)/.build
TEST_DIR := $(BUILD_DIR)/test
ERROR_FILE := $(BUILD_DIR)/error_occurred
-MAKEFILE_INCLUDED=yes
-
# Helper function to process the newt element of a space separated path
# It works a bit like the traditional functional head tail
# so the CURRENT_PATH_ELEMENT will become the new head
@@ -97,31 +91,8 @@ distclean: clean
rm -f *.bin *.hex *.uf2
echo 'done.'
-#Compatibility with the old make variables, anything you specify directly on the command line
-# always overrides the detected folders
-ifdef keyboard
- KEYBOARD := $(keyboard)
-endif
-ifdef keymap
- KEYMAP := $(keymap)
-endif
-
-# Uncomment these for debugging
-# $(info Keyboard: $(KEYBOARD))
-# $(info Keymap: $(KEYMAP))
-
-# Set the default goal depending on where we are running make from
-# this handles the case where you run make without any arguments
.DEFAULT_GOAL := all:all
-ifneq ($(KEYMAP),)
- .DEFAULT_GOAL := $(KEYBOARD):$(KEYMAP)
-else ifneq ($(KEYBOARD),)
- # Inside a keyboard folder, build all keymaps for all subprojects
- # Note that this is different from the old behaviour, which would
- # build only the default keymap of the default keyboard
- .DEFAULT_GOAL := $(KEYBOARD):all
-endif
# Compare the start of the RULE variable with the first argument($1)
@@ -257,10 +228,6 @@ define PARSE_RULE
else ifeq ($$(call TRY_TO_MATCH_RULE_FROM_LIST,$$(shell util/list_keyboards.sh | sort -u)),true)
KEYBOARD_RULE=$$(MATCHED_ITEM)
$$(eval $$(call PARSE_KEYBOARD,$$(MATCHED_ITEM)))
- # Otherwise use the KEYBOARD variable, which is determined either by
- # the current directory you run make from, or passed in as an argument
- else ifneq ($$(KEYBOARD),)
- $$(eval $$(call PARSE_KEYBOARD,$$(KEYBOARD)))
else
$$(info make: *** No rule to make target '$1'. Stop.)
$$(info |)
@@ -423,11 +390,12 @@ define PARSE_ALL_KEYMAPS
endef
define BUILD_TEST
- TEST_NAME := $1
+ TEST_PATH := $1
+ TEST_NAME := $$(notdir $$(TEST_PATH))
MAKE_TARGET := $2
COMMAND := $1
MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f build_test.mk $$(MAKE_TARGET)
- MAKE_VARS := TEST=$$(TEST_NAME) FULL_TESTS="$$(FULL_TESTS)"
+ MAKE_VARS := TEST=$$(TEST_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)"
MAKE_MSG := $$(MSG_MAKE_TEST)
$$(eval $$(call BUILD))
ifneq ($$(MAKE_TARGET),clean)
@@ -451,7 +419,7 @@ define PARSE_TEST
ifeq ($$(TEST_NAME),all)
MATCHED_TESTS := $$(TEST_LIST)
else
- MATCHED_TESTS := $$(foreach TEST,$$(TEST_LIST),$$(if $$(findstring $$(TEST_NAME),$$(TEST)),$$(TEST),))
+ MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring $$(TEST_NAME), $$(notdir $$(TEST))), $$(TEST),))
endif
$$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET))))
endef
@@ -470,7 +438,8 @@ define SET_SILENT_MODE
endif
endef
-include $(ROOT_DIR)/message.mk
+include paths.mk
+include $(BUILDDEFS_PATH)/message.mk
ifeq ($(strip $(BREAK_ON_ERRORS)), yes)
HANDLE_ERROR = exit 1
@@ -506,7 +475,6 @@ endef
ifndef SKIP_GIT
if [ ! -e lib/chibios ]; then git submodule sync lib/chibios && git submodule update --depth 50 --init lib/chibios; fi
if [ ! -e lib/chibios-contrib ]; then git submodule sync lib/chibios-contrib && git submodule update --depth 50 --init lib/chibios-contrib; fi
- if [ ! -e lib/ugfx ]; then git submodule sync lib/ugfx && git submodule update --depth 50 --init lib/ugfx; fi
if [ ! -e lib/lufa ]; then git submodule sync lib/lufa && git submodule update --depth 50 --init lib/lufa; fi
if [ ! -e lib/vusb ]; then git submodule sync lib/vusb && git submodule update --depth 50 --init lib/vusb; fi
if [ ! -e lib/printf ]; then git submodule sync lib/printf && git submodule update --depth 50 --init lib/printf; fi
diff --git a/bin/qmk b/bin/qmk
deleted file mode 100755
index 617f992826..0000000000
--- a/bin/qmk
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-"""CLI wrapper for running QMK commands.
-"""
-import os
-import sys
-from pathlib import Path
-
-# Add the QMK python libs to our path
-script_dir = Path(os.path.realpath(__file__)).parent
-qmk_dir = script_dir.parent
-python_lib_dir = Path(qmk_dir / 'lib' / 'python').resolve()
-sys.path.append(str(python_lib_dir))
-
-# Setup the CLI
-import milc # noqa
-
-milc.EMOJI_LOGLEVELS['INFO'] = '{fg_blue}Ψ{style_reset_all}'
-
-
-@milc.cli.entrypoint('QMK Helper Script')
-def qmk_main(cli):
- """The function that gets run when no subcommand is provided.
- """
- cli.print_help()
-
-
-def main():
- """Setup our environment and then call the CLI entrypoint.
- """
- # Change to the root of our checkout
- os.environ['ORIG_CWD'] = os.getcwd()
- os.environ['DEPRECATED_BIN_QMK'] = '1'
- os.chdir(qmk_dir)
-
- print('Warning: The bin/qmk script is being deprecated. Please install the QMK CLI: python3 -m pip install qmk', file=sys.stderr)
-
- # Import the subcommands
- import milc.subcommand.config # noqa
- import qmk.cli # noqa
-
- # Execute
- return_code = milc.cli()
-
- if return_code is False:
- exit(1)
-
- elif return_code is not True and isinstance(return_code, int):
- if return_code < 0 or return_code > 255:
- milc.cli.log.error('Invalid return_code: %d', return_code)
- exit(255)
-
- exit(return_code)
-
- exit(0)
-
-
-if __name__ == '__main__':
- main()
diff --git a/build_full_test.mk b/build_full_test.mk
index f8030cb060..4cd1ac61b5 100644
--- a/build_full_test.mk
+++ b/build_full_test.mk
@@ -13,21 +13,24 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#include $(TMK_PATH)/protocol.mk
+$(TEST)_INC := \
+ tests\test_common\common_config.h
-TEST_PATH=tests/$(TEST)
-
-$(TEST)_SRC= \
- $(TEST_PATH)/keymap.c \
+$(TEST)_SRC := \
$(TMK_COMMON_SRC) \
$(QUANTUM_SRC) \
$(SRC) \
+ tests/test_common/keymap.c \
tests/test_common/matrix.c \
tests/test_common/test_driver.cpp \
tests/test_common/keyboard_report_util.cpp \
- tests/test_common/test_fixture.cpp
-$(TEST)_SRC += $(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp))
+ tests/test_common/test_fixture.cpp \
+ tests/test_common/test_keymap_key.cpp \
+ tests/test_common/test_logger.cpp \
+ $(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp))
+
+$(TEST)_DEFS := $(TMK_COMMON_DEFS) $(OPT_DEFS)
+
+$(TEST)_CONFIG := $(TEST_PATH)/config.h
-$(TEST)_DEFS=$(TMK_COMMON_DEFS) $(OPT_DEFS)
-$(TEST)_CONFIG=$(TEST_PATH)/config.h
-VPATH+=$(TOP_DIR)/tests/test_common
+VPATH += $(TOP_DIR)/tests/test_common \ No newline at end of file
diff --git a/build_keyboard.mk b/build_keyboard.mk
index 37fa6852f8..c12aa0fce0 100644
--- a/build_keyboard.mk
+++ b/build_keyboard.mk
@@ -10,7 +10,8 @@ endif
.DEFAULT_GOAL := all
-include common.mk
+include paths.mk
+include $(BUILDDEFS_PATH)/message.mk
# Set the qmk cli to use
QMK_BIN ?= qmk
@@ -32,20 +33,6 @@ endif
# this an empty or blank macro!
KEYMAP_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
-# For split boards we need to set a master half.
-MASTER ?= left
-ifdef master
- MASTER = $(master)
-endif
-
-ifeq ($(MASTER),right)
- OPT_DEFS += -DMASTER_IS_ON_RIGHT
-else
- ifneq ($(MASTER),left)
-$(error MASTER does not have a valid value(left/right))
- endif
-endif
-
ifdef SKIP_VERSION
OPT_DEFS += -DSKIP_VERSION
endif
@@ -115,6 +102,7 @@ include $(INFO_RULES_MK)
# Check for keymap.json first, so we can regenerate keymap.c
include build_json.mk
+# Pull in keymap level rules.mk
ifeq ("$(wildcard $(KEYMAP_PATH))", "")
# Look through the possible keymap folders until we find a matching keymap.c
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","")
@@ -177,7 +165,7 @@ ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes)
include platforms/chibios/boards/QMK_PROTON_C/convert_to_proton_c.mk
endif
-include quantum/mcu_selection.mk
+include $(BUILDDEFS_PATH)/mcu_selection.mk
# Find all the C source files to be compiled in subfolders.
KEYBOARD_SRC :=
@@ -345,6 +333,7 @@ ifeq ("$(USER_NAME)","")
endif
USER_PATH := users/$(USER_NAME)
+# Pull in user level rules.mk
-include $(USER_PATH)/rules.mk
ifneq ("$(wildcard $(USER_PATH)/config.h)","")
CONFIG_H += $(USER_PATH)/config.h
@@ -354,7 +343,24 @@ ifneq ("$(wildcard $(USER_PATH)/post_config.h)","")
endif
# Disable features that a keyboard doesn't support
--include disable_features.mk
+-include $(BUILDDEFS_PATH)/disable_features.mk
+
+# Pull in post_rules.mk files from all our subfolders
+ifneq ("$(wildcard $(KEYBOARD_PATH_1)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_1)/post_rules.mk
+endif
+ifneq ("$(wildcard $(KEYBOARD_PATH_2)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_2)/post_rules.mk
+endif
+ifneq ("$(wildcard $(KEYBOARD_PATH_3)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_3)/post_rules.mk
+endif
+ifneq ("$(wildcard $(KEYBOARD_PATH_4)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_4)/post_rules.mk
+endif
+ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_5)/post_rules.mk
+endif
ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
CONFIG_H += $(KEYMAP_PATH)/config.h
@@ -380,9 +386,10 @@ VPATH += $(KEYBOARD_PATHS)
VPATH += $(COMMON_VPATH)
include common_features.mk
+include $(BUILDDEFS_PATH)/generic_features.mk
include $(TMK_PATH)/protocol.mk
-include $(TMK_PATH)/common.mk
-include bootloader.mk
+include $(PLATFORM_PATH)/common.mk
+include $(BUILDDEFS_PATH)/bootloader.mk
SRC += $(patsubst %.c,%.clib,$(LIB_SRC))
SRC += $(patsubst %.c,%.clib,$(QUANTUM_LIB_SRC))
@@ -397,39 +404,34 @@ ifneq ($(REQUIRE_PLATFORM_KEY),)
endif
endif
-include $(TMK_PATH)/$(PLATFORM_KEY).mk
+include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
+-include $(PLATFORM_PATH)/$(PLATFORM_KEY)/flash.mk
+
ifneq ($(strip $(PROTOCOL)),)
include $(TMK_PATH)/protocol/$(strip $(shell echo $(PROTOCOL) | tr '[:upper:]' '[:lower:]')).mk
else
include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk
endif
--include $(TOP_DIR)/platforms/$(PLATFORM_KEY)/flash.mk
# TODO: remove this bodge?
PROJECT_DEFS := $(OPT_DEFS)
PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYBOARD_PATHS)
PROJECT_CONFIG := $(CONFIG_H)
-ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
- VISUALIZER_DIR = $(QUANTUM_DIR)/visualizer
- VISUALIZER_PATH = $(QUANTUM_PATH)/visualizer
- include $(VISUALIZER_PATH)/visualizer.mk
-endif
-
CONFIG_H += $(POST_CONFIG_H)
ALL_CONFIGS := $(PROJECT_CONFIG) $(CONFIG_H)
OUTPUTS := $(KEYMAP_OUTPUT) $(KEYBOARD_OUTPUT)
$(KEYMAP_OUTPUT)_SRC := $(SRC)
-$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) $(GFXDEFS) \
+$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) \
-DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYBOARD_H=\"$(QMK_KEYBOARD_H)\" \
-DQMK_KEYMAP=\"$(KEYMAP)\" -DQMK_KEYMAP_H=\"$(KEYMAP).h\" -DQMK_KEYMAP_CONFIG_H=\"$(KEYMAP_PATH)/config.h\" \
-DQMK_SUBPROJECT -DQMK_SUBPROJECT_H -DQMK_SUBPROJECT_CONFIG_H
$(KEYMAP_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS)
$(KEYMAP_OUTPUT)_CONFIG := $(CONFIG_H)
-$(KEYBOARD_OUTPUT)_SRC := $(CHIBISRC) $(GFXSRC)
-$(KEYBOARD_OUTPUT)_DEFS := $(PROJECT_DEFS) $(GFXDEFS)
-$(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC) $(GFXINC)
+$(KEYBOARD_OUTPUT)_SRC := $(PLATFORM_SRC)
+$(KEYBOARD_OUTPUT)_DEFS := $(PROJECT_DEFS)
+$(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC)
$(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG)
# Default target.
@@ -445,7 +447,7 @@ check-size: build
check-md5: build
objs-size: build
-include show_options.mk
+include $(BUILDDEFS_PATH)/show_options.mk
include $(TMK_PATH)/rules.mk
# Ensure we have generated files available for each of the objects
diff --git a/build_test.mk b/build_test.mk
index 037577bf90..136a0455f0 100644
--- a/build_test.mk
+++ b/build_test.mk
@@ -4,7 +4,8 @@ endif
.DEFAULT_GOAL := all
-include common.mk
+include paths.mk
+include $(BUILDDEFS_PATH)/message.mk
TARGET=test/$(TEST)
@@ -15,14 +16,14 @@ TEST_OBJ = $(BUILD_DIR)/test_obj
OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT)
GTEST_INC := \
- $(LIB_PATH)/googletest/googletest/include\
- $(LIB_PATH)/googletest/googlemock/include\
+ $(LIB_PATH)/googletest/googletest/include \
+ $(LIB_PATH)/googletest/googlemock/include
-GTEST_INTERNAL_INC :=\
- $(LIB_PATH)/googletest/googletest\
+GTEST_INTERNAL_INC := \
+ $(LIB_PATH)/googletest/googletest \
$(LIB_PATH)/googletest/googlemock
-$(GTEST_OUTPUT)_SRC :=\
+$(GTEST_OUTPUT)_SRC := \
googletest/src/gtest-all.cc\
googlemock/src/gmock-all.cc
@@ -32,9 +33,9 @@ $(GTEST_OUTPUT)_INC := $(GTEST_INC) $(GTEST_INTERNAL_INC)
LDFLAGS += -lstdc++ -lpthread -shared-libgcc
CREATE_MAP := no
-VPATH +=\
- $(LIB_PATH)/googletest\
- $(LIB_PATH)/googlemock\
+VPATH += \
+ $(LIB_PATH)/googletest \
+ $(LIB_PATH)/googlemock \
$(LIB_PATH)/printf
all: elf
@@ -48,15 +49,18 @@ CONSOLE_ENABLE = yes
endif
ifneq ($(filter $(FULL_TESTS),$(TEST)),)
-include tests/$(TEST)/rules.mk
+include tests/test_common/build.mk
+include $(TEST_PATH)/test.mk
endif
include common_features.mk
-include $(TMK_PATH)/common.mk
+include $(BUILDDEFS_PATH)/generic_features.mk
+include $(PLATFORM_PATH)/common.mk
+include $(TMK_PATH)/protocol.mk
include $(QUANTUM_PATH)/debounce/tests/rules.mk
+include $(QUANTUM_PATH)/encoder/tests/rules.mk
include $(QUANTUM_PATH)/sequencer/tests/rules.mk
-include $(QUANTUM_PATH)/serial_link/tests/rules.mk
-include $(TMK_PATH)/common/test/rules.mk
+include $(PLATFORM_PATH)/test/rules.mk
ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include build_full_test.mk
endif
@@ -71,7 +75,7 @@ $(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC)
$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS)
$(TEST_OBJ)/$(TEST)_CONFIG := $($(TEST)_CONFIG)
-include $(TMK_PATH)/native.mk
+include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
include $(TMK_PATH)/rules.mk
diff --git a/bootloader.mk b/builddefs/bootloader.mk
index 5ba118fb44..ccb92392d9 100644
--- a/bootloader.mk
+++ b/builddefs/bootloader.mk
@@ -34,6 +34,8 @@
# stm32duino STM32Duino (STM32F103x8)
# stm32-dfu STM32 USB DFU in ROM
# apm32-dfu APM32 USB DFU in ROM
+# RISC-V:
+# gd32v-dfu GD32V USB DFU in ROM
#
# BOOTLOADER_SIZE can still be defined manually, but it's recommended
# you add any possible configuration to this list
@@ -125,6 +127,13 @@ ifeq ($(strip $(BOOTLOADER)), apm32-dfu)
DFU_ARGS ?= -d 314B:0106 -a 0 -s 0x08000000:leave
DFU_SUFFIX_ARGS ?= -v 314B -p 0106
endif
+ifeq ($(strip $(BOOTLOADER)), gd32v-dfu)
+ OPT_DEFS += -DBOOTLOADER_GD32V_DFU
+
+ # Options to pass to dfu-util when flashing
+ DFU_ARGS ?= -d 28E9:0189 -a 0 -s 0x08000000:leave
+ DFU_SUFFIX_ARGS ?= -v 28E9 -p 0189
+endif
ifeq ($(strip $(BOOTLOADER)), kiibohd)
OPT_DEFS += -DBOOTLOADER_KIIBOHD
ifeq ($(strip $(MCU_ORIG)), MK20DX128)
diff --git a/disable_features.mk b/builddefs/disable_features.mk
index 84d8316eac..090a9b5a11 100644
--- a/disable_features.mk
+++ b/builddefs/disable_features.mk
@@ -1,7 +1,6 @@
# Unconditionally disable features that a keyboard advertises it doesn't support
FEATURE_NAMES :=
-FEATURE_NAMES += ADAFRUIT_BLE
FEATURE_NAMES += AUDIO
FEATURE_NAMES += BACKLIGHT
FEATURE_NAMES += BLUETOOTH
@@ -20,10 +19,8 @@ FEATURE_NAMES += PS2_MOUSE
FEATURE_NAMES += RGBLIGHT
FEATURE_NAMES += RGB_MATRIX
FEATURE_NAMES += SLEEP_LED
-FEATURE_NAMES += SERIAL_LINK
FEATURE_NAMES += STENO
FEATURE_NAMES += SWAP_HANDS
-FEATURE_NAMES += VISUALIZER
FEATURE_NAMES += WATCHDOG
FEATURE_NAMES += XT
diff --git a/builddefs/generic_features.mk b/builddefs/generic_features.mk
new file mode 100644
index 0000000000..e4151eb217
--- /dev/null
+++ b/builddefs/generic_features.mk
@@ -0,0 +1,52 @@
+# Copyright 2021 QMK
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+SPACE_CADET_ENABLE ?= yes
+GRAVE_ESC_ENABLE ?= yes
+
+GENERIC_FEATURES = \
+ COMBO \
+ COMMAND \
+ DEFERRED_EXEC \
+ DIGITIZER \
+ DIP_SWITCH \
+ DYNAMIC_KEYMAP \
+ DYNAMIC_MACRO \
+ ENCODER \
+ GRAVE_ESC \
+ HAPTIC \
+ KEY_LOCK \
+ KEY_OVERRIDE \
+ LEADER \
+ PROGRAMMABLE_BUTTON \
+ SPACE_CADET \
+ SWAP_HANDS \
+ TAP_DANCE \
+ VELOCIKEY \
+ WPM \
+ DYNAMIC_TAPPING_TERM \
+
+define HANDLE_GENERIC_FEATURE
+ # $$(info "Processing: $1_ENABLE $2.c")
+ SRC += $$(wildcard $$(QUANTUM_DIR)/process_keycode/process_$2.c)
+ SRC += $$(wildcard $$(QUANTUM_DIR)/$2.c)
+ OPT_DEFS += -D$1_ENABLE
+endef
+
+$(foreach F,$(GENERIC_FEATURES),\
+ $(if $(filter yes, $(strip $($(F)_ENABLE))),\
+ $(eval $(call HANDLE_GENERIC_FEATURE,$(F),$(shell echo $(F) | tr '[:upper:]' '[:lower:]'))) \
+ ) \
+)
diff --git a/quantum/mcu_selection.mk b/builddefs/mcu_selection.mk
index f7eaeec8ac..46d34aabe4 100644
--- a/quantum/mcu_selection.mk
+++ b/builddefs/mcu_selection.mk
@@ -81,7 +81,7 @@ ifneq ($(findstring MK20DX256, $(MCU)),)
BOARD ?= PJRC_TEENSY_3_1
endif
-ifneq ($(findstring MK66F18, $(MCU)),)
+ifneq ($(findstring MK66FX1M0, $(MCU)),)
# Cortex version
MCU = cortex-m4
@@ -122,7 +122,7 @@ ifneq ($(findstring STM32F042, $(MCU)),)
MCU_SERIES = STM32F0xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32F042x6
@@ -138,6 +138,11 @@ ifneq ($(findstring STM32F042, $(MCU)),)
# UF2 settings
UF2_FAMILY ?= STM32F0
+
+ # Stack sizes: Since this chip has limited RAM capacity, the stack area needs to be reduced.
+ # This ensures that the EEPROM page buffer fits into RAM
+ USE_PROCESS_STACKSIZE = 0x600
+ USE_EXCEPTIONS_STACKSIZE = 0x300
endif
ifneq ($(findstring STM32F072, $(MCU)),)
@@ -154,7 +159,7 @@ ifneq ($(findstring STM32F072, $(MCU)),)
MCU_SERIES = STM32F0xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32F072xB
@@ -186,7 +191,7 @@ ifneq ($(findstring STM32F103, $(MCU)),)
MCU_SERIES = STM32F1xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32F103x8
@@ -218,7 +223,7 @@ ifneq ($(findstring STM32F303, $(MCU)),)
MCU_SERIES = STM32F3xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32F303xC
@@ -250,7 +255,7 @@ ifneq ($(findstring STM32F401, $(MCU)),)
MCU_SERIES = STM32F4xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
ifeq ($(strip $(BOOTLOADER)), tinyuf2)
MCU_LDSCRIPT ?= STM32F401xC_tinyuf2
@@ -273,7 +278,7 @@ ifneq ($(findstring STM32F401, $(MCU)),)
UF2_FAMILY ?= STM32F4
endif
-ifneq ($(findstring STM32F407, $(MCU)),)
+ifneq ($(findstring STM32F405, $(MCU)),)
# Cortex version
MCU = cortex-m4
@@ -289,6 +294,38 @@ ifneq ($(findstring STM32F407, $(MCU)),)
# Linker script to use
# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
+ MCU_LDSCRIPT ?= STM32F405xG
+
+ # Startup code to use
+ # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP ?= stm32f4xx
+
+ # Board: it should exist either in <chibios>/os/hal/boards/,
+ # <keyboard_dir>/boards/, or drivers/boards/
+ BOARD ?= GENERIC_STM32_F405XG
+
+ USE_FPU ?= yes
+
+ # UF2 settings
+ UF2_FAMILY ?= STM32F4
+endif
+
+ifneq ($(findstring STM32F407, $(MCU)),)
+ # Cortex version
+ MCU = cortex-m4
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ ARMV = 7
+
+ ## chip/board settings
+ # - the next two should match the directories in
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = STM32
+ MCU_SERIES = STM32F4xx
+
+ # Linker script to use
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
+ # or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32F407xE
# Startup code to use
@@ -319,7 +356,7 @@ ifneq ($(findstring STM32F411, $(MCU)),)
MCU_SERIES = STM32F4xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
ifeq ($(strip $(BOOTLOADER)), tinyuf2)
MCU_LDSCRIPT ?= STM32F411xE_tinyuf2
@@ -356,8 +393,7 @@ ifneq ($(findstring STM32F446, $(MCU)),)
MCU_SERIES = STM32F4xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32F446xE
@@ -386,7 +422,7 @@ ifneq ($(findstring STM32G431, $(MCU)),)
MCU_SERIES = STM32G4xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32G431xB
@@ -418,7 +454,7 @@ ifneq ($(findstring STM32G474, $(MCU)),)
MCU_SERIES = STM32G4xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32G474xE
@@ -450,7 +486,7 @@ ifneq (,$(filter $(MCU),STM32L433 STM32L443))
MCU_SERIES = STM32L4xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32L432xC
@@ -484,7 +520,7 @@ ifneq (,$(filter $(MCU),STM32L412 STM32L422))
MCU_SERIES = STM32L4xx
# Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # - it should exist either in <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
# or <keyboard_dir>/ld/
MCU_LDSCRIPT ?= STM32L412xB
@@ -504,6 +540,66 @@ ifneq (,$(filter $(MCU),STM32L412 STM32L422))
UF2_FAMILY ?= STM32L4
endif
+ifneq ($(findstring WB32F3G71, $(MCU)),)
+ # Cortex version
+ MCU = cortex-m3
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ ARMV = 7
+
+ ## chip/board settings
+ # - the next two should match the directories in
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = WB32
+ MCU_SERIES = WB32F3G71xx
+
+ # Linker script to use
+ # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # or <keyboard_dir>/ld/
+ MCU_LDSCRIPT ?= WB32F3G71x9
+
+ # Startup code to use
+ # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP ?= wb32f3g71xx
+
+ # Board: it should exist either in <chibios>/os/hal/boards/,
+ # <keyboard_dir>/boards/, or drivers/boards/
+ BOARD ?= GENERIC_WB32_F3G71XX
+
+ USE_FPU ?= no
+endif
+
+ifneq ($(findstring GD32VF103, $(MCU)),)
+ # RISC-V
+ MCU = risc-v
+
+ # RISC-V extensions and abi configuration
+ MCU_ARCH = rv32imac
+ MCU_ABI = ilp32
+ MCU_CMODEL = medlow
+
+ ## chip/board settings
+ # - the next two should match the directories in
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = GD32V
+ MCU_SERIES = GD32VF103
+
+ # Linker script to use
+ # - it should exist either in <chibios>/os/common/startup/RISCV-ECLIC/compilers/GCC/ld/
+ # or <keyboard_dir>/ld/
+ MCU_LDSCRIPT ?= GD32VF103xB
+
+ # Startup code to use
+ # - it should exist in <chibios>/os/common/startup/RISCV-ECLIC/compilers/GCC/mk/
+ MCU_STARTUP ?= gd32vf103
+
+ # Board: it should exist either in <chibios>/os/hal/boards/,
+ # <keyboard_dir>/boards/, or drivers/boards/
+ BOARD ?= SIPEED_LONGAN_NANO
+
+ USE_FPU ?= no
+endif
+
ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287))
PROTOCOL = LUFA
diff --git a/message.mk b/builddefs/message.mk
index cb4ef43719..cb4ef43719 100644
--- a/message.mk
+++ b/builddefs/message.mk
diff --git a/show_options.mk b/builddefs/show_options.mk
index b17d8c7d9d..2820332d56 100644
--- a/show_options.mk
+++ b/builddefs/show_options.mk
@@ -21,17 +21,15 @@ HARDWARE_OPTION_NAMES = \
RGBLIGHT_CUSTOM_DRIVER \
RGB_MATRIX_ENABLE \
RGB_MATRIX_DRIVER \
- SERIAL_LINK_ENABLE \
CIE1931_CURVE \
MIDI_ENABLE \
BLUETOOTH_ENABLE \
+ BLUETOOTH_DRIVER \
AUDIO_ENABLE \
HD44780_ENABLE \
ENCODER_ENABLE \
- LCD_ENABLE \
LED_TABLES \
POINTING_DEVICE_ENABLE \
- VISUALIZER_ENABLE \
DIP_SWITCH_ENABLE
OTHER_OPTION_NAMES = \
@@ -39,9 +37,9 @@ OTHER_OPTION_NAMES = \
UCIS_ENABLE \
UNICODEMAP_ENABLE \
UNICODE_COMMON \
- API_SYSEX_ENABLE \
AUTO_SHIFT_ENABLE \
AUTO_SHIFT_MODIFIERS \
+ DYNAMIC_TAPPING_TERM_ENABLE \
COMBO_ENABLE \
KEY_LOCK_ENABLE \
KEY_OVERRIDE_ENABLE \
@@ -57,7 +55,6 @@ OTHER_OPTION_NAMES = \
LED_ANIMATIONS \
IOS_DEVICE_ENABLE \
HELIX ZINC \
- ADAFRUIT_BLE_ENABLE \
AUTOLOG_ENABLE \
DEBUG_ENABLE \
ENCODER_ENABLE_CUSTOM \
@@ -65,7 +62,6 @@ OTHER_OPTION_NAMES = \
HAPTIC_ENABLE \
HHKB_RN42_ENABLE \
ISSI_ENABLE \
- KEYBOARD_LOCK_ENABLE \
KEYLOGGER_ENABLE \
LCD_BACKLIGHT_ENABLE \
MACROS_ENABLED \
@@ -74,7 +70,6 @@ OTHER_OPTION_NAMES = \
SWAP_HANDS_ENABLE \
RING_BUFFERED_6KRO_REPORT_ENABLE \
WATCHDOG_ENABLE \
- XT_ENABLE \
ERGOINU \
NO_USB_STARTUP_CHECK \
DISABLE_PROMICRO_LEDs \
@@ -83,7 +78,8 @@ OTHER_OPTION_NAMES = \
RGB_MATRIX_KEYPRESSES \
LED_MIRRORED \
RGBLIGHT_FULL_POWER \
- LTO_ENABLE
+ LTO_ENABLE \
+ PROGRAMMABLE_BUTTON_ENABLE
define NAME_ECHO
@printf " %-30s = %-16s # %s\\n" "$1" "$($1)" "$(origin $1)"
diff --git a/common_features.mk b/common_features.mk
index aea79789df..a28c8a042a 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -13,8 +13,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-SERIAL_PATH := $(QUANTUM_PATH)/serial_link
-
QUANTUM_SRC += \
$(QUANTUM_DIR)/quantum.c \
$(QUANTUM_DIR)/send_string.c \
@@ -29,13 +27,16 @@ QUANTUM_SRC += \
$(QUANTUM_DIR)/keyboard.c \
$(QUANTUM_DIR)/keymap_common.c \
$(QUANTUM_DIR)/keycode_config.c \
+ $(QUANTUM_DIR)/sync_timer.c \
$(QUANTUM_DIR)/logging/debug.c \
$(QUANTUM_DIR)/logging/sendchar.c \
VPATH += $(QUANTUM_DIR)/logging
# Fall back to lib/printf if there is no platform provided print
-ifeq ("$(wildcard $(TMK_PATH)/common/$(PLATFORM_KEY)/printf.mk)","")
+ifeq ("$(wildcard $(PLATFORM_PATH)/$(PLATFORM_KEY)/printf.mk)","")
include $(QUANTUM_PATH)/logging/print.mk
+else
+ include $(PLATFORM_PATH)/$(PLATFORM_KEY)/printf.mk
endif
ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes)
@@ -45,19 +46,6 @@ else ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), api)
OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE
endif
-ifeq ($(strip $(API_SYSEX_ENABLE)), yes)
- OPT_DEFS += -DAPI_SYSEX_ENABLE
- OPT_DEFS += -DAPI_ENABLE
- MIDI_ENABLE=yes
- SRC += $(QUANTUM_DIR)/api/api_sysex.c
- SRC += $(QUANTUM_DIR)/api.c
-endif
-
-ifeq ($(strip $(COMMAND_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/command.c
- OPT_DEFS += -DCOMMAND_ENABLE
-endif
-
AUDIO_ENABLE ?= no
ifeq ($(strip $(AUDIO_ENABLE)), yes)
ifeq ($(PLATFORM),CHIBIOS)
@@ -82,7 +70,7 @@ ifeq ($(strip $(AUDIO_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c
SRC += $(QUANTUM_DIR)/process_keycode/process_clicky.c
SRC += $(QUANTUM_DIR)/audio/audio.c ## common audio code, hardware agnostic
- SRC += $(QUANTUM_DIR)/audio/driver_$(PLATFORM_KEY)_$(strip $(AUDIO_DRIVER)).c
+ SRC += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/audio_$(strip $(AUDIO_DRIVER)).c
SRC += $(QUANTUM_DIR)/audio/voices.c
SRC += $(QUANTUM_DIR)/audio/luts.c
endif
@@ -121,10 +109,43 @@ ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/mousekey.c
endif
+VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi pmw3360 pimoroni_trackball custom
+POINTING_DEVICE_DRIVER ?= custom
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
- OPT_DEFS += -DPOINTING_DEVICE_ENABLE
- MOUSE_ENABLE := yes
- SRC += $(QUANTUM_DIR)/pointing_device.c
+ ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),)
+ $(error POINTING_DEVICE_DRIVER="$(POINTING_DEVICE_DRIVER)" is not a valid pointing device type)
+ else
+ OPT_DEFS += -DPOINTING_DEVICE_ENABLE
+ MOUSE_ENABLE := yes
+ SRC += $(QUANTUM_DIR)/pointing_device.c
+ SRC += $(QUANTUM_DIR)/pointing_device_drivers.c
+ ifneq ($(strip $(POINTING_DEVICE_DRIVER)), custom)
+ SRC += drivers/sensors/$(strip $(POINTING_DEVICE_DRIVER)).c
+ OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(shell echo $(POINTING_DEVICE_DRIVER) | tr '[:lower:]' '[:upper:]'))
+ endif
+ OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(POINTING_DEVICE_DRIVER))
+ ifeq ($(strip $(POINTING_DEVICE_DRIVER)), adns9800)
+ OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
+ QUANTUM_LIB_SRC += spi_master.c
+ else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), analog_joystick)
+ OPT_DEFS += -DSTM32_ADC -DHAL_USE_ADC=TRUE
+ LIB_SRC += analog.c
+ else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_i2c)
+ OPT_DEFS += -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ SRC += drivers/sensors/cirque_pinnacle.c
+ QUANTUM_LIB_SRC += i2c_master.c
+ else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_spi)
+ OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
+ SRC += drivers/sensors/cirque_pinnacle.c
+ QUANTUM_LIB_SRC += spi_master.c
+ else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pimoroni_trackball)
+ OPT_DEFS += -DSTM32_SPI -DHAL_USE_I2C=TRUE
+ QUANTUM_LIB_SRC += i2c_master.c
+ else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pmw3360)
+ OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
+ QUANTUM_LIB_SRC += spi_master.c
+ endif
+ endif
endif
VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c spi
@@ -156,36 +177,18 @@ else
ifeq ($(PLATFORM),AVR)
# Automatically provided by avr-libc, nothing required
else ifeq ($(PLATFORM),CHIBIOS)
- ifeq ($(MCU_SERIES), STM32F3xx)
- SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
- SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
- OPT_DEFS += -DEEPROM_EMU_STM32F303xC
- OPT_DEFS += -DSTM32_EEPROM_ENABLE
- else ifeq ($(MCU_SERIES), STM32F1xx)
- SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
- SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
- OPT_DEFS += -DEEPROM_EMU_STM32F103xB
- OPT_DEFS += -DSTM32_EEPROM_ENABLE
- else ifeq ($(MCU_SERIES)_$(MCU_LDSCRIPT), STM32F0xx_STM32F072xB)
- SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
- SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
- OPT_DEFS += -DEEPROM_EMU_STM32F072xB
- OPT_DEFS += -DSTM32_EEPROM_ENABLE
- else ifeq ($(MCU_SERIES)_$(MCU_LDSCRIPT), STM32F0xx_STM32F042x6)
-
- # Stack sizes: Since this chip has limited RAM capacity, the stack area needs to be reduced.
- # This ensures that the EEPROM page buffer fits into RAM
- USE_PROCESS_STACKSIZE = 0x600
- USE_EXCEPTIONS_STACKSIZE = 0x300
+ ifneq ($(filter STM32F3xx_% STM32F1xx_% %_STM32F401xC %_STM32F401xE %_STM32F405xG %_STM32F411xE %_STM32F072xB %_STM32F042x6 %_GD32VF103xB %_GD32VF103x8, $(MCU_SERIES)_$(MCU_LDSCRIPT)),)
+ OPT_DEFS += -DEEPROM_DRIVER
+ COMMON_VPATH += $(DRIVER_PATH)/eeprom
+ SRC += eeprom_driver.c
SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
- OPT_DEFS += -DEEPROM_EMU_STM32F042x6
- OPT_DEFS += -DSTM32_EEPROM_ENABLE
else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),)
OPT_DEFS += -DEEPROM_DRIVER
COMMON_VPATH += $(DRIVER_PATH)/eeprom
COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/eeprom
- SRC += eeprom_driver.c eeprom_stm32_L0_L1.c
+ SRC += eeprom_driver.c
+ SRC += eeprom_stm32_L0_L1.c
else
# This will effectively work the same as "transient" if not supported by the chip
SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c
@@ -264,7 +267,7 @@ endif
endif
RGB_MATRIX_ENABLE ?= no
-VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 WS2812 custom
+VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 CKLED2001 WS2812 custom
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
@@ -320,6 +323,13 @@ endif
QUANTUM_LIB_SRC += i2c_master.c
endif
+ ifeq ($(strip $(RGB_MATRIX_DRIVER)), CKLED2001)
+ OPT_DEFS += -DCKLED2001 -DSTM32_I2C -DHAL_USE_I2C=TRUE
+ COMMON_VPATH += $(DRIVER_PATH)/led
+ SRC += ckled2001.c
+ QUANTUM_LIB_SRC += i2c_master.c
+ endif
+
ifeq ($(strip $(RGB_MATRIX_DRIVER)), WS2812)
OPT_DEFS += -DWS2812
WS2812_DRIVER_REQUIRED := yes
@@ -349,17 +359,6 @@ ifeq ($(strip $(PRINTING_ENABLE)), yes)
SRC += $(TMK_DIR)/protocol/serial_uart.c
endif
-ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
- SERIAL_SRC := $(wildcard $(SERIAL_PATH)/protocol/*.c)
- SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c)
- SERIAL_DEFS += -DSERIAL_LINK_ENABLE
- COMMON_VPATH += $(SERIAL_PATH)
-
- SRC += $(patsubst $(QUANTUM_PATH)/%,%,$(SERIAL_SRC))
- OPT_DEFS += $(SERIAL_DEFS)
- VAPTH += $(SERIAL_PATH)
-endif
-
VARIABLE_TRACE ?= no
ifneq ($(strip $(VARIABLE_TRACE)),no)
SRC += $(QUANTUM_DIR)/variable_trace.c
@@ -369,8 +368,11 @@ ifneq ($(strip $(VARIABLE_TRACE)),no)
endif
endif
-ifeq ($(strip $(LCD_ENABLE)), yes)
- CIE1931_CURVE := yes
+ifeq ($(strip $(SLEEP_LED_ENABLE)), yes)
+ SRC += $(PLATFORM_COMMON_DIR)/sleep_led.c
+ OPT_DEFS += -DSLEEP_LED_ENABLE
+
+ NO_SUSPEND_POWER_DOWN := yes
endif
VALID_BACKLIGHT_TYPES := pwm timer software custom
@@ -436,10 +438,6 @@ ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes)
SRC += apa102.c
endif
-ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
- CIE1931_CURVE := yes
-endif
-
ifeq ($(strip $(CIE1931_CURVE)), yes)
OPT_DEFS += -DUSE_CIE1931_CURVE
LED_TABLES := yes
@@ -455,21 +453,6 @@ ifeq ($(strip $(TERMINAL_ENABLE)), yes)
OPT_DEFS += -DUSER_PRINT
endif
-ifeq ($(strip $(WPM_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/wpm.c
- OPT_DEFS += -DWPM_ENABLE
-endif
-
-ifeq ($(strip $(ENCODER_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/encoder.c
- OPT_DEFS += -DENCODER_ENABLE
-endif
-
-ifeq ($(strip $(VELOCIKEY_ENABLE)), yes)
- OPT_DEFS += -DVELOCIKEY_ENABLE
- SRC += $(QUANTUM_DIR)/velocikey.c
-endif
-
ifeq ($(strip $(ORYX_ENABLE)), yes)
WEBUSB_ENABLE := yes
SRC += $(QUANTUM_DIR)/oryx.c
@@ -479,22 +462,12 @@ endif
ifeq ($(strip $(VIA_ENABLE)), yes)
DYNAMIC_KEYMAP_ENABLE := yes
RAW_ENABLE := yes
- BOOTMAGIC_ENABLE := lite
+ BOOTMAGIC_ENABLE := yes
SRC += $(QUANTUM_DIR)/via.c
OPT_DEFS += -DVIA_ENABLE
endif
-ifeq ($(strip $(DYNAMIC_KEYMAP_ENABLE)), yes)
- OPT_DEFS += -DDYNAMIC_KEYMAP_ENABLE
- SRC += $(QUANTUM_DIR)/dynamic_keymap.c
-endif
-
-ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
- OPT_DEFS += -DDIP_SWITCH_ENABLE
- SRC += $(QUANTUM_DIR)/dip_switch.c
-endif
-
-VALID_MAGIC_TYPES := yes lite
+VALID_MAGIC_TYPES := yes
BOOTMAGIC_ENABLE ?= no
ifneq ($(strip $(BOOTMAGIC_ENABLE)), no)
ifeq ($(filter $(BOOTMAGIC_ENABLE),$(VALID_MAGIC_TYPES)),)
@@ -573,23 +546,19 @@ ifeq ($(strip $(CRC_ENABLE)), yes)
SRC += crc.c
endif
-HAPTIC_ENABLE ?= no
-ifneq ($(strip $(HAPTIC_ENABLE)),no)
+ifeq ($(strip $(HAPTIC_ENABLE)),yes)
COMMON_VPATH += $(DRIVER_PATH)/haptic
- OPT_DEFS += -DHAPTIC_ENABLE
- SRC += $(QUANTUM_DIR)/haptic.c
- SRC += $(QUANTUM_DIR)/process_keycode/process_haptic.c
-endif
-ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), )
- SRC += DRV2605L.c
- QUANTUM_LIB_SRC += i2c_master.c
- OPT_DEFS += -DDRV2605L
-endif
+ ifneq ($(filter DRV2605L, $(HAPTIC_DRIVER)), )
+ SRC += DRV2605L.c
+ QUANTUM_LIB_SRC += i2c_master.c
+ OPT_DEFS += -DDRV2605L
+ endif
-ifneq ($(filter SOLENOID, $(HAPTIC_ENABLE)), )
- SRC += solenoid.c
- OPT_DEFS += -DSOLENOID_ENABLE
+ ifneq ($(filter SOLENOID, $(HAPTIC_DRIVER)), )
+ SRC += solenoid.c
+ OPT_DEFS += -DSOLENOID_ENABLE
+ endif
endif
ifeq ($(strip $(HD44780_ENABLE)), yes)
@@ -622,8 +591,6 @@ ifeq ($(strip $(ST7565_ENABLE)), yes)
SRC += st7565.c
endif
-include $(DRIVER_PATH)/qwiic/qwiic.mk
-
ifeq ($(strip $(UCIS_ENABLE)), yes)
OPT_DEFS += -DUCIS_ENABLE
UNICODE_COMMON := yes
@@ -646,60 +613,52 @@ ifeq ($(strip $(UNICODE_COMMON)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_unicode_common.c
endif
-SPACE_CADET_ENABLE ?= yes
-ifeq ($(strip $(SPACE_CADET_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_space_cadet.c
- OPT_DEFS += -DSPACE_CADET_ENABLE
-endif
-
MAGIC_ENABLE ?= yes
ifeq ($(strip $(MAGIC_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_magic.c
OPT_DEFS += -DMAGIC_KEYCODE_ENABLE
endif
-GRAVE_ESC_ENABLE ?= yes
-ifeq ($(strip $(GRAVE_ESC_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_grave_esc.c
- OPT_DEFS += -DGRAVE_ESC_ENABLE
-endif
-
-ifeq ($(strip $(DYNAMIC_MACRO_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_dynamic_macro.c
- OPT_DEFS += -DDYNAMIC_MACRO_ENABLE
-endif
-
-ifeq ($(strip $(COMBO_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_combo.c
- OPT_DEFS += -DCOMBO_ENABLE
+ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
+ SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c
+ OPT_DEFS += -DAUTO_SHIFT_ENABLE
+ ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes)
+ OPT_DEFS += -DAUTO_SHIFT_MODIFIERS
+ endif
endif
-ifeq ($(strip $(KEY_OVERRIDE_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_key_override.c
- OPT_DEFS += -DKEY_OVERRIDE_ENABLE
+ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes)
+ PS2_ENABLE := yes
+ SRC += ps2_mouse.c
+ OPT_DEFS += -DPS2_MOUSE_ENABLE
+ OPT_DEFS += -DMOUSE_ENABLE
endif
-ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c
- OPT_DEFS += -DTAP_DANCE_ENABLE
+ifeq ($(strip $(PS2_USE_BUSYWAIT)), yes)
+ PS2_ENABLE := yes
+ SRC += ps2_busywait.c
+ SRC += ps2_io_avr.c
+ OPT_DEFS += -DPS2_USE_BUSYWAIT
endif
-ifeq ($(strip $(KEY_LOCK_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_key_lock.c
- OPT_DEFS += -DKEY_LOCK_ENABLE
+ifeq ($(strip $(PS2_USE_INT)), yes)
+ PS2_ENABLE := yes
+ SRC += ps2_interrupt.c
+ SRC += ps2_io.c
+ OPT_DEFS += -DPS2_USE_INT
endif
-ifeq ($(strip $(LEADER_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_leader.c
- OPT_DEFS += -DLEADER_ENABLE
+ifeq ($(strip $(PS2_USE_USART)), yes)
+ PS2_ENABLE := yes
+ SRC += ps2_usart.c
+ SRC += ps2_io.c
+ OPT_DEFS += -DPS2_USE_USART
endif
-ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c
- OPT_DEFS += -DAUTO_SHIFT_ENABLE
- ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes)
- OPT_DEFS += -DAUTO_SHIFT_MODIFIERS
- endif
+ifeq ($(strip $(PS2_ENABLE)), yes)
+ COMMON_VPATH += $(DRIVER_PATH)/ps2
+ COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/ps2
+ OPT_DEFS += -DPS2_ENABLE
endif
JOYSTICK_ENABLE ?= no
@@ -722,11 +681,6 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), yes)
endif
endif
-DIGITIZER_ENABLE ?= no
-ifneq ($(strip $(DIGITIZER_ENABLE)), no)
- SRC += $(QUANTUM_DIR)/digitizer.c
-endif
-
USBPD_ENABLE ?= no
VALID_USBPD_DRIVER_TYPES = custom vendor
USBPD_DRIVER ?= vendor
@@ -750,3 +704,27 @@ ifeq ($(strip $(USBPD_ENABLE)), yes)
endif
endif
endif
+
+BLUETOOTH_ENABLE ?= no
+VALID_BLUETOOTH_DRIVER_TYPES := AdafruitBLE RN42 custom
+ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
+ ifeq ($(filter $(strip $(BLUETOOTH_DRIVER)),$(VALID_BLUETOOTH_DRIVER_TYPES)),)
+ $(error "$(BLUETOOTH_DRIVER)" is not a valid Bluetooth driver type)
+ endif
+ OPT_DEFS += -DBLUETOOTH_ENABLE
+ NO_USB_STARTUP_CHECK := yes
+ COMMON_VPATH += $(DRIVER_PATH)/bluetooth
+ SRC += outputselect.c
+
+ ifeq ($(strip $(BLUETOOTH_DRIVER)), AdafruitBLE)
+ OPT_DEFS += -DMODULE_ADAFRUIT_BLE
+ SRC += analog.c
+ SRC += $(DRIVER_PATH)/bluetooth/adafruit_ble.cpp
+ QUANTUM_LIB_SRC += spi_master.c
+ endif
+
+ ifeq ($(strip $(BLUETOOTH_DRIVER)), RN42)
+ OPT_DEFS += -DMODULE_RN42
+ SRC += $(TMK_DIR)/protocol/serial_uart.c
+ endif
+endif
diff --git a/data/mappings/info_config.json b/data/mappings/info_config.json
index 72bb0f4a1c..3cb64dd3a2 100644
--- a/data/mappings/info_config.json
+++ b/data/mappings/info_config.json
@@ -68,7 +68,7 @@
"RGBLIGHT_SLEEP": {"info_key": "rgblight.sleep", "value_type": "bool"},
"RGBLIGHT_SPLIT": {"info_key": "rgblight.split", "value_type": "bool"},
"RGBW": {"info_key": "rgblight.rgbw", "value_type": "bool"},
- "PRODUCT": {"info_key": "keyboard_folder", "to_json": false},
+ "PRODUCT": {"info_key": "keyboard_name", "warn_duplicate": false},
"PRODUCT_ID": {"info_key": "usb.pid", "value_type": "hex"},
"VENDOR_ID": {"info_key": "usb.vid", "value_type": "hex"},
"QMK_ESC_OUTPUT": {"info_key": "qmk_lufa_bootloader.esc_output"},
@@ -76,6 +76,7 @@
"QMK_KEYS_PER_SCAN": {"info_key": "qmk.keys_per_scan", "value_type": "int"},
"QMK_LED": {"info_key": "qmk_lufa_bootloader.led"},
"QMK_SPEAKER": {"info_key": "qmk_lufa_bootloader.speaker"},
+ "SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "bool"},
"SPLIT_MODS_ENABLE": {"info_key": "split.transport.sync_modifiers", "value_type": "bool"},
"SPLIT_TRANSPORT_MIRROR": {"info_key": "split.transport.sync_matrix_state", "value_type": "bool"},
"SPLIT_USB_DETECT": {"info_key": "split.usb_detect.enabled", "value_type": "bool"},
diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema
index 15f407fce4..308f9b782b 100644
--- a/data/schemas/keyboard.jsonschema
+++ b/data/schemas/keyboard.jsonschema
@@ -13,12 +13,13 @@
},
"processor": {
"type": "string",
- "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66F18", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F407", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L412", "STM32L422", "STM32L433", "STM32L443", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"]
+ "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66FX1M0", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F405", "STM32F407", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L412", "STM32L422", "STM32L433", "STM32L443", "GD32VF103", "WB32F3G71", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"]
},
"audio": {
"type": "object",
"additionalProperties": false,
"properties": {
+ "macro_beep": {"type": "boolean"},
"pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
"voices": {"type": "boolean"}
}
@@ -56,7 +57,7 @@
},
"bootloader": {
"type": "string",
- "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "unknown", "usbasploader", "USBasp", "tinyuf2"],
+ "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "micronucleus", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "gd32v-dfu", "wb32-dfu", "unknown", "usbasploader", "USBasp", "tinyuf2"],
},
"bootloader_instructions": {
"type": "string",
diff --git a/data/schemas/keymap.jsonschema b/data/schemas/keymap.jsonschema
index a4bdab966b..faa250a942 100644
--- a/data/schemas/keymap.jsonschema
+++ b/data/schemas/keymap.jsonschema
@@ -5,6 +5,7 @@
"type": "object",
"properties": {
"author": {"type": "string"},
+ "host_language": {"$ref": "qmk.definitions.v1#/text_identifier"},
"keyboard": {"$ref": "qmk.definitions.v1#/text_identifier"},
"keymap": {"$ref": "qmk.definitions.v1#/text_identifier"},
"layout": {"$ref": "qmk.definitions.v1#/layout_macro"},
@@ -15,10 +16,42 @@
"items": {"type": "string"}
}
},
+ "macros": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "action": {
+ "type": "string",
+ "enum": ['beep', 'delay', 'down', 'tap', 'up']
+ },
+ "keycodes": {
+ "type": "array",
+ "items": {
+ "$ref": "qmk.definitions.v1#/text_identifier"
+ }
+ },
+ "duration": {
+ "$ref": "qmk.definitions.v1#/unsigned_int"
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
"config": {"$ref": "qmk.keyboard.v1"},
"notes": {
"type": "string",
"description": "asdf"
}
}
-} \ No newline at end of file
+}
diff --git a/data/templates/avr/config.h b/data/templates/avr/config.h
index 4192bbcfa2..7c15e8e704 100644
--- a/data/templates/avr/config.h
+++ b/data/templates/avr/config.h
@@ -1,19 +1,5 @@
-/*
-Copyright %YEAR% %YOUR_NAME%
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -23,8 +9,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x0000
#define DEVICE_VER 0x0001
-#define MANUFACTURER %YOUR_NAME%
-#define PRODUCT %KEYBOARD%
+#define MANUFACTURER %(USER_NAME)s
+#define PRODUCT %(KEYBOARD)s
/* key matrix size */
#define MATRIX_ROWS 2
diff --git a/data/templates/avr/readme.md b/data/templates/avr/readme.md
index b099ed726d..207850e065 100644
--- a/data/templates/avr/readme.md
+++ b/data/templates/avr/readme.md
@@ -1,20 +1,20 @@
-# %KEYBOARD%
+# %(KEYBOARD)s
-![%KEYBOARD%](imgur.com image replace me!)
+![%(KEYBOARD)s](imgur.com image replace me!)
*A short description of the keyboard/project*
-* Keyboard Maintainer: [%YOUR_NAME%](https://github.com/yourusername)
+* Keyboard Maintainer: [%(YOUR_NAME)s](https://github.com/%(USER_NAME)s)
* Hardware Supported: *The PCBs, controllers supported*
* Hardware Availability: *Links to where you can find this hardware*
Make example for this keyboard (after setting up your build environment):
- make %KEYBOARD%:default
+ make %(KEYBOARD)s:default
Flashing example for this keyboard:
- make %KEYBOARD%:default:flash
+ make %(KEYBOARD)s:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
diff --git a/data/templates/avr/rules.mk b/data/templates/avr/rules.mk
index 9906266f48..d2109f6250 100644
--- a/data/templates/avr/rules.mk
+++ b/data/templates/avr/rules.mk
@@ -12,8 +12,6 @@ MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
-# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
-SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = no # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
diff --git a/data/templates/base/%(KEYBOARD)s.c b/data/templates/base/%(KEYBOARD)s.c
new file mode 100644
index 0000000000..0c509aff65
--- /dev/null
+++ b/data/templates/base/%(KEYBOARD)s.c
@@ -0,0 +1,4 @@
+// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "%(KEYBOARD)s.h"
diff --git a/data/templates/base/%(KEYBOARD)s.h b/data/templates/base/%(KEYBOARD)s.h
new file mode 100644
index 0000000000..3e8ca3912d
--- /dev/null
+++ b/data/templates/base/%(KEYBOARD)s.h
@@ -0,0 +1,22 @@
+// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "quantum.h"
+
+/* This is a shortcut to help you visually see your layout.
+ *
+ * The first section contains all of the arguments representing the physical
+ * layout of the board and position of the keys.
+ *
+ * The second converts the arguments into a two-dimensional array which
+ * represents the switch matrix.
+ */
+#define LAYOUT( \
+ k00, k01, k02, \
+ k10, k12 \
+) { \
+ { k00, k01, k02 }, \
+ { k10, KC_NO, k12 } \
+}
diff --git a/data/templates/base/info.json b/data/templates/base/info.json
index 3993d85467..a50ccba7bf 100644
--- a/data/templates/base/info.json
+++ b/data/templates/base/info.json
@@ -1,7 +1,7 @@
{
- "keyboard_name": "%KEYBOARD%",
+ "keyboard_name": "%(KEYBOARD)s",
"url": "",
- "maintainer": "%YOUR_NAME%",
+ "maintainer": "%(USER_NAME)s",
"layouts": {
"LAYOUT": {
"layout": [
diff --git a/data/templates/base/keymaps/default/keymap.c b/data/templates/base/keymaps/default/keymap.c
index b8ffb0156c..3fec3d5120 100644
--- a/data/templates/base/keymaps/default/keymap.c
+++ b/data/templates/base/keymaps/default/keymap.c
@@ -1,18 +1,6 @@
-/* Copyright %YEAR% %YOUR_NAME%
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
+// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include QMK_KEYBOARD_H
// Defines names for use in layer keycodes and the keymap
@@ -21,15 +9,6 @@ enum layer_names {
_FN
};
-// Defines the keycodes used by our macros in process_record_user
-enum custom_keycodes {
- QMKBEST = SAFE_RANGE,
- QMKURL
-};
-
-// Defines the keycodes used by our macros in process_record_user
-enum custom_keycodes { QMKBEST = SAFE_RANGE, QMKURL };
-
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Base */
[_BASE] = LAYOUT(
@@ -37,29 +16,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TAB, KC_SPC
),
[_FN] = LAYOUT(
- QMKBEST, QMKURL, _______,
+ _______, _______, _______,
RESET, XXXXXXX
)
};
-
-bool process_record_user(uint16_t keycode, keyrecord_t *record) {
- switch (keycode) {
- case QMKBEST:
- if (record->event.pressed) {
- // when keycode QMKBEST is pressed
- SEND_STRING("QMK is the best thing ever!");
- } else {
- // when keycode QMKBEST is released
- }
- break;
- case QMKURL:
- if (record->event.pressed) {
- // when keycode QMKURL is pressed
- SEND_STRING("https://qmk.fm/\n");
- } else {
- // when keycode QMKURL is released
- }
- break;
- }
- return true;
-}
diff --git a/data/templates/base/keymaps/default/readme.md b/data/templates/base/keymaps/default/readme.md
index e052ed80f1..63a0643275 100644
--- a/data/templates/base/keymaps/default/readme.md
+++ b/data/templates/base/keymaps/default/readme.md
@@ -1 +1 @@
-# The default keymap for %KEYBOARD%
+# The default keymap for %(KEYBOARD)s
diff --git a/data/templates/ps2avrgb/config.h b/data/templates/ps2avrgb/config.h
index 6150bcce6d..876a60252f 100644
--- a/data/templates/ps2avrgb/config.h
+++ b/data/templates/ps2avrgb/config.h
@@ -1,19 +1,5 @@
-/*
-Copyright %YEAR% %YOUR_NAME%
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s)
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -23,8 +9,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x0000
#define DEVICE_VER 0x0001
-#define MANUFACTURER %YOUR_NAME%
-#define PRODUCT %KEYBOARD%
+#define MANUFACTURER %(USER_NAME)s
+#define PRODUCT %(KEYBOARD)s
/* key matrix size */
#define MATRIX_ROWS 8
diff --git a/data/templates/ps2avrgb/readme.md b/data/templates/ps2avrgb/readme.md
index 94063f9ebc..a2ac4495b6 100644
--- a/data/templates/ps2avrgb/readme.md
+++ b/data/templates/ps2avrgb/readme.md
@@ -1,20 +1,20 @@
-# %KEYBOARD%
+# %(KEYBOARD)s
-![%KEYBOARD%](imgur.com image replace me!)
+![%(KEYBOARD)s](imgur.com image replace me!)
*A short description of the keyboard/project*
-* Keyboard Maintainer: [%YOUR_NAME%](https://github.com/yourusername)
+* Keyboard Maintainer: [%(YOUR_NAME)s](https://github.com/yourusername)
* Hardware Supported: *The PCBs, controllers supported*
* Hardware Availability: *Links to where you can find this hardware*
Make example for this keyboard (after setting up your build environment):
- make %KEYBOARD%:default
+ make %(KEYBOARD)s:default
Flashing example for this keyboard ([after setting up the bootloadHID flashing environment](https://docs.qmk.fm/#/flashing_bootloadhid))
- make %KEYBOARD%:default:flash
+ make %(KEYBOARD)s:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
diff --git a/data/templates/ps2avrgb/rules.mk b/data/templates/ps2avrgb/rules.mk
index b374eca336..1bbfa8fa0e 100644
--- a/data/templates/ps2avrgb/rules.mk
+++ b/data/templates/ps2avrgb/rules.mk
@@ -12,8 +12,6 @@ MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
-# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
-SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
WS2812_DRIVER = i2c
diff --git a/doxygen-todo b/doxygen-todo
index 643a0df1da..4151627e4a 100644
--- a/doxygen-todo
+++ b/doxygen-todo
@@ -6,22 +6,8 @@ tmk_core/protocol/midi/bytequeue
tmk_core/protocol/midi/Config
tmk_core/protocol/usb_hid
tmk_core/protocol/vusb
-tmk_core/tool
-tmk_core/tool/chibios
quantum
-quantum/api
quantum/audio
quantum/keymap_extras
quantum/process_keycode
-quantum/serial_link
-quantum/serial_link/protocol
-quantum/serial_link/system
-quantum/serial_link/tests
-quantum/tools
-quantum/visualizer
-quantum/visualizer/resources
drivers
-drivers/ugfx
-drivers/ugfx/gdisp
-drivers/ugfx/gdisp/is31fl3731c
-drivers/ugfx/gdisp/st7565
diff --git a/tmk_core/protocol/lufa/adafruit_ble.cpp b/drivers/bluetooth/adafruit_ble.cpp
index 3f2cc35734..34a780e9a5 100644
--- a/tmk_core/protocol/lufa/adafruit_ble.cpp
+++ b/drivers/bluetooth/adafruit_ble.cpp
@@ -16,24 +16,22 @@
// These are the pin assignments for the 32u4 boards.
// You may define them to something else in your config.h
// if yours is wired up differently.
-#ifndef AdafruitBleResetPin
-# define AdafruitBleResetPin D4
+#ifndef ADAFRUIT_BLE_RST_PIN
+# define ADAFRUIT_BLE_RST_PIN D4
#endif
-#ifndef AdafruitBleCSPin
-# define AdafruitBleCSPin B4
+#ifndef ADAFRUIT_BLE_CS_PIN
+# define ADAFRUIT_BLE_CS_PIN B4
#endif
-#ifndef AdafruitBleIRQPin
-# define AdafruitBleIRQPin E6
+#ifndef ADAFRUIT_BLE_IRQ_PIN
+# define ADAFRUIT_BLE_IRQ_PIN E6
#endif
-#ifndef AdafruitBleSpiClockSpeed
-# define AdafruitBleSpiClockSpeed 4000000UL // SCK frequency
+#ifndef ADAFRUIT_BLE_SCK_DIVISOR
+# define ADAFRUIT_BLE_SCK_DIVISOR 2 // 4MHz SCK/8MHz CPU, calculated for Feather 32U4 BLE
#endif
-#define SCK_DIVISOR (F_CPU / AdafruitBleSpiClockSpeed)
-
#define SAMPLE_BATTERY
#define ConnectionUpdateInterval 1000 /* milliseconds */
@@ -145,7 +143,7 @@ static bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool ver
// Send a single SDEP packet
static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) {
- spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR);
+ spi_start(ADAFRUIT_BLE_CS_PIN, false, 0, ADAFRUIT_BLE_SCK_DIVISOR);
uint16_t timerStart = timer_read();
bool success = false;
bool ready = false;
@@ -159,7 +157,7 @@ static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) {
// Release it and let it initialize
spi_stop();
wait_us(SdepBackOff);
- spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR);
+ spi_start(ADAFRUIT_BLE_CS_PIN, false, 0, ADAFRUIT_BLE_SCK_DIVISOR);
} while (timer_elapsed(timerStart) < timeout);
if (ready) {
@@ -192,7 +190,7 @@ static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) {
bool ready = false;
do {
- ready = readPin(AdafruitBleIRQPin);
+ ready = readPin(ADAFRUIT_BLE_IRQ_PIN);
if (ready) {
break;
}
@@ -200,7 +198,7 @@ static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) {
} while (timer_elapsed(timerStart) < timeout);
if (ready) {
- spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR);
+ spi_start(ADAFRUIT_BLE_CS_PIN, false, 0, ADAFRUIT_BLE_SCK_DIVISOR);
do {
// Read the command type, waiting for the data to be ready
@@ -209,7 +207,7 @@ static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) {
// Release it and let it initialize
spi_stop();
wait_us(SdepBackOff);
- spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR);
+ spi_start(ADAFRUIT_BLE_CS_PIN, false, 0, ADAFRUIT_BLE_SCK_DIVISOR);
continue;
}
@@ -235,7 +233,7 @@ static void resp_buf_read_one(bool greedy) {
return;
}
- if (readPin(AdafruitBleIRQPin)) {
+ if (readPin(ADAFRUIT_BLE_IRQ_PIN)) {
struct sdep_msg msg;
again:
@@ -246,7 +244,7 @@ static void resp_buf_read_one(bool greedy) {
dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send));
}
- if (greedy && resp_buf.peek(last_send) && readPin(AdafruitBleIRQPin)) {
+ if (greedy && resp_buf.peek(last_send) && readPin(ADAFRUIT_BLE_IRQ_PIN)) {
goto again;
}
}
@@ -297,16 +295,16 @@ static bool ble_init(void) {
state.configured = false;
state.is_connected = false;
- setPinInput(AdafruitBleIRQPin);
+ setPinInput(ADAFRUIT_BLE_IRQ_PIN);
spi_init();
// Perform a hardware reset
- setPinOutput(AdafruitBleResetPin);
- writePinHigh(AdafruitBleResetPin);
- writePinLow(AdafruitBleResetPin);
+ setPinOutput(ADAFRUIT_BLE_RST_PIN);
+ writePinHigh(ADAFRUIT_BLE_RST_PIN);
+ writePinLow(ADAFRUIT_BLE_RST_PIN);
wait_ms(10);
- writePinHigh(AdafruitBleResetPin);
+ writePinHigh(ADAFRUIT_BLE_RST_PIN);
wait_ms(1000); // Give it a second to initialize
@@ -509,7 +507,7 @@ void adafruit_ble_task(void) {
resp_buf_read_one(true);
send_buf_send_one(SdepShortTimeout);
- if (resp_buf.empty() && (state.event_flags & UsingEvents) && readPin(AdafruitBleIRQPin)) {
+ if (resp_buf.empty() && (state.event_flags & UsingEvents) && readPin(ADAFRUIT_BLE_IRQ_PIN)) {
// Must be an event update
if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) {
uint32_t mask = strtoul(resbuf, NULL, 16);
diff --git a/tmk_core/protocol/lufa/adafruit_ble.h b/drivers/bluetooth/adafruit_ble.h
index b43e0771d9..b43e0771d9 100644
--- a/tmk_core/protocol/lufa/adafruit_ble.h
+++ b/drivers/bluetooth/adafruit_ble.h
diff --git a/tmk_core/protocol/lufa/outputselect.c b/drivers/bluetooth/outputselect.c
index f758c65280..f758c65280 100644
--- a/tmk_core/protocol/lufa/outputselect.c
+++ b/drivers/bluetooth/outputselect.c
diff --git a/tmk_core/protocol/lufa/outputselect.h b/drivers/bluetooth/outputselect.h
index c4548e1122..c4548e1122 100644
--- a/tmk_core/protocol/lufa/outputselect.h
+++ b/drivers/bluetooth/outputselect.h
diff --git a/tmk_core/protocol/lufa/ringbuffer.hpp b/drivers/bluetooth/ringbuffer.hpp
index 70a3c4881d..70a3c4881d 100644
--- a/tmk_core/protocol/lufa/ringbuffer.hpp
+++ b/drivers/bluetooth/ringbuffer.hpp
diff --git a/drivers/haptic/solenoid.c b/drivers/haptic/solenoid.c
index 25cf344655..7a09940f78 100644
--- a/drivers/haptic/solenoid.c
+++ b/drivers/haptic/solenoid.c
@@ -19,6 +19,7 @@
#include "solenoid.h"
#include "haptic.h"
#include "gpio.h"
+#include "usb_device_state.h"
bool solenoid_on = false;
bool solenoid_buzzing = false;
@@ -36,7 +37,7 @@ void solenoid_set_buzz(int buzz) { haptic_set_buzz(buzz); }
void solenoid_set_dwell(uint8_t dwell) { solenoid_dwell = dwell; }
void solenoid_stop(void) {
- writePinLow(SOLENOID_PIN);
+ SOLENOID_PIN_WRITE_INACTIVE();
solenoid_on = false;
solenoid_buzzing = false;
}
@@ -48,7 +49,7 @@ void solenoid_fire(void) {
solenoid_on = true;
solenoid_buzzing = true;
solenoid_start = timer_read();
- writePinHigh(SOLENOID_PIN);
+ SOLENOID_PIN_WRITE_ACTIVE();
}
void solenoid_check(void) {
@@ -69,20 +70,23 @@ void solenoid_check(void) {
if ((elapsed % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) {
if (!solenoid_buzzing) {
solenoid_buzzing = true;
- writePinHigh(SOLENOID_PIN);
+ SOLENOID_PIN_WRITE_ACTIVE();
}
} else {
if (solenoid_buzzing) {
solenoid_buzzing = false;
- writePinLow(SOLENOID_PIN);
+ SOLENOID_PIN_WRITE_INACTIVE();
}
}
}
}
void solenoid_setup(void) {
+ SOLENOID_PIN_WRITE_INACTIVE();
setPinOutput(SOLENOID_PIN);
- solenoid_fire();
+ if ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED)) {
+ solenoid_fire();
+ }
}
-void solenoid_shutdown(void) { writePinLow(SOLENOID_PIN); }
+void solenoid_shutdown(void) { SOLENOID_PIN_WRITE_INACTIVE(); }
diff --git a/drivers/haptic/solenoid.h b/drivers/haptic/solenoid.h
index f2a3bc4c30..653148154f 100644
--- a/drivers/haptic/solenoid.h
+++ b/drivers/haptic/solenoid.h
@@ -49,6 +49,14 @@
# error SOLENOID_PIN not defined
#endif
+#ifdef SOLENOID_PIN_ACTIVE_LOW
+# define SOLENOID_PIN_WRITE_ACTIVE() writePinLow(SOLENOID_PIN)
+# define SOLENOID_PIN_WRITE_INACTIVE() writePinHigh(SOLENOID_PIN)
+#else
+# define SOLENOID_PIN_WRITE_ACTIVE() writePinHigh(SOLENOID_PIN)
+# define SOLENOID_PIN_WRITE_INACTIVE() writePinLow(SOLENOID_PIN)
+#endif
+
void solenoid_buzz_on(void);
void solenoid_buzz_off(void);
void solenoid_set_buzz(int buzz);
diff --git a/drivers/led/apa102.c b/drivers/led/apa102.c
index 7396dc3c55..00e7eb4505 100644
--- a/drivers/led/apa102.c
+++ b/drivers/led/apa102.c
@@ -24,8 +24,8 @@
# elif defined(PROTOCOL_CHIBIOS)
# include "hal.h"
-# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
-# define APA102_NOPS (100 / (1000000000L / (STM32_SYSCLK / 4))) // This calculates how many loops of 4 nops to run to delay 100 ns
+# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(GD32VF103)
+# define APA102_NOPS (100 / (1000000000L / (CPU_CLOCK / 4))) // This calculates how many loops of 4 nops to run to delay 100 ns
# else
# error("APA102_NOPS configuration required")
# define APA102_NOPS 0 // this just pleases the compile so the above error is easier to spot
diff --git a/drivers/led/aw20216.c b/drivers/led/aw20216.c
index c608c0ab44..2c7ff8f088 100644
--- a/drivers/led/aw20216.c
+++ b/drivers/led/aw20216.c
@@ -119,7 +119,8 @@ void AW20216_init(pin_t cs_pin, pin_t en_pin) {
}
void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
- aw_led led = g_aw_leds[index];
+ aw_led led;
+ memcpy_P(&led, (&g_aw_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green;
diff --git a/drivers/led/aw20216.h b/drivers/led/aw20216.h
index 97ac6dc5bf..0a17050fed 100644
--- a/drivers/led/aw20216.h
+++ b/drivers/led/aw20216.h
@@ -28,7 +28,7 @@ typedef struct aw_led {
uint8_t b;
} aw_led;
-extern const aw_led __flash g_aw_leds[DRIVER_LED_TOTAL];
+extern const aw_led PROGMEM g_aw_leds[DRIVER_LED_TOTAL];
void AW20216_init(pin_t cs_pin, pin_t en_pin);
void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
diff --git a/drivers/led/ckled2001.c b/drivers/led/ckled2001.c
new file mode 100644
index 0000000000..990e50cb60
--- /dev/null
+++ b/drivers/led/ckled2001.c
@@ -0,0 +1,228 @@
+/* Copyright 2021 @ Keychron (https://www.keychron.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ckled2001.h"
+#include "i2c_master.h"
+#include "wait.h"
+
+#ifndef CKLED2001_TIMEOUT
+# define CKLED2001_TIMEOUT 100
+#endif
+
+#ifndef CKLED2001_PERSISTENCE
+# define CKLED2001_PERSISTENCE 0
+#endif
+
+#ifndef PHASE_CHANNEL
+# define PHASE_CHANNEL MSKPHASE_12CHANNEL
+#endif
+
+// Transfer buffer for TWITransmitData()
+uint8_t g_twi_transfer_buffer[20];
+
+// These buffers match the CKLED2001 PWM registers.
+// The control buffers match the PG0 LED On/Off registers.
+// Storing them like this is optimal for I2C transfers to the registers.
+// We could optimize this and take out the unused registers from these
+// buffers and the transfers in CKLED2001_write_pwm_buffer() but it's
+// probably not worth the extra complexity.
+uint8_t g_pwm_buffer[DRIVER_COUNT][192];
+bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
+
+uint8_t g_led_control_registers[DRIVER_COUNT][24] = {0};
+bool g_led_control_registers_update_required[DRIVER_COUNT] = {false};
+
+bool CKLED2001_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
+ // If the transaction fails function returns false.
+ g_twi_transfer_buffer[0] = reg;
+ g_twi_transfer_buffer[1] = data;
+
+#if CKLED2001_PERSISTENCE > 0
+ for (uint8_t i = 0; i < CKLED2001_PERSISTENCE; i++) {
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, CKLED2001_TIMEOUT) != 0) {
+ return false;
+ }
+ }
+#else
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, CKLED2001_TIMEOUT) != 0) {
+ return false;
+ }
+#endif
+ return true;
+}
+
+bool CKLED2001_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
+ // Assumes PG1 is already selected.
+ // If any of the transactions fails function returns false.
+ // Transmit PWM registers in 12 transfers of 16 bytes.
+ // g_twi_transfer_buffer[] is 20 bytes
+
+ // Iterate over the pwm_buffer contents at 16 byte intervals.
+ for (int i = 0; i < 192; i += 16) {
+ g_twi_transfer_buffer[0] = i;
+ // Copy the data from i to i+15.
+ // Device will auto-increment register for data after the first byte
+ // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer.
+ for (int j = 0; j < 16; j++) {
+ g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
+ }
+
+#if CKLED2001_PERSISTENCE > 0
+ for (uint8_t i = 0; i < CKLED2001_PERSISTENCE; i++) {
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, CKLED2001_TIMEOUT) != 0) {
+ return false;
+ }
+ }
+#else
+ if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, CKLED2001_TIMEOUT) != 0) {
+ return false;
+ }
+#endif
+ }
+ return true;
+}
+
+void CKLED2001_init(uint8_t addr) {
+ // Select to function page
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, FUNCTION_PAGE);
+ // Setting LED driver to shutdown mode
+ CKLED2001_write_register(addr, CONFIGURATION_REG, MSKSW_SHUT_DOWN_MODE);
+ // Setting internal channel pulldown/pullup
+ CKLED2001_write_register(addr, PDU_REG, MSKSET_CA_CB_CHANNEL);
+ // Select number of scan phase
+ CKLED2001_write_register(addr, SCAN_PHASE_REG, PHASE_CHANNEL);
+ // Setting PWM Delay Phase
+ CKLED2001_write_register(addr, SLEW_RATE_CONTROL_MODE1_REG, MSKPWM_DELAY_PHASE_ENABLE);
+ // Setting Driving/Sinking Channel Slew Rate
+ CKLED2001_write_register(addr, SLEW_RATE_CONTROL_MODE2_REG, MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE);
+ // Setting Iref
+ CKLED2001_write_register(addr, SOFTWARE_SLEEP_REG, MSKSLEEP_DISABLE);
+ // Set LED CONTROL PAGE (Page 0)
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_CONTROL_PAGE);
+ for (int i = 0; i < LED_CONTROL_ON_OFF_LENGTH; i++) {
+ CKLED2001_write_register(addr, i, 0x00);
+ }
+
+ // Set PWM PAGE (Page 1)
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_PWM_PAGE);
+ for (int i = 0; i < LED_CURRENT_TUNE_LENGTH; i++) {
+ CKLED2001_write_register(addr, i, 0x00);
+ }
+
+ // Set CURRENT PAGE (Page 4)
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, CURRENT_TUNE_PAGE);
+ for (int i = 0; i < LED_CURRENT_TUNE_LENGTH; i++) {
+ CKLED2001_write_register(addr, i, 0xFF);
+ }
+
+ // Enable LEDs ON/OFF
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_CONTROL_PAGE);
+ for (int i = 0; i < LED_CONTROL_ON_OFF_LENGTH; i++) {
+ CKLED2001_write_register(addr, i, 0xFF);
+ }
+
+ // Select to function page
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, FUNCTION_PAGE);
+ // Setting LED driver to normal mode
+ CKLED2001_write_register(addr, CONFIGURATION_REG, MSKSW_NORMAL_MODE);
+}
+
+void CKLED2001_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+ ckled2001_led led;
+ if (index >= 0 && index < DRIVER_LED_TOTAL) {
+ memcpy_P(&led, (&g_ckled2001_leds[index]), sizeof(led));
+
+ g_pwm_buffer[led.driver][led.r] = red;
+ g_pwm_buffer[led.driver][led.g] = green;
+ g_pwm_buffer[led.driver][led.b] = blue;
+ g_pwm_buffer_update_required[led.driver] = true;
+ }
+}
+
+void CKLED2001_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+ for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
+ CKLED2001_set_color(i, red, green, blue);
+ }
+}
+
+void CKLED2001_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
+ ckled2001_led led;
+ memcpy_P(&led, (&g_ckled2001_leds[index]), sizeof(led));
+
+ uint8_t control_register_r = led.r / 8;
+ uint8_t control_register_g = led.g / 8;
+ uint8_t control_register_b = led.b / 8;
+ uint8_t bit_r = led.r % 8;
+ uint8_t bit_g = led.g % 8;
+ uint8_t bit_b = led.b % 8;
+
+ if (red) {
+ g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
+ } else {
+ g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r);
+ }
+ if (green) {
+ g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g);
+ } else {
+ g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g);
+ }
+ if (blue) {
+ g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b);
+ } else {
+ g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
+ }
+
+ g_led_control_registers_update_required[led.driver] = true;
+}
+
+void CKLED2001_update_pwm_buffers(uint8_t addr, uint8_t index) {
+ if (g_pwm_buffer_update_required[index]) {
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_PWM_PAGE);
+
+ // If any of the transactions fail we risk writing dirty PG0,
+ // refresh page 0 just in case.
+ if (!CKLED2001_write_pwm_buffer(addr, g_pwm_buffer[index])) {
+ g_led_control_registers_update_required[index] = true;
+ }
+ }
+ g_pwm_buffer_update_required[index] = false;
+}
+
+void CKLED2001_update_led_control_registers(uint8_t addr, uint8_t index) {
+ if (g_led_control_registers_update_required[index]) {
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, LED_CONTROL_PAGE);
+ for (int i = 0; i < 24; i++) {
+ CKLED2001_write_register(addr, i, g_led_control_registers[index][i]);
+ }
+ }
+ g_led_control_registers_update_required[index] = false;
+}
+
+void CKLED2001_return_normal(uint8_t addr) {
+ // Select to function page
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, FUNCTION_PAGE);
+ // Setting LED driver to normal mode
+ CKLED2001_write_register(addr, CONFIGURATION_REG, MSKSW_NORMAL_MODE);
+}
+
+void CKLED2001_shutdown(uint8_t addr) {
+ // Select to function page
+ CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, FUNCTION_PAGE);
+ // Setting LED driver to shutdown mode
+ CKLED2001_write_register(addr, CONFIGURATION_REG, MSKSW_SHUT_DOWN_MODE);
+ // Write SW Sleep Register
+ CKLED2001_write_register(addr, SOFTWARE_SLEEP_REG, MSKSLEEP_ENABLE);
+}
diff --git a/drivers/led/ckled2001.h b/drivers/led/ckled2001.h
new file mode 100644
index 0000000000..1967961d20
--- /dev/null
+++ b/drivers/led/ckled2001.h
@@ -0,0 +1,339 @@
+/* Copyright 2021 @ Keychron (https://www.keychron.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "progmem.h"
+
+typedef struct ckled2001_led {
+ uint8_t driver : 2;
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+} __attribute__((packed)) ckled2001_led;
+
+extern const ckled2001_led PROGMEM g_ckled2001_leds[DRIVER_LED_TOTAL];
+
+void CKLED2001_init(uint8_t addr);
+bool CKLED2001_write_register(uint8_t addr, uint8_t reg, uint8_t data);
+bool CKLED2001_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
+
+void CKLED2001_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
+void CKLED2001_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
+
+void CKLED2001_set_led_control_register(uint8_t index, bool red, bool green, bool blue);
+
+// This should not be called from an interrupt
+// (eg. from a timer interrupt).
+// Call this while idle (in between matrix scans).
+// If the buffer is dirty, it will update the driver with the buffer.
+void CKLED2001_update_pwm_buffers(uint8_t addr, uint8_t index);
+void CKLED2001_update_led_control_registers(uint8_t addr, uint8_t index);
+
+void CKLED2001_return_normal(uint8_t addr);
+void CKLED2001_shutdown(uint8_t addr);
+
+// Registers Page Define
+#define CONFIGURE_CMD_PAGE 0xFD
+#define LED_CONTROL_PAGE 0x00
+#define LED_PWM_PAGE 0x01
+#define FUNCTION_PAGE 0x03
+#define CURRENT_TUNE_PAGE 0x04
+
+// Function Register: address 0x00
+#define CONFIGURATION_REG 0x00
+#define MSKSW_SHUT_DOWN_MODE (0x0 << 0)
+#define MSKSW_NORMAL_MODE (0x1 << 0)
+
+#define DRIVER_ID_REG 0x11
+#define CKLED2001_ID 0x8A
+
+#define PDU_REG 0x13
+#define MSKSET_CA_CB_CHANNEL 0xAA
+#define MSKCLR_CA_CB_CHANNEL 0x00
+
+#define SCAN_PHASE_REG 0x14
+#define MSKPHASE_12CHANNEL 0x00
+#define MSKPHASE_11CHANNEL 0x01
+#define MSKPHASE_10CHANNEL 0x02
+#define MSKPHASE_9CHANNEL 0x03
+#define MSKPHASE_8CHANNEL 0x04
+#define MSKPHASE_7CHANNEL 0x05
+#define MSKPHASE_6CHANNEL 0x06
+#define MSKPHASE_5CHANNEL 0x07
+#define MSKPHASE_4CHANNEL 0x08
+#define MSKPHASE_3CHANNEL 0x09
+#define MSKPHASE_2CHANNEL 0x0A
+#define MSKPHASE_1CHANNEL 0x0B
+
+#define SLEW_RATE_CONTROL_MODE1_REG 0x15
+#define MSKPWM_DELAY_PHASE_ENABLE 0x04
+#define MSKPWM_DELAY_PHASE_DISABLE 0x00
+
+#define SLEW_RATE_CONTROL_MODE2_REG 0x16
+#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE 0xC0
+#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_DISABLE 0x00
+
+#define OPEN_SHORT_ENABLE_REG 0x17
+#define MSKOPEN_DETECTION_ENABLE (0x01 << 7)
+#define MSKOPEN_DETECTION_DISABLE (0x00)
+
+#define MSKSHORT_DETECTION_ENABLE (0x01 << 6)
+#define MSKSHORT_DETECTION_DISABLE (0x00)
+
+#define OPEN_SHORT_DUTY_REG 0x18
+#define OPEN_SHORT_FLAG_REG 0x19
+
+#define MSKOPEN_DETECTION_INTERRUPT_ENABLE (0x01 << 7)
+#define MSKOPEN_DETECTION_INTERRUPT_DISABLE (0x00)
+
+#define MSKSHORT_DETECTION_INTERRUPT_ENABLE (0x01 << 6)
+#define MSKSHORT_DETECTION_INTERRUPT_DISABLE (0x00)
+
+#define SOFTWARE_SLEEP_REG 0x1A
+#define MSKSLEEP_ENABLE 0x02
+#define MSKSLEEP_DISABLE 0x00
+
+// LED Control Registers
+#define LED_CONTROL_ON_OFF_FIRST_ADDR 0x0
+#define LED_CONTROL_ON_OFF_LAST_ADDR 0x17
+#define LED_CONTROL_ON_OFF_LENGTH ((LED_CONTROL_ON_OFF_LAST_ADDR - LED_CONTROL_ON_OFF_FIRST_ADDR) + 1)
+
+#define LED_CONTROL_OPEN_FIRST_ADDR 0x18
+#define LED_CONTROL_OPEN_LAST_ADDR 0x2F
+#define LED_CONTROL_OPEN_LENGTH ((LED_CONTROL_OPEN_LAST_ADDR - LED_CONTROL_OPEN_FIRST_ADDR) + 1)
+
+#define LED_CONTROL_SHORT_FIRST_ADDR 0x30
+#define LED_CONTROL_SHORT_LAST_ADDR 0x47
+#define LED_CONTROL_SHORT_LENGTH ((LED_CONTROL_SHORT_LAST_ADDR - LED_CONTROL_SHORT_FIRST_ADDR) + 1)
+
+#define LED_CONTROL_PAGE_LENGTH 0x48
+
+// LED Control Registers
+#define LED_PWM_FIRST_ADDR 0x00
+#define LED_PWM_LAST_ADDR 0xBF
+#define LED_PWM_LENGTH 0xC0
+
+// Current Tune Registers
+#define LED_CURRENT_TUNE_FIRST_ADDR 0x00
+#define LED_CURRENT_TUNE_LAST_ADDR 0x0B
+#define LED_CURRENT_TUNE_LENGTH 0x0C
+
+#define A_1 0x00
+#define A_2 0x01
+#define A_3 0x02
+#define A_4 0x03
+#define A_5 0x04
+#define A_6 0x05
+#define A_7 0x06
+#define A_8 0x07
+#define A_9 0x08
+#define A_10 0x09
+#define A_11 0x0A
+#define A_12 0x0B
+#define A_13 0x0C
+#define A_14 0x0D
+#define A_15 0x0E
+#define A_16 0x0F
+
+#define B_1 0x10
+#define B_2 0x11
+#define B_3 0x12
+#define B_4 0x13
+#define B_5 0x14
+#define B_6 0x15
+#define B_7 0x16
+#define B_8 0x17
+#define B_9 0x18
+#define B_10 0x19
+#define B_11 0x1A
+#define B_12 0x1B
+#define B_13 0x1C
+#define B_14 0x1D
+#define B_15 0x1E
+#define B_16 0x1F
+
+#define C_1 0x20
+#define C_2 0x21
+#define C_3 0x22
+#define C_4 0x23
+#define C_5 0x24
+#define C_6 0x25
+#define C_7 0x26
+#define C_8 0x27
+#define C_9 0x28
+#define C_10 0x29
+#define C_11 0x2A
+#define C_12 0x2B
+#define C_13 0x2C
+#define C_14 0x2D
+#define C_15 0x2E
+#define C_16 0x2F
+
+#define D_1 0x30
+#define D_2 0x31
+#define D_3 0x32
+#define D_4 0x33
+#define D_5 0x34
+#define D_6 0x35
+#define D_7 0x36
+#define D_8 0x37
+#define D_9 0x38
+#define D_10 0x39
+#define D_11 0x3A
+#define D_12 0x3B
+#define D_13 0x3C
+#define D_14 0x3D
+#define D_15 0x3E
+#define D_16 0x3F
+
+#define E_1 0x40
+#define E_2 0x41
+#define E_3 0x42
+#define E_4 0x43
+#define E_5 0x44
+#define E_6 0x45
+#define E_7 0x46
+#define E_8 0x47
+#define E_9 0x48
+#define E_10 0x49
+#define E_11 0x4A
+#define E_12 0x4B
+#define E_13 0x4C
+#define E_14 0x4D
+#define E_15 0x4E
+#define E_16 0x4F
+
+#define F_1 0x50
+#define F_2 0x51
+#define F_3 0x52
+#define F_4 0x53
+#define F_5 0x54
+#define F_6 0x55
+#define F_7 0x56
+#define F_8 0x57
+#define F_9 0x58
+#define F_10 0x59
+#define F_11 0x5A
+#define F_12 0x5B
+#define F_13 0x5C
+#define F_14 0x5D
+#define F_15 0x5E
+#define F_16 0x5F
+
+#define G_1 0x60
+#define G_2 0x61
+#define G_3 0x62
+#define G_4 0x63
+#define G_5 0x64
+#define G_6 0x65
+#define G_7 0x66
+#define G_8 0x67
+#define G_9 0x68
+#define G_10 0x69
+#define G_11 0x6A
+#define G_12 0x6B
+#define G_13 0x6C
+#define G_14 0x6D
+#define G_15 0x6E
+#define G_16 0x6F
+
+#define H_1 0x70
+#define H_2 0x71
+#define H_3 0x72
+#define H_4 0x73
+#define H_5 0x74
+#define H_6 0x75
+#define H_7 0x76
+#define H_8 0x77
+#define H_9 0x78
+#define H_10 0x79
+#define H_11 0x7A
+#define H_12 0x7B
+#define H_13 0x7C
+#define H_14 0x7D
+#define H_15 0x7E
+#define H_16 0x7F
+
+#define I_1 0x80
+#define I_2 0x81
+#define I_3 0x82
+#define I_4 0x83
+#define I_5 0x84
+#define I_6 0x85
+#define I_7 0x86
+#define I_8 0x87
+#define I_9 0x88
+#define I_10 0x89
+#define I_11 0x8A
+#define I_12 0x8B
+#define I_13 0x8C
+#define I_14 0x8D
+#define I_15 0x8E
+#define I_16 0x8F
+
+#define J_1 0x90
+#define J_2 0x91
+#define J_3 0x92
+#define J_4 0x93
+#define J_5 0x94
+#define J_6 0x95
+#define J_7 0x96
+#define J_8 0x97
+#define J_9 0x98
+#define J_10 0x99
+#define J_11 0x9A
+#define J_12 0x9B
+#define J_13 0x9C
+#define J_14 0x9D
+#define J_15 0x9E
+#define J_16 0x9F
+
+#define K_1 0xA0
+#define K_2 0xA1
+#define K_3 0xA2
+#define K_4 0xA3
+#define K_5 0xA4
+#define K_6 0xA5
+#define K_7 0xA6
+#define K_8 0xA7
+#define K_9 0xA8
+#define K_10 0xA9
+#define K_11 0xAA
+#define K_12 0xAB
+#define K_13 0xAC
+#define K_14 0xAD
+#define K_15 0xAE
+#define K_16 0xAF
+
+#define L_1 0xB0
+#define L_2 0xB1
+#define L_3 0xB2
+#define L_4 0xB3
+#define L_5 0xB4
+#define L_6 0xB5
+#define L_7 0xB6
+#define L_8 0xB7
+#define L_9 0xB8
+#define L_10 0xB9
+#define L_11 0xBA
+#define L_12 0xBB
+#define L_13 0xBC
+#define L_14 0xBD
+#define L_15 0xBE
+#define L_16 0xBF \ No newline at end of file
diff --git a/drivers/led/issi/is31fl3731-simple.c b/drivers/led/issi/is31fl3731-simple.c
index d295772f5e..f51e2e38af 100644
--- a/drivers/led/issi/is31fl3731-simple.c
+++ b/drivers/led/issi/is31fl3731-simple.c
@@ -1,6 +1,7 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2019 Clueboard
+ * Copyright 2021 Doni Crosby
*
* 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
@@ -40,6 +41,9 @@
#define ISSI_REG_PICTUREFRAME 0x01
+// Not defined in the datasheet -- See AN for IC
+#define ISSI_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting
+
#define ISSI_REG_SHUTDOWN 0x0A
#define ISSI_REG_AUDIOSYNC 0x06
@@ -144,6 +148,9 @@ void IS31FL3731_init(uint8_t addr) {
// enable software shutdown
IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00);
+#ifdef ISSI_3731_DEGHOST // set to enable de-ghosting of the array
+ IS31FL3731_write_register(addr, ISSI_REG_GHOST_IMAGE_PREVENTION, 0x10);
+#endif
// this delay was copied from other drivers, might not be needed
wait_ms(10);
@@ -186,8 +193,9 @@ void IS31FL3731_init(uint8_t addr) {
}
void IS31FL3731_set_value(int index, uint8_t value) {
+ is31_led led;
if (index >= 0 && index < DRIVER_LED_TOTAL) {
- is31_led led = g_is31_leds[index];
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
// Subtract 0x24 to get the second index of g_pwm_buffer
g_pwm_buffer[led.driver][led.v - 0x24] = value;
@@ -202,7 +210,8 @@ void IS31FL3731_set_value_all(uint8_t value) {
}
void IS31FL3731_set_led_control_register(uint8_t index, bool value) {
- is31_led led = g_is31_leds[index];
+ is31_led led;
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
uint8_t control_register = (led.v - 0x24) / 8;
uint8_t bit_value = (led.v - 0x24) % 8;
diff --git a/drivers/led/issi/is31fl3731-simple.h b/drivers/led/issi/is31fl3731-simple.h
index ecde31eed5..ded94b0470 100644
--- a/drivers/led/issi/is31fl3731-simple.h
+++ b/drivers/led/issi/is31fl3731-simple.h
@@ -27,7 +27,7 @@ typedef struct is31_led {
uint8_t v;
} __attribute__((packed)) is31_led;
-extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3731_init(uint8_t addr);
void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/led/issi/is31fl3731.c b/drivers/led/issi/is31fl3731.c
index 110bdc1be4..e6190a6b90 100644
--- a/drivers/led/issi/is31fl3731.c
+++ b/drivers/led/issi/is31fl3731.c
@@ -1,5 +1,6 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
+ * Copyright 2021 Doni Crosby
*
* 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
@@ -39,6 +40,9 @@
#define ISSI_REG_PICTUREFRAME 0x01
+// Not defined in the datasheet -- See AN for IC
+#define ISSI_REG_GHOST_IMAGE_PREVENTION 0xC2 // Set bit 4 to enable de-ghosting
+
#define ISSI_REG_SHUTDOWN 0x0A
#define ISSI_REG_AUDIOSYNC 0x06
@@ -132,6 +136,9 @@ void IS31FL3731_init(uint8_t addr) {
// enable software shutdown
IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00);
+#ifdef ISSI_3731_DEGHOST // set to enable de-ghosting of the array
+ IS31FL3731_write_register(addr, ISSI_REG_GHOST_IMAGE_PREVENTION, 0x10);
+#endif
// this delay was copied from other drivers, might not be needed
wait_ms(10);
@@ -174,8 +181,9 @@ void IS31FL3731_init(uint8_t addr) {
}
void IS31FL3731_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+ is31_led led;
if (index >= 0 && index < DRIVER_LED_TOTAL) {
- is31_led led = g_is31_leds[index];
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
// Subtract 0x24 to get the second index of g_pwm_buffer
g_pwm_buffer[led.driver][led.r - 0x24] = red;
@@ -192,7 +200,8 @@ void IS31FL3731_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL3731_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
- is31_led led = g_is31_leds[index];
+ is31_led led;
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
uint8_t control_register_r = (led.r - 0x24) / 8;
uint8_t control_register_g = (led.g - 0x24) / 8;
diff --git a/drivers/led/issi/is31fl3731.h b/drivers/led/issi/is31fl3731.h
index 803ea3ea12..6647119eba 100644
--- a/drivers/led/issi/is31fl3731.h
+++ b/drivers/led/issi/is31fl3731.h
@@ -28,7 +28,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3731_init(uint8_t addr);
void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data);
diff --git a/drivers/led/issi/is31fl3733.c b/drivers/led/issi/is31fl3733.c
index d99e5339c9..696491d070 100644
--- a/drivers/led/issi/is31fl3733.c
+++ b/drivers/led/issi/is31fl3733.c
@@ -1,6 +1,7 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
+ * Copyright 2021 Doni Crosby
*
* 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
@@ -56,6 +57,18 @@
# define ISSI_PERSISTENCE 0
#endif
+#ifndef ISSI_PWM_FREQUENCY
+# define ISSI_PWM_FREQUENCY 0b000 // PFS - IS31FL3733B only
+#endif
+
+#ifndef ISSI_SWPULLUP
+# define ISSI_SWPULLUP PUR_0R
+#endif
+
+#ifndef ISSI_CSPULLUP
+# define ISSI_CSPULLUP PUR_0R
+#endif
+
// Transfer buffer for TWITransmitData()
uint8_t g_twi_transfer_buffer[20];
@@ -154,18 +167,23 @@ void IS31FL3733_init(uint8_t addr, uint8_t sync) {
// Select PG3
IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION);
+ // Set de-ghost pull-up resistors (SWx)
+ IS31FL3733_write_register(addr, ISSI_REG_SWPULLUP, ISSI_SWPULLUP);
+ // Set de-ghost pull-down resistors (CSx)
+ IS31FL3733_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP);
// Set global current to maximum.
IS31FL3733_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
// Disable software shutdown.
- IS31FL3733_write_register(addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01);
+ IS31FL3733_write_register(addr, ISSI_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((ISSI_PWM_FREQUENCY & 0b111) << 3) | 0x01);
// Wait 10ms to ensure the device has woken up.
wait_ms(10);
}
void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+ is31_led led;
if (index >= 0 && index < DRIVER_LED_TOTAL) {
- is31_led led = g_is31_leds[index];
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green;
@@ -181,7 +199,8 @@ void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL3733_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
- is31_led led = g_is31_leds[index];
+ is31_led led;
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
uint8_t control_register_r = led.r / 8;
uint8_t control_register_g = led.g / 8;
diff --git a/drivers/led/issi/is31fl3733.h b/drivers/led/issi/is31fl3733.h
index 64fd38eb19..c5d62fed85 100644
--- a/drivers/led/issi/is31fl3733.h
+++ b/drivers/led/issi/is31fl3733.h
@@ -1,6 +1,7 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
+ * Copyright 2021 Doni Crosby
*
* 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
@@ -29,7 +30,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3733_init(uint8_t addr, uint8_t sync);
bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data);
@@ -47,6 +48,14 @@ void IS31FL3733_set_led_control_register(uint8_t index, bool red, bool green, bo
void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index);
void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index);
+#define PUR_0R 0x00 // No PUR resistor
+#define PUR_05KR 0x02 // 0.5k Ohm resistor in t_NOL
+#define PUR_3KR 0x03 // 3.0k Ohm resistor on all the time
+#define PUR_4KR 0x04 // 4.0k Ohm resistor on all the time
+#define PUR_8KR 0x05 // 8.0k Ohm resistor on all the time
+#define PUR_16KR 0x06 // 16k Ohm resistor on all the time
+#define PUR_32KR 0x07 // 32k Ohm resistor in t_NOL
+
#define A_1 0x00
#define A_2 0x01
#define A_3 0x02
diff --git a/drivers/led/issi/is31fl3736.c b/drivers/led/issi/is31fl3736.c
index 7dece1b1eb..c9a871118d 100644
--- a/drivers/led/issi/is31fl3736.c
+++ b/drivers/led/issi/is31fl3736.c
@@ -1,4 +1,5 @@
/* Copyright 2018 Jason Williams (Wilba)
+ * Copyright 2021 Doni Crosby
*
* 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
@@ -54,6 +55,14 @@
# define ISSI_PERSISTENCE 0
#endif
+#ifndef ISSI_SWPULLUP
+# define ISSI_SWPULLUP PUR_0R
+#endif
+
+#ifndef ISSI_CSPULLUP
+# define ISSI_CSPULLUP PUR_0R
+#endif
+
// Transfer buffer for TWITransmitData()
uint8_t g_twi_transfer_buffer[20];
@@ -140,6 +149,10 @@ void IS31FL3736_init(uint8_t addr) {
// Select PG3
IS31FL3736_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION);
+ // Set de-ghost pull-up resistors (SWx)
+ IS31FL3736_write_register(addr, ISSI_REG_SWPULLUP, ISSI_SWPULLUP);
+ // Set de-ghost pull-down resistors (CSx)
+ IS31FL3736_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP);
// Set global current to maximum.
IS31FL3736_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
// Disable software shutdown.
@@ -150,8 +163,9 @@ void IS31FL3736_init(uint8_t addr) {
}
void IS31FL3736_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+ is31_led led;
if (index >= 0 && index < DRIVER_LED_TOTAL) {
- is31_led led = g_is31_leds[index];
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green;
@@ -167,7 +181,8 @@ void IS31FL3736_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL3736_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
- is31_led led = g_is31_leds[index];
+ is31_led led;
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
// IS31FL3733
// The PWM register for a matrix position (0x00 to 0xBF) can be
diff --git a/drivers/led/issi/is31fl3736.h b/drivers/led/issi/is31fl3736.h
index c956c87f7c..9fbe1cc577 100644
--- a/drivers/led/issi/is31fl3736.h
+++ b/drivers/led/issi/is31fl3736.h
@@ -1,4 +1,5 @@
/* Copyright 2018 Jason Williams (Wilba)
+ * Copyright 2021 Doni Crosby
*
* 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
@@ -38,7 +39,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3736_init(uint8_t addr);
void IS31FL3736_write_register(uint8_t addr, uint8_t reg, uint8_t data);
@@ -60,6 +61,15 @@ void IS31FL3736_mono_set_led_control_register(uint8_t index, bool enabled);
void IS31FL3736_update_pwm_buffers(uint8_t addr1, uint8_t addr2);
void IS31FL3736_update_led_control_registers(uint8_t addr1, uint8_t addr2);
+#define PUR_0R 0x00 // No PUR resistor
+#define PUR_05KR 0x01 // 0.5k Ohm resistor
+#define PUR_1KR 0x02 // 1.0k Ohm resistor
+#define PUR_2KR 0x03 // 2.0k Ohm resistor
+#define PUR_4KR 0x04 // 4.0k Ohm resistor
+#define PUR_8KR 0x05 // 8.0k Ohm resistor
+#define PUR_16KR 0x06 // 16k Ohm resistor
+#define PUR_32KR 0x07 // 32k Ohm resistor
+
#define A_1 0x00
#define A_2 0x02
#define A_3 0x04
diff --git a/drivers/led/issi/is31fl3737.c b/drivers/led/issi/is31fl3737.c
index 0bb4ddd425..0722e18869 100644
--- a/drivers/led/issi/is31fl3737.c
+++ b/drivers/led/issi/is31fl3737.c
@@ -1,6 +1,7 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
+ * Copyright 2021 Doni Crosby
*
* 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
@@ -56,6 +57,14 @@
# define ISSI_PERSISTENCE 0
#endif
+#ifndef ISSI_SWPULLUP
+# define ISSI_SWPULLUP PUR_0R
+#endif
+
+#ifndef ISSI_CSPULLUP
+# define ISSI_CSPULLUP PUR_0R
+#endif
+
// Transfer buffer for TWITransmitData()
uint8_t g_twi_transfer_buffer[20];
@@ -143,6 +152,10 @@ void IS31FL3737_init(uint8_t addr) {
// Select PG3
IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION);
+ // Set de-ghost pull-up resistors (SWx)
+ IS31FL3737_write_register(addr, ISSI_REG_SWPULLUP, ISSI_SWPULLUP);
+ // Set de-ghost pull-down resistors (CSx)
+ IS31FL3737_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP);
// Set global current to maximum.
IS31FL3737_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
// Disable software shutdown.
@@ -153,8 +166,9 @@ void IS31FL3737_init(uint8_t addr) {
}
void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+ is31_led led;
if (index >= 0 && index < DRIVER_LED_TOTAL) {
- is31_led led = g_is31_leds[index];
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green;
@@ -170,7 +184,8 @@ void IS31FL3737_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
- is31_led led = g_is31_leds[index];
+ is31_led led;
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
uint8_t control_register_r = led.r / 8;
uint8_t control_register_g = led.g / 8;
diff --git a/drivers/led/issi/is31fl3737.h b/drivers/led/issi/is31fl3737.h
index 06886e9c9b..31b1a22267 100644
--- a/drivers/led/issi/is31fl3737.h
+++ b/drivers/led/issi/is31fl3737.h
@@ -1,6 +1,7 @@
/* Copyright 2017 Jason Williams
* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
+ * Copyright 2021 Doni Crosby
*
* 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
@@ -29,7 +30,7 @@ typedef struct is31_led {
uint8_t b;
} __attribute__((packed)) is31_led;
-extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3737_init(uint8_t addr);
void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data);
@@ -47,6 +48,15 @@ void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bo
void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2);
void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2);
+#define PUR_0R 0x00 // No PUR resistor
+#define PUR_05KR 0x01 // 0.5k Ohm resistor in t_NOL
+#define PUR_1KR 0x02 // 1.0k Ohm resistor in t_NOL
+#define PUR_2KR 0x03 // 2.0k Ohm resistor in t_NOL
+#define PUR_4KR 0x04 // 4.0k Ohm resistor in t_NOL
+#define PUR_8KR 0x05 // 8.0k Ohm resistor in t_NOL
+#define PUR_16KR 0x06 // 16k Ohm resistor in t_NOL
+#define PUR_32KR 0x07 // 32k Ohm resistor in t_NOL
+
#define A_1 0x00
#define A_2 0x01
#define A_3 0x02
diff --git a/drivers/led/issi/is31fl3741.c b/drivers/led/issi/is31fl3741.c
index 24a273514e..8d347a5e60 100644
--- a/drivers/led/issi/is31fl3741.c
+++ b/drivers/led/issi/is31fl3741.c
@@ -61,6 +61,14 @@
# define ISSI_PERSISTENCE 0
#endif
+#ifndef ISSI_SWPULLUP
+# define ISSI_SWPULLUP PUR_32KR
+#endif
+
+#ifndef ISSI_CSPULLUP
+# define ISSI_CSPULLUP PUR_32KR
+#endif
+
#define ISSI_MAX_LEDS 351
// Transfer buffer for TWITransmitData()
@@ -157,7 +165,7 @@ void IS31FL3741_init(uint8_t addr) {
// Set Golbal Current Control Register
IS31FL3741_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
// Set Pull up & Down for SWx CSy
- IS31FL3741_write_register(addr, ISSI_REG_PULLDOWNUP, 0x77);
+ IS31FL3741_write_register(addr, ISSI_REG_PULLDOWNUP, ((ISSI_CSPULLUP << 4) | ISSI_SWPULLUP));
// IS31FL3741_update_led_scaling_registers(addr, 0xFF, 0xFF, 0xFF);
@@ -166,8 +174,9 @@ void IS31FL3741_init(uint8_t addr) {
}
void IS31FL3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+ is31_led led;
if (index >= 0 && index < DRIVER_LED_TOTAL) {
- is31_led led = g_is31_leds[index];
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green;
@@ -183,7 +192,8 @@ void IS31FL3741_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
}
void IS31FL3741_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
- is31_led led = g_is31_leds[index];
+ is31_led led;
+ memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
if (red) {
g_scaling_registers[led.driver][led.r] = 0xFF;
diff --git a/drivers/led/issi/is31fl3741.h b/drivers/led/issi/is31fl3741.h
index 163a035233..8154f8be70 100644
--- a/drivers/led/issi/is31fl3741.h
+++ b/drivers/led/issi/is31fl3741.h
@@ -30,7 +30,7 @@ typedef struct is31_led {
uint32_t b : 10;
} __attribute__((packed)) is31_led;
-extern const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL];
+extern const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL];
void IS31FL3741_init(uint8_t addr);
void IS31FL3741_write_register(uint8_t addr, uint8_t reg, uint8_t data);
@@ -51,6 +51,15 @@ void IS31FL3741_set_scaling_registers(const is31_led *pled, uint8_t red, uint8_t
void IS31FL3741_set_pwm_buffer(const is31_led *pled, uint8_t red, uint8_t green, uint8_t blue);
+#define PUR_0R 0x00 // No PUR resistor
+#define PUR_05KR 0x01 // 0.5k Ohm resistor
+#define PUR_1KR 0x02 // 1.0k Ohm resistor
+#define PUR_2KR 0x03 // 2.0k Ohm resistor
+#define PUR_4KR 0x04 // 4.0k Ohm resistor
+#define PUR_8KR 0x05 // 8.0k Ohm resistor
+#define PUR_16KR 0x06 // 16k Ohm resistor
+#define PUR_32KR 0x07 // 32k Ohm resistor
+
#define CS1_SW1 0x00
#define CS2_SW1 0x01
#define CS3_SW1 0x02
diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h
index 13b73ede9d..3b56d370dc 100644
--- a/drivers/oled/oled_driver.h
+++ b/drivers/oled/oled_driver.h
@@ -190,6 +190,7 @@ bool oled_init(oled_rotation_t rotation);
// Called at the start of oled_init, weak function overridable by the user
// rotation - the value passed into oled_init
// Return new oled_rotation_t if you want to override default rotation
+oled_rotation_t oled_init_kb(oled_rotation_t rotation);
oled_rotation_t oled_init_user(oled_rotation_t rotation);
// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
@@ -285,7 +286,8 @@ uint8_t oled_get_brightness(void);
void oled_task(void);
// Called at the start of oled_task, weak function overridable by the user
-void oled_task_user(void);
+bool oled_task_kb(void);
+bool oled_task_user(void);
// Set the specific 8 lines rows of the screen to scroll.
// 0 is the default for start, and 7 for end, which is the entire
diff --git a/drivers/oled/ssd1306_sh1106.c b/drivers/oled/ssd1306_sh1106.c
index e9049438f5..d9bd3c14bd 100644
--- a/drivers/oled/ssd1306_sh1106.c
+++ b/drivers/oled/ssd1306_sh1106.c
@@ -167,7 +167,7 @@ bool oled_init(oled_rotation_t rotation) {
}
#endif
- oled_rotation = oled_init_user(rotation);
+ oled_rotation = oled_init_user(oled_init_kb(rotation));
if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
oled_rotation_width = OLED_DISPLAY_WIDTH;
} else {
@@ -232,6 +232,7 @@ bool oled_init(oled_rotation_t rotation) {
return true;
}
+__attribute__((weak)) oled_rotation_t oled_init_kb(oled_rotation_t rotation) { return rotation; }
__attribute__((weak)) oled_rotation_t oled_init_user(oled_rotation_t rotation) { return rotation; }
void oled_clear(void) {
@@ -741,11 +742,11 @@ void oled_task(void) {
if (timer_elapsed(oled_update_timeout) >= OLED_UPDATE_INTERVAL) {
oled_update_timeout = timer_read();
oled_set_cursor(0, 0);
- oled_task_user();
+ oled_task_kb();
}
#else
oled_set_cursor(0, 0);
- oled_task_user();
+ oled_task_kb();
#endif
#if OLED_SCROLL_TIMEOUT > 0
@@ -776,4 +777,5 @@ void oled_task(void) {
#endif
}
-__attribute__((weak)) void oled_task_user(void) {}
+__attribute__((weak)) bool oled_task_kb(void) { return oled_task_user(); }
+__attribute__((weak)) bool oled_task_user(void) { return true; }
diff --git a/tmk_core/protocol/ps2.h b/drivers/ps2/ps2.h
index f123192852..f123192852 100644
--- a/tmk_core/protocol/ps2.h
+++ b/drivers/ps2/ps2.h
diff --git a/tmk_core/protocol/ps2_busywait.c b/drivers/ps2/ps2_busywait.c
index 983194eea8..983194eea8 100644
--- a/tmk_core/protocol/ps2_busywait.c
+++ b/drivers/ps2/ps2_busywait.c
diff --git a/tmk_core/protocol/ps2_interrupt.c b/drivers/ps2/ps2_interrupt.c
index 780040d152..70debd02f7 100644
--- a/tmk_core/protocol/ps2_interrupt.c
+++ b/drivers/ps2/ps2_interrupt.c
@@ -73,17 +73,17 @@ static inline void pbuf_clear(void);
void ps2_interrupt_service_routine(void);
void palCallback(void *arg) { ps2_interrupt_service_routine(); }
-# define PS2_INT_INIT() \
- { palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT); } \
+# define PS2_INT_INIT() \
+ { palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_INPUT); } \
while (0)
-# define PS2_INT_ON() \
- { \
- palEnableLineEvent(PS2_CLOCK, PAL_EVENT_MODE_FALLING_EDGE); \
- palSetLineCallback(PS2_CLOCK, palCallback, NULL); \
- } \
+# define PS2_INT_ON() \
+ { \
+ palEnableLineEvent(PS2_CLOCK_PIN, PAL_EVENT_MODE_FALLING_EDGE); \
+ palSetLineCallback(PS2_CLOCK_PIN, palCallback, NULL); \
+ } \
while (0)
-# define PS2_INT_OFF() \
- { palDisableLineEvent(PS2_CLOCK); } \
+# define PS2_INT_OFF() \
+ { palDisableLineEvent(PS2_CLOCK_PIN); } \
while (0)
#endif // PROTOCOL_CHIBIOS
diff --git a/tmk_core/protocol/ps2_io.h b/drivers/ps2/ps2_io.h
index de93cb7a39..de93cb7a39 100644
--- a/tmk_core/protocol/ps2_io.h
+++ b/drivers/ps2/ps2_io.h
diff --git a/tmk_core/protocol/ps2_mouse.c b/drivers/ps2/ps2_mouse.c
index 39251a6434..8a6668b410 100644
--- a/tmk_core/protocol/ps2_mouse.c
+++ b/drivers/ps2/ps2_mouse.c
@@ -16,13 +16,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
-
-#if defined(__AVR__)
-# include <avr/io.h>
-#endif
-
#include "ps2_mouse.h"
#include "wait.h"
+#include "gpio.h"
#include "host.h"
#include "timer.h"
#include "print.h"
@@ -158,8 +154,8 @@ static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report)
#ifdef PS2_MOUSE_INVERT_BUTTONS
// swap left & right buttons
- uint8_t needs_left = mouse_report->buttons & PS2_MOUSE_BTN_RIGHT;
- uint8_t needs_right = mouse_report->buttons & PS2_MOUSE_BTN_LEFT;
+ uint8_t needs_left = mouse_report->buttons & PS2_MOUSE_BTN_RIGHT;
+ uint8_t needs_right = mouse_report->buttons & PS2_MOUSE_BTN_LEFT;
mouse_report->buttons = (mouse_report->buttons & ~(PS2_MOUSE_BTN_MASK)) | (needs_left ? PS2_MOUSE_BTN_LEFT : 0) | (needs_right ? PS2_MOUSE_BTN_RIGHT : 0);
#else
// remove sign and overflow flags
diff --git a/tmk_core/protocol/ps2_mouse.h b/drivers/ps2/ps2_mouse.h
index c97c6c893a..c97c6c893a 100644
--- a/tmk_core/protocol/ps2_mouse.h
+++ b/drivers/ps2/ps2_mouse.h
diff --git a/drivers/qwiic/micro_oled.c b/drivers/qwiic/micro_oled.c
deleted file mode 100644
index 8dfff6968f..0000000000
--- a/drivers/qwiic/micro_oled.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/* Jim Lindblom @ SparkFun Electronics
- * October 26, 2014
- * https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED
- *
- * Modified by:
- * Emil Varughese @ Edwin Robotics Pvt. Ltd.
- * July 27, 2015
- * https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
- *
- * This code was heavily based around the MicroView library, written by GeekAmmo
- * (https://github.com/geekammo/MicroView-Arduino-Library).
- *
- * Adapted for QMK by:
- * Jack Humbert <jack.humb@gmail.com>
- * October 11, 2018
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include "micro_oled.h"
-#include "print.h"
-#include <stdlib.h>
-#include "util/font5x7.h"
-#include "util/font8x16.h"
-#include <string.h>
-
-#define TOTALFONTS 2
-const unsigned char* fonts_pointer[] = {font5x7, font8x16};
-
-uint8_t foreColor, drawMode, fontWidth, fontHeight, fontType, fontStartChar, fontTotalChar, cursorX, cursorY;
-uint16_t fontMapWidth;
-
-#ifndef _BV
-# define _BV(x) (1 << (x))
-#endif
-
-#define swap(a, b) \
- { \
- uint8_t t = a; \
- a = b; \
- b = t; \
- }
-
-uint8_t micro_oled_transfer_buffer[20];
-static uint8_t micro_oled_screen_current[LCDWIDTH * LCDHEIGHT / 8] = {0};
-
-/* LCD Memory organised in 64 horizontal pixel and 6 rows of byte
- B B .............B -----
- y y .............y \
- t t .............t \
- e e .............e \
- 0 1 .............63 \
- \
- D0 D0.............D0 \
- D1 D1.............D1 / ROW 0
- D2 D2.............D2 /
- D3 D3.............D3 /
- D4 D4.............D4 /
- D5 D5.............D5 /
- D6 D6.............D6 /
- D7 D7.............D7 ----
- */
-#ifdef NO_LCD_SPLASH
-// do not initialize with a splash screen
-static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0};
-#else
-# if LCDWIDTH == 64
-# if LCDHEIGHT == 48
-static uint8_t micro_oled_screen_buffer[] = {
- // QMK Logo - generated at http://www.majer.ch/lcd/adf_bitmap.php
- // 64x48 image
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0xF8, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xF8, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x8C, 0x8C, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF1, 0xE3, 0xE7, 0xCF, 0xCF, 0xCF, 0xCF, 0x00, 0x00, 0xCF, 0xCF, 0xCF, 0xC7, 0xE7, 0xE3, 0xF1, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x1F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x1F, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-# endif
-# elif LCDWIDTH == 128
-# if LCDHEIGHT == 32
-static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {
- // 128x32 qmk image
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xFC, 0xFC, 0xE0, 0xF0, 0xFC, 0xE0, 0xE0, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0x10, 0x30, 0xE0, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xB2, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0x03, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xB2, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x02, 0x02, 0x03, 0x01, 0x00, 0x06, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x06, 0x00, 0x03, 0x1E, 0x18, 0x0F, 0x01, 0x0F, 0x18, 0x1E, 0x01, 0x00, 0x0F, 0x1F, 0x12, 0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0x12, 0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x4D, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xF9, 0xF3, 0xF3, 0xC0, 0x80, 0xF3, 0xF3, 0xF3, 0xF9, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0xC0, 0x00, 0x70, 0xC0, 0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x1C, 0xF0, 0x00, 0x00, 0xFC, 0x0C, 0x38, 0xE0, 0x00, 0x00, 0xC0, 0x38, 0x0C, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x60, 0x90, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x3F, 0x3F, 0x07, 0x3F, 0x3F, 0x07, 0x0F, 0x3F, 0x07, 0x07, 0x3F, 0x07, 0x07, 0x3F, 0x3F, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x06, 0x04, 0x04, 0x07, 0x01, 0x00, 0x00, 0x13, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, 0x07, 0x0D, 0x08, 0x00, 0x07, 0x00, 0x00, 0x01, 0x07, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-# elif LCDHEIGHT == 64
-static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF, 0x7F, 0x7E, 0xFE, 0xFF, 0xFF, 0xFE, 0xFE, 0x7F, 0x7F, 0xFE, 0xFE, 0xFF, 0xFF, 0xFE, 0x7E, 0x7F, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xF3, 0xF3, 0xE7, 0xE7, 0x00, 0x00, 0xE7, 0xE7, 0xF3, 0xF3, 0xF0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x1F, 0x3F, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x80, 0x03, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x80, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x70, 0x88, 0x04, 0x04, 0x04, 0xF8, 0x00, 0x00, 0x3C, 0xE0, 0xC0, 0x38, 0x1C, 0xE0, 0x80, 0x70, 0x0C, 0x00, 0xF8, 0xAC, 0x24, 0x24, 0x3C, 0x30, 0x00, 0x00, 0xFC, 0x0C, 0x04, 0x00, 0xF8, 0xAC, 0x24, 0x24, 0x2C, 0x30, 0x00, 0x70, 0xDC, 0x04, 0x04, 0x88, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x8C, 0x04, 0x04, 0xF8, 0x00, 0x04, 0x3C, 0xE0, 0x80, 0xF0, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x83, 0x01, 0x01, 0x01, 0x81, 0xFE, 0x3C, 0x00, 0x00, 0xFF, 0x03, 0x0E, 0x70, 0xC0, 0xE0, 0x38, 0x06, 0x03, 0xFF, 0x00, 0x00, 0xFF, 0x18, 0x38, 0x66, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-// TODO: generate bitmap of QMK logo here
-# endif
-# else
-// catchall for custom screen sizes
-static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0};
-# endif
-#endif
-
-void micro_oled_init(void) {
- i2c_init();
-
-#ifdef __AVR__
- i2c_start(I2C_ADDRESS_SA0_1, 100);
-#else
- i2c_start(I2C_ADDRESS_SA0_1);
-#endif
-
- // Display Init sequence for 64x48 OLED module
- send_command(DISPLAYOFF); // 0xAE
-
- send_command(SETDISPLAYCLOCKDIV); // 0xD5
- send_command(0x80); // the suggested ratio 0x80
-
- send_command(SETMULTIPLEX); // 0xA8
- send_command(LCDHEIGHT - 1);
-
- send_command(SETDISPLAYOFFSET); // 0xD3
- send_command(0x00); // no offset
-
- send_command(SETSTARTLINE | 0x00); // line #0
-
- send_command(CHARGEPUMP); // enable charge pump
- send_command(0x14);
-
- send_command(NORMALDISPLAY); // 0xA6
- send_command(DISPLAYALLONRESUME); // 0xA4
-
- // display at regular orientation
- send_command(SEGREMAP | 0x1);
- send_command(COMSCANDEC);
-
-// rotate display 180
-#ifdef micro_oled_rotate_180
- send_command(SEGREMAP);
- send_command(COMSCANINC);
-#endif
-
- send_command(MEMORYMODE);
- send_command(0x02); // 0x02 = 10b, Page addressing mode
-
- send_command(SETCOMPINS); // 0xDA
- if (LCDHEIGHT > 32) {
- send_command(0x12);
- } else {
- send_command(0x02);
- }
- send_command(SETCONTRAST); // 0x81
- send_command(0x8F);
-
- send_command(SETPRECHARGE); // 0xd9
- send_command(0xF1);
-
- send_command(SETVCOMDESELECT); // 0xDB
- send_command(0x40);
-
- send_command(DISPLAYON); //--turn on oled panel
- clear_screen(); // Erase hardware memory inside the OLED controller to avoid random data in memory.
- send_buffer();
-}
-
-void send_command(uint8_t command) {
- micro_oled_transfer_buffer[0] = I2C_COMMAND;
- micro_oled_transfer_buffer[1] = command;
- i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
-}
-
-void send_data(uint8_t data) {
- micro_oled_transfer_buffer[0] = I2C_DATA;
- micro_oled_transfer_buffer[1] = data;
- i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
-}
-
-/** \brief Set SSD1306 page address.
- Send page address command and address to the SSD1306 OLED controller.
-*/
-void set_page_address(uint8_t address) {
- address = (0xB0 | address);
- send_command(address);
-}
-
-/** \brief Set SSD1306 column address.
- Send column address command and address to the SSD1306 OLED controller.
-*/
-void set_column_address(uint8_t address) {
- send_command((0x10 | (address >> 4)) + ((128 - LCDWIDTH) >> 8));
- send_command(0x0F & address);
-}
-
-/** \brief Clear SSD1306's memory.
- To clear GDRAM inside the LCD controller.
-*/
-void clear_screen(void) {
- for (int i = 0; i < 8; i++) {
- set_page_address(i);
- set_column_address(0);
- for (int j = 0; j < 0x80; j++) {
- send_data(0);
- }
- }
-
- memset(micro_oled_screen_current, 0, LCDWIDTH * LCDHEIGHT / 8);
-}
-
-/** \brief Clear SSD1306's memory.
- To clear GDRAM inside the LCD controller.
-*/
-void clear_buffer(void) {
- // 384
- memset(micro_oled_screen_buffer, 0, LCDWIDTH * LCDHEIGHT / 8);
-}
-
-/** \brief Invert display.
- The PIXEL_ON color of the display will turn to PIXEL_OFF and the PIXEL_OFF will turn to PIXEL_ON.
-*/
-void invert_screen(bool invert) {
- if (invert) {
- send_command(INVERTDISPLAY);
- } else {
- send_command(NORMALDISPLAY);
- }
-}
-
-/** \brief Set contrast.
- OLED contract value from 0 to 255. Note: Contrast level is not very obvious.
-*/
-void set_contrast(uint8_t contrast) {
- send_command(SETCONTRAST); // 0x81
- send_command(contrast);
-}
-
-/** \brief Transfer display buffer.
- Sends the updated buffer to the controller - the current status is checked before to save i2c exectution time
-*/
-void send_buffer(void) {
- uint8_t i, j;
-
- uint8_t page_addr = 0xFF;
- for (i = 0; i < LCDHEIGHT / 8; i++) {
- uint8_t col_addr = 0xFF;
- for (j = 0; j < LCDWIDTH; j++) {
- if (micro_oled_screen_buffer[i * LCDWIDTH + j] != micro_oled_screen_current[i * LCDWIDTH + j]) {
- if (page_addr != i) {
- set_page_address(i);
- page_addr = i;
- }
- if (col_addr != j) {
- set_column_address(j);
- col_addr = j + 1;
- }
- send_data(micro_oled_screen_buffer[i * LCDWIDTH + j]);
- micro_oled_screen_current[i * LCDWIDTH + j] = micro_oled_screen_buffer[i * LCDWIDTH + j];
- }
- }
- }
-}
-
-/** \brief Draw pixel with color and mode.
- Draw color pixel in the screen buffer's x,y position with NORM or XOR draw mode.
-*/
-void draw_pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode) {
- if ((x < 0) || (x >= LCDWIDTH) || (y < 0) || (y >= LCDHEIGHT)) return;
-
- if (mode == XOR) {
- if (color == PIXEL_ON) micro_oled_screen_buffer[x + (y / 8) * LCDWIDTH] ^= _BV((y % 8));
- } else {
- if (color == PIXEL_ON)
- micro_oled_screen_buffer[x + (y / 8) * LCDWIDTH] |= _BV((y % 8));
- else
- micro_oled_screen_buffer[x + (y / 8) * LCDWIDTH] &= ~_BV((y % 8));
- }
-}
-
-/** \brief Draw line with color and mode.
-Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer.
-*/
-void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode) {
- uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
- if (steep) {
- swap(x0, y0);
- swap(x1, y1);
- }
-
- if (x0 > x1) {
- swap(x0, x1);
- swap(y0, y1);
- }
-
- uint8_t dx, dy;
- dx = x1 - x0;
- dy = abs(y1 - y0);
-
- int8_t err = dx / 2;
- int8_t ystep;
-
- if (y0 < y1) {
- ystep = 1;
- } else {
- ystep = -1;
- }
-
- for (; x0 < x1; x0++) {
- if (steep) {
- draw_pixel(y0, x0, color, mode);
- } else {
- draw_pixel(x0, y0, color, mode);
- }
- err -= dy;
- if (err < 0) {
- y0 += ystep;
- err += dx;
- }
- }
-}
-
-/** \brief Draw horizontal line with color and mode.
-Draw horizontal line using color and mode from x,y to x+width,y of the screen buffer.
-*/
-void draw_line_hori(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode) { draw_line(x, y, x + width, y, color, mode); }
-
-/** \brief Draw vertical line.
-Draw vertical line using current fore color and current draw mode from x,y to x,y+height of the screen buffer.
-*/
-void draw_line_vert(uint8_t x, uint8_t y, uint8_t height, bool color, uint8_t mode) { draw_line(x, y, x, y + height, color, mode); }
-
-/** \brief Draw rectangle with color and mode.
-Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
-*/
-void draw_rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
- uint8_t tempHeight;
-
- draw_line_hori(x, y, width, color, mode);
- draw_line_hori(x, y + height - 1, width, color, mode);
-
- tempHeight = height - 2;
-
- // skip drawing vertical lines to avoid overlapping of pixel that will
- // affect XOR plot if no pixel in between horizontal lines
- if (tempHeight < 1) return;
-
- draw_line_vert(x, y + 1, tempHeight, color, mode);
- draw_line_vert(x + width - 1, y + 1, tempHeight, color, mode);
-}
-
-/** \brief Draw rectangle with color and mode.
-Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
-*/
-void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
- uint8_t tempHeight;
-
- draw_line_hori(x + 1, y, width - 2, color, mode);
- draw_line_hori(x + 1, y + height - 1, width - 2, color, mode);
-
- tempHeight = height - 2;
-
- // skip drawing vertical lines to avoid overlapping of pixel that will
- // affect XOR plot if no pixel in between horizontal lines
- if (tempHeight < 1) return;
-
- draw_line_vert(x, y + 1, tempHeight, color, mode);
- draw_line_vert(x + width - 1, y + 1, tempHeight, color, mode);
-}
-
-/** \brief Draw filled rectangle with color and mode.
-Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
-*/
-void draw_rect_filled(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
- // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
- for (int i = x; i < x + width; i++) {
- draw_line_vert(i, y, height, color, mode);
- }
-}
-
-/** \brief Draw filled rectangle with color and mode.
-Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
-*/
-void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
- // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
- for (int i = x; i < x + width; i++) {
- if (i == x || i == (x + width - 1))
- draw_line_vert(i, y + 1, height - 2, color, mode);
- else
- draw_line_vert(i, y, height, color, mode);
- }
-}
-
-/** \brief Draw character with color and mode.
- Draw character c using color and draw mode at x,y.
-*/
-void draw_char(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode, uint8_t font) {
- // TODO - New routine to take font of any height, at the moment limited to font height in multiple of 8 pixels
-
- uint8_t rowsToDraw, row, tempC;
- uint8_t i, j, temp;
- uint16_t charPerBitmapRow, charColPositionOnBitmap, charRowPositionOnBitmap, charBitmapStartPosition;
-
- if ((font >= TOTALFONTS) || (font < 0)) return;
-
- uint8_t fontType = font;
- uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType] + 0);
- uint8_t fontHeight = pgm_read_byte(fonts_pointer[fontType] + 1);
- uint8_t fontStartChar = pgm_read_byte(fonts_pointer[fontType] + 2);
- uint8_t fontTotalChar = pgm_read_byte(fonts_pointer[fontType] + 3);
- uint16_t fontMapWidth = (pgm_read_byte(fonts_pointer[fontType] + 4) * 100) + pgm_read_byte(fonts_pointer[fontType] + 5); // two bytes values into integer 16
-
- if ((c < fontStartChar) || (c > (fontStartChar + fontTotalChar - 1))) // no bitmap for the required c
- return;
-
- tempC = c - fontStartChar;
-
- // each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn
- rowsToDraw = fontHeight / 8; // 8 is LCD's page size, see SSD1306 datasheet
- if (rowsToDraw <= 1) rowsToDraw = 1;
-
- // the following draw function can draw anywhere on the screen, but SLOW pixel by pixel draw
- if (rowsToDraw == 1) {
- for (i = 0; i < fontWidth + 1; i++) {
- if (i == fontWidth) // this is done in a weird way because for 5x7 font, there is no margin, this code add a margin after col 5
- temp = 0;
- else
- temp = pgm_read_byte(fonts_pointer[fontType] + FONTHEADERSIZE + (tempC * fontWidth) + i);
-
- for (j = 0; j < 8; j++) { // 8 is the LCD's page height (see datasheet for explanation)
- if (temp & 0x1) {
- draw_pixel(x + i, y + j, color, mode);
- } else {
- draw_pixel(x + i, y + j, !color, mode);
- }
-
- temp >>= 1;
- }
- }
- return;
- }
-
- // font height over 8 bit
- // take character "0" ASCII 48 as example
- charPerBitmapRow = fontMapWidth / fontWidth; // 256/8 =32 char per row
- charColPositionOnBitmap = tempC % charPerBitmapRow; // =16
- charRowPositionOnBitmap = (int)(tempC / charPerBitmapRow); // =1
- charBitmapStartPosition = (charRowPositionOnBitmap * fontMapWidth * (fontHeight / 8)) + (charColPositionOnBitmap * fontWidth);
-
- // each row on LCD is 8 bit height (see datasheet for explanation)
- for (row = 0; row < rowsToDraw; row++) {
- for (i = 0; i < fontWidth; i++) {
- temp = pgm_read_byte(fonts_pointer[fontType] + FONTHEADERSIZE + (charBitmapStartPosition + i + (row * fontMapWidth)));
- for (j = 0; j < 8; j++) { // 8 is the LCD's page height (see datasheet for explanation)
- if (temp & 0x1) {
- draw_pixel(x + i, y + j + (row * 8), color, mode);
- } else {
- draw_pixel(x + i, y + j + (row * 8), !color, mode);
- }
- temp >>= 1;
- }
- }
- }
-}
-
-void draw_string(uint8_t x, uint8_t y, char* string, uint8_t color, uint8_t mode, uint8_t font) {
- if ((font >= TOTALFONTS) || (font < 0)) return;
-
- uint8_t fontType = font;
- uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType] + 0);
-
- uint8_t cur_x = x;
- for (int i = 0; i < strlen(string); i++) {
- draw_char(cur_x, y, string[i], color, mode, font);
- cur_x += fontWidth + 1;
- }
-}
diff --git a/drivers/qwiic/micro_oled.h b/drivers/qwiic/micro_oled.h
deleted file mode 100644
index 6f9106f581..0000000000
--- a/drivers/qwiic/micro_oled.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Jim Lindblom @ SparkFun Electronics
- * October 26, 2014
- * https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED
- *
- * Modified by:
- * Emil Varughese @ Edwin Robotics Pvt. Ltd.
- * July 27, 2015
- * https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
- *
- * This code was heavily based around the MicroView library, written by GeekAmmo
- * (https://github.com/geekammo/MicroView-Arduino-Library).
- *
- * Adapted for QMK by:
- * Jack Humbert <jack.humb@gmail.com>
- * October 11, 2018
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#include "qwiic.h"
-
-void micro_oled_init(void);
-
-void send_command(uint8_t command);
-void send_data(uint8_t data);
-void set_page_address(uint8_t address);
-void set_column_address(uint8_t address);
-void clear_screen(void);
-void clear_buffer(void);
-void send_buffer(void);
-void draw_pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode);
-void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode);
-void draw_line_hori(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode);
-void draw_line_vert(uint8_t x, uint8_t y, uint8_t height, bool color, uint8_t mode);
-void draw_rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode);
-void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode);
-void draw_rect_filled(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode);
-void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode);
-void draw_char(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode, uint8_t font);
-void draw_string(uint8_t x, uint8_t y, char* string, uint8_t color, uint8_t mode, uint8_t font);
-
-#define I2C_ADDRESS_SA0_0 0b0111100
-#ifndef I2C_ADDRESS_SA0_1
-# define I2C_ADDRESS_SA0_1 0b0111101
-#endif
-#define I2C_COMMAND 0x00
-#define I2C_DATA 0x40
-#define PIXEL_OFF 0
-#define PIXEL_ON 1
-
-#ifndef LCDWIDTH
-# define LCDWIDTH 64
-#endif
-#ifndef LCDHEIGHT
-# define LCDHEIGHT 48
-#endif
-#define FONTHEADERSIZE 6
-
-#define NORM 0
-#define XOR 1
-
-#define PAGE 0
-#define ALL 1
-
-#define WIDGETSTYLE0 0
-#define WIDGETSTYLE1 1
-#define WIDGETSTYLE2 2
-
-#define SETCONTRAST 0x81
-#define DISPLAYALLONRESUME 0xA4
-#define DISPLAYALLON 0xA5
-#define NORMALDISPLAY 0xA6
-#define INVERTDISPLAY 0xA7
-#define DISPLAYOFF 0xAE
-#define DISPLAYON 0xAF
-#define SETDISPLAYOFFSET 0xD3
-#define SETCOMPINS 0xDA
-#define SETVCOMDESELECT 0xDB
-#define SETDISPLAYCLOCKDIV 0xD5
-#define SETPRECHARGE 0xD9
-#define SETMULTIPLEX 0xA8
-#define SETLOWCOLUMN 0x00
-#define SETHIGHCOLUMN 0x10
-#define SETSTARTLINE 0x40
-#define MEMORYMODE 0x20
-#define COMSCANINC 0xC0
-#define COMSCANDEC 0xC8
-#define SEGREMAP 0xA0
-#define CHARGEPUMP 0x8D
-#define EXTERNALVCC 0x01
-#define SWITCHCAPVCC 0x02
-
-// Scroll
-#define ACTIVATESCROLL 0x2F
-#define DEACTIVATESCROLL 0x2E
-#define SETVERTICALSCROLLAREA 0xA3
-#define RIGHTHORIZONTALSCROLL 0x26
-#define LEFT_HORIZONTALSCROLL 0x27
-#define VERTICALRIGHTHORIZONTALSCROLL 0x29
-#define VERTICALLEFTHORIZONTALSCROLL 0x2A
-
-typedef enum CMD {
- CMD_CLEAR, // 0
- CMD_INVERT, // 1
- CMD_CONTRAST, // 2
- CMD_DISPLAY, // 3
- CMD_SETCURSOR, // 4
- CMD_PIXEL, // 5
- CMD_LINE, // 6
- CMD_LINEH, // 7
- CMD_LINEV, // 8
- CMD_RECT, // 9
- CMD_RECTFILL, // 10
- CMD_CIRCLE, // 11
- CMD_CIRCLEFILL, // 12
- CMD_DRAWCHAR, // 13
- CMD_DRAWBITMAP, // 14
- CMD_GETLCDWIDTH, // 15
- CMD_GETLCDHEIGHT, // 16
- CMD_SETCOLOR, // 17
- CMD_SETDRAWMODE // 18
-} commCommand_t;
diff --git a/drivers/qwiic/qwiic.mk b/drivers/qwiic/qwiic.mk
deleted file mode 100644
index 164bd72108..0000000000
--- a/drivers/qwiic/qwiic.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-ifeq ($(strip $(QWIIC_ENABLE)),yes)
- COMMON_VPATH += $(DRIVER_PATH)/qwiic
- OPT_DEFS += -DQWIIC_ENABLE
- SRC += qwiic.c
- QUANTUM_LIB_SRC += i2c_master.c
-
-ifneq ($(filter JOYSTIIC, $(QWIIC_DRIVERS)),)
- OPT_DEFS += -DQWIIC_JOYSTIIC_ENABLE
- SRC += joystiic.c
-endif
-
-ifneq ($(filter MICRO_OLED, $(QWIIC_DRIVERS)),)
- OPT_DEFS += -DQWIIC_MICRO_OLED_ENABLE
- SRC += micro_oled.c
-endif
-
-endif
diff --git a/drivers/qwiic/util/font5x7.h b/drivers/qwiic/util/font5x7.h
deleted file mode 100644
index a641945aae..0000000000
--- a/drivers/qwiic/util/font5x7.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/******************************************************************************
-font5x7.h
-Definition for small font
-
-This file was imported from the MicroView library, written by GeekAmmo
-(https://github.com/geekammo/MicroView-Arduino-Library), and released under
-the terms of the GNU General Public License as published by the Free Software
-Foundation, either version 3 of the License, or (at your option) any later
-version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Modified by:
-Emil Varughese @ Edwin Robotics Pvt. Ltd.
-July 27, 2015
-https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
-
-******************************************************************************/
-#pragma once
-
-#include "progmem.h"
-
-// Standard ASCII 5x7 font
-static const unsigned char font5x7[] PROGMEM = {
- // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
- 5, 8, 0, 255, 12, 75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, 0x18, 0x3C, 0x18, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x18, 0x24, 0x18, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x26, 0x29, 0x79, 0x29, 0x26, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x66, 0x89, 0x95, 0x6A, 0x60, 0x60, 0x60, 0x60, 0x60, 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x08, 0x04, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x20, 0x10, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x30, 0x38, 0x3E, 0x38, 0x30,
- 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x80, 0x70, 0x30, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x72, 0x49, 0x49, 0x49, 0x46, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x27, 0x45, 0x45, 0x45, 0x39, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x41, 0x21, 0x11, 0x09, 0x07, 0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02,
- 0x01, 0x59, 0x09, 0x06, 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x3E, 0x41, 0x41, 0x51, 0x73, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x26, 0x49, 0x49, 0x49, 0x32, 0x03, 0x01, 0x7F, 0x01, 0x03, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, 0x63, 0x03, 0x04, 0x78, 0x04, 0x03, 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x41, 0x7F, 0x04, 0x02, 0x01, 0x02, 0x04, 0x40, 0x40,
- 0x40, 0x40, 0x40, 0x00, 0x03, 0x07, 0x08, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x7F, 0x28, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x28, 0x38, 0x44, 0x44, 0x28, 0x7F, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x08, 0x7E, 0x09, 0x02, 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x20, 0x40, 0x40, 0x3D, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x78, 0x04, 0x78, 0x7C, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x24, 0x04, 0x04, 0x3F, 0x44, 0x24, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x44, 0x28, 0x10, 0x28, 0x44, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x3C, 0x26, 0x23,
- 0x26, 0x3C, 0x1E, 0xA1, 0xA1, 0x61, 0x12, 0x3A, 0x40, 0x40, 0x20, 0x7A, 0x38, 0x54, 0x54, 0x55, 0x59, 0x21, 0x55, 0x55, 0x79, 0x41, 0x21, 0x54, 0x54, 0x78, 0x41, 0x21, 0x55, 0x54, 0x78, 0x40, 0x20, 0x54, 0x55, 0x79, 0x40, 0x0C, 0x1E, 0x52, 0x72, 0x12, 0x39, 0x55, 0x55, 0x55, 0x59, 0x39, 0x54, 0x54, 0x54, 0x59, 0x39, 0x55, 0x54, 0x54, 0x58, 0x00, 0x00, 0x45, 0x7C, 0x41, 0x00, 0x02, 0x45, 0x7D, 0x42, 0x00, 0x01, 0x45, 0x7C, 0x40, 0xF0, 0x29, 0x24, 0x29, 0xF0, 0xF0, 0x28, 0x25, 0x28, 0xF0, 0x7C, 0x54, 0x55, 0x45, 0x00, 0x20, 0x54, 0x54, 0x7C, 0x54, 0x7C, 0x0A, 0x09, 0x7F, 0x49, 0x32, 0x49, 0x49, 0x49, 0x32, 0x32, 0x48, 0x48, 0x48, 0x32, 0x32, 0x4A, 0x48, 0x48, 0x30, 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x3A, 0x42, 0x40, 0x20, 0x78, 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 0x39, 0x44, 0x44, 0x44, 0x39, 0x3D, 0x40, 0x40, 0x40, 0x3D, 0x3C, 0x24, 0xFF, 0x24, 0x24, 0x48, 0x7E, 0x49, 0x43, 0x66, 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 0xFF, 0x09, 0x29, 0xF6, 0x20, 0xC0, 0x88, 0x7E, 0x09,
- 0x03, 0x20, 0x54, 0x54, 0x79, 0x41, 0x00, 0x00, 0x44, 0x7D, 0x41, 0x30, 0x48, 0x48, 0x4A, 0x32, 0x38, 0x40, 0x40, 0x22, 0x7A, 0x00, 0x7A, 0x0A, 0x0A, 0x72, 0x7D, 0x0D, 0x19, 0x31, 0x7D, 0x26, 0x29, 0x29, 0x2F, 0x28, 0x26, 0x29, 0x29, 0x29, 0x26, 0x30, 0x48, 0x4D, 0x40, 0x20, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 0x2F, 0x10, 0x28, 0x34, 0xFA, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x08, 0x14, 0x2A, 0x14, 0x22, 0x22, 0x14, 0x2A, 0x14, 0x08, 0xAA, 0x00, 0x55, 0x00, 0xAA, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x10, 0x10, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x10, 0x10, 0x1F, 0x10, 0x1F, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10,
- 0x10, 0x10, 0x10, 0x1F, 0x10, 0x10, 0x10, 0x10, 0xF0, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x17, 0x14, 0x10, 0x10, 0x1F, 0x10, 0x1F, 0x14, 0x14, 0x14, 0xF4, 0x14, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x00, 0x00, 0x1F, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0xF0, 0x10, 0xF0, 0x10, 0x10, 0xFF, 0x10, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x38, 0x44, 0x44, 0x38, 0x44, 0x7C,
- 0x2A, 0x2A, 0x3E, 0x14, 0x7E, 0x02, 0x02, 0x06, 0x06, 0x02, 0x7E, 0x02, 0x7E, 0x02, 0x63, 0x55, 0x49, 0x41, 0x63, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x40, 0x7E, 0x20, 0x1E, 0x20, 0x06, 0x02, 0x7E, 0x02, 0x02, 0x99, 0xA5, 0xE7, 0xA5, 0x99, 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 0x4C, 0x72, 0x01, 0x72, 0x4C, 0x30, 0x4A, 0x4D, 0x4D, 0x30, 0x30, 0x48, 0x78, 0x48, 0x30, 0xBC, 0x62, 0x5A, 0x46, 0x3D, 0x3E, 0x49, 0x49, 0x49, 0x00, 0x7E, 0x01, 0x01, 0x01, 0x7E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x44, 0x44, 0x5F, 0x44, 0x44, 0x40, 0x51, 0x4A, 0x44, 0x40, 0x40, 0x44, 0x4A, 0x51, 0x40, 0x00, 0x00, 0xFF, 0x01, 0x03, 0xE0, 0x80, 0xFF, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x6B, 0x08, 0x36, 0x12, 0x36, 0x24, 0x36, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x30, 0x40, 0xFF, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x01, 0x1E, 0x00, 0x19, 0x1D, 0x17, 0x12, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/drivers/qwiic/util/font8x16.h b/drivers/qwiic/util/font8x16.h
deleted file mode 100644
index 4d3c237866..0000000000
--- a/drivers/qwiic/util/font8x16.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/******************************************************************************
-font8x16.h
-Definition for medium font
-
-This file was imported from the MicroView library, written by GeekAmmo
-(https://github.com/geekammo/MicroView-Arduino-Library), and released under
-the terms of the GNU General Public License as published by the Free Software
-Foundation, either version 3 of the License, or (at your option) any later
-version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Modified by:
-Emil Varughese @ Edwin Robotics Pvt. Ltd.
-July 27, 2015
-https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
-******************************************************************************/
-#pragma once
-
-#include "progmem.h"
-
-static const unsigned char font8x16[] PROGMEM = {
- // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
- 8, 16, 32, 96, 2, 56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xBE, 0x90, 0xD0, 0xBE, 0x90, 0x00, 0x00, 0x1C, 0x62, 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x0C, 0x12, 0x92, 0x4C, 0xB0, 0x88, 0x06, 0x00, 0x80, 0x7C, 0x62, 0xB2, 0x1C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7E, 0x18, 0x24, 0x00, 0x00, 0x80, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x06, 0x00, 0x00, 0xF8, 0x04, 0xC2, 0x32, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x04, 0x04, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x42, 0x22,
- 0x1C, 0x00, 0x00, 0x00, 0x02, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00, 0xC0, 0xA0, 0x98, 0x84, 0xFE, 0x80, 0x80, 0x00, 0x00, 0x1E, 0x12, 0x12, 0x22, 0xC2, 0x00, 0x00, 0xF8, 0x44, 0x22, 0x22, 0x22, 0xC0, 0x00, 0x00, 0x00, 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00, 0x00, 0x8C, 0x52, 0x22, 0x52, 0x8C, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x26, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x0F, 0x04, 0x03, 0x00, 0x00, 0x04, 0x02, 0x01, 0x03, 0x04, 0x04, 0x03, 0x00,
- 0x03, 0x04, 0x04, 0x04, 0x05, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x04, 0x04,
- 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x04, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x04, 0x72, 0x8A, 0xFA, 0x84, 0x78, 0x00, 0x00, 0xC0, 0x38, 0x06, 0x38, 0xC0, 0x00, 0x00, 0x00, 0xFE, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x22, 0xE2, 0x00, 0x00, 0xFE, 0x20, 0x20, 0x20, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0xFE, 0x40, 0xB0, 0x08, 0x04, 0x02, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xFE, 0x0C, 0x70, 0x80, 0x70, 0x0C, 0xFE, 0x00, 0xFE, 0x0C, 0x30, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, 0xFE, 0x42, 0x42, 0x42, 0x22, 0x1C, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x42, 0x42, 0xA2, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x42, 0x80, 0x00, 0x00, 0x02, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x02, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x06, 0x38, 0xC0, 0x00, 0xC0, 0x38, 0x06, 0x00, 0x3E, 0xC0, 0xF0, 0x0E, 0xF0, 0xC0, 0x3E, 0x00, 0x00, 0x06, 0x98, 0x60, 0x98, 0x06, 0x00, 0x00, 0x00, 0x06, 0x18, 0xE0, 0x18, 0x06, 0x00, 0x00, 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x06, 0x18, 0x60, 0x80, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x40, 0x30, 0x0C, 0x0C, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x02, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0C, 0x12, 0x11, 0x10, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,
- 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x90, 0x90, 0x90, 0xE0, 0x00, 0x00, 0x00, 0x20, 0xFC, 0x22, 0x22, 0x22, 0x02,
- 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x80, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x20, 0x10, 0xF0, 0x20, 0x10, 0xF0, 0x00, 0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x20, 0x10, 0x10, 0x70, 0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x20, 0x00, 0x00, 0x00, 0x20, 0x20, 0xFC, 0x20, 0x20, 0x20, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x70, 0x80, 0x00, 0x80, 0x70, 0x00, 0x00, 0xF0, 0x00, 0xC0, 0x30, 0xC0, 0x00, 0xF0, 0x00, 0x00, 0x30, 0xC0, 0xC0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0xC0, 0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x10,
- 0x10, 0x90, 0x50, 0x30, 0x00, 0x00, 0x00, 0x80, 0x80, 0x7E, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x7E, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x24, 0x24, 0x22, 0x1F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00,
- 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x3F, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x3F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x01, 0x06, 0x01, 0x00, 0x00, 0x06, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x20, 0x20, 0x31, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/drivers/sensors/adns5050.c b/drivers/sensors/adns5050.c
index e7273977d5..c23d24d5af 100644
--- a/drivers/sensors/adns5050.c
+++ b/drivers/sensors/adns5050.c
@@ -17,89 +17,98 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
#include "adns5050.h"
#include "wait.h"
#include "debug.h"
-#include "print.h"
#include "gpio.h"
-#ifndef OPTIC_ROTATED
-# define OPTIC_ROTATED false
-#endif
-
-// Definitions for the ADNS serial line.
-#ifndef ADNS_SCLK_PIN
-# define ADNS_SCLK_PIN B7
-#endif
-
-#ifndef ADNS_SDIO_PIN
-# define ADNS_SDIO_PIN C6
-#endif
-
-#ifndef ADNS_CS_PIN
-# define ADNS_CS_PIN B4
-#endif
-
-#ifdef CONSOLE_ENABLE
-void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
-#endif
-
-// Initialize the ADNS serial pins.
-void adns_init(void) {
- setPinOutput(ADNS_SCLK_PIN);
- setPinOutput(ADNS_SDIO_PIN);
- setPinOutput(ADNS_CS_PIN);
+// Registers
+// clang-format off
+#define REG_PRODUCT_ID 0x00
+#define REG_REVISION_ID 0x01
+#define REG_MOTION 0x02
+#define REG_DELTA_X 0x03
+#define REG_DELTA_Y 0x04
+#define REG_SQUAL 0x05
+#define REG_SHUTTER_UPPER 0x06
+#define REG_SHUTTER_LOWER 0x07
+#define REG_MAXIMUM_PIXEL 0x08
+#define REG_PIXEL_SUM 0x09
+#define REG_MINIMUM_PIXEL 0x0a
+#define REG_PIXEL_GRAB 0x0b
+#define REG_MOUSE_CONTROL 0x0d
+#define REG_MOUSE_CONTROL2 0x19
+#define REG_LED_DC_MODE 0x22
+#define REG_CHIP_RESET 0x3a
+#define REG_PRODUCT_ID2 0x3e
+#define REG_INV_REV_ID 0x3f
+#define REG_MOTION_BURST 0x63
+// clang-format on
+
+void adns5050_init(void) {
+ // Initialize the ADNS serial pins.
+ setPinOutput(ADNS5050_SCLK_PIN);
+ setPinOutput(ADNS5050_SDIO_PIN);
+ setPinOutput(ADNS5050_CS_PIN);
+
+ // reboot the adns.
+ // if the adns hasn't initialized yet, this is harmless.
+ adns5050_write_reg(REG_CHIP_RESET, 0x5a);
+
+ // wait maximum time before adns is ready.
+ // this ensures that the adns is actuall ready after reset.
+ wait_ms(55);
+
+ // read a burst from the adns and then discard it.
+ // gets the adns ready for write commands
+ // (for example, setting the dpi).
+ adns5050_read_burst();
}
// Perform a synchronization with the ADNS.
// Just as with the serial protocol, this is used by the slave to send a
// synchronization signal to the master.
-void adns_sync(void) {
- writePinLow(ADNS_CS_PIN);
+void adns5050_sync(void) {
+ writePinLow(ADNS5050_CS_PIN);
wait_us(1);
- writePinHigh(ADNS_CS_PIN);
+ writePinHigh(ADNS5050_CS_PIN);
}
-void adns_cs_select(void) {
- writePinLow(ADNS_CS_PIN);
-}
+void adns5050_cs_select(void) { writePinLow(ADNS5050_CS_PIN); }
-void adns_cs_deselect(void) {
- writePinHigh(ADNS_CS_PIN);
-}
+void adns5050_cs_deselect(void) { writePinHigh(ADNS5050_CS_PIN); }
-uint8_t adns_serial_read(void) {
- setPinInput(ADNS_SDIO_PIN);
+uint8_t adns5050_serial_read(void) {
+ setPinInput(ADNS5050_SDIO_PIN);
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; ++i) {
- writePinLow(ADNS_SCLK_PIN);
+ writePinLow(ADNS5050_SCLK_PIN);
wait_us(1);
- byte = (byte << 1) | readPin(ADNS_SDIO_PIN);
+ byte = (byte << 1) | readPin(ADNS5050_SDIO_PIN);
- writePinHigh(ADNS_SCLK_PIN);
+ writePinHigh(ADNS5050_SCLK_PIN);
wait_us(1);
}
return byte;
}
-void adns_serial_write(uint8_t data) {
- setPinOutput(ADNS_SDIO_PIN);
+void adns5050_serial_write(uint8_t data) {
+ setPinOutput(ADNS5050_SDIO_PIN);
for (int8_t b = 7; b >= 0; b--) {
- writePinLow(ADNS_SCLK_PIN);
+ writePinLow(ADNS5050_SCLK_PIN);
if (data & (1 << b))
- writePinHigh(ADNS_SDIO_PIN);
+ writePinHigh(ADNS5050_SDIO_PIN);
else
- writePinLow(ADNS_SDIO_PIN);
+ writePinLow(ADNS5050_SDIO_PIN);
wait_us(2);
- writePinHigh(ADNS_SCLK_PIN);
+ writePinHigh(ADNS5050_SCLK_PIN);
}
// tSWR. See page 15 of the ADNS spec sheet.
@@ -113,17 +122,17 @@ void adns_serial_write(uint8_t data) {
// Read a byte of data from a register on the ADNS.
// Don't forget to use the register map (as defined in the header file).
-uint8_t adns_read_reg(uint8_t reg_addr) {
- adns_cs_select();
+uint8_t adns5050_read_reg(uint8_t reg_addr) {
+ adns5050_cs_select();
- adns_serial_write(reg_addr);
+ adns5050_serial_write(reg_addr);
// We don't need a minimum tSRAD here. That's because a 4ms wait time is
- // already included in adns_serial_write(), so we're good.
+ // already included in adns5050_serial_write(), so we're good.
// See page 10 and 15 of the ADNS spec sheet.
- //wait_us(4);
+ // wait_us(4);
- uint8_t byte = adns_serial_read();
+ uint8_t byte = adns5050_serial_read();
// tSRW & tSRR. See page 15 of the ADNS spec sheet.
// Technically, this is only necessary if the next operation is an SDIO
@@ -131,38 +140,38 @@ uint8_t adns_read_reg(uint8_t reg_addr) {
// Honestly, this wait could probably be removed.
wait_us(1);
- adns_cs_deselect();
+ adns5050_cs_deselect();
return byte;
}
-void adns_write_reg(uint8_t reg_addr, uint8_t data) {
- adns_cs_select();
- adns_serial_write( 0b10000000 | reg_addr );
- adns_serial_write(data);
- adns_cs_deselect();
+void adns5050_write_reg(uint8_t reg_addr, uint8_t data) {
+ adns5050_cs_select();
+ adns5050_serial_write(0b10000000 | reg_addr);
+ adns5050_serial_write(data);
+ adns5050_cs_deselect();
}
-report_adns_t adns_read_burst(void) {
- adns_cs_select();
+report_adns5050_t adns5050_read_burst(void) {
+ adns5050_cs_select();
- report_adns_t data;
+ report_adns5050_t data;
data.dx = 0;
data.dy = 0;
- adns_serial_write(REG_MOTION_BURST);
+ adns5050_serial_write(REG_MOTION_BURST);
// We don't need a minimum tSRAD here. That's because a 4ms wait time is
- // already included in adns_serial_write(), so we're good.
+ // already included in adns5050_serial_write(), so we're good.
// See page 10 and 15 of the ADNS spec sheet.
- //wait_us(4);
+ // wait_us(4);
- uint8_t x = adns_serial_read();
- uint8_t y = adns_serial_read();
+ uint8_t x = adns5050_serial_read();
+ uint8_t y = adns5050_serial_read();
// Burst mode returns a bunch of other shit that we don't really need.
// Setting CS to high ends burst mode early.
- adns_cs_deselect();
+ adns5050_cs_deselect();
data.dx = convert_twoscomp(x);
data.dy = convert_twoscomp(y);
@@ -180,14 +189,21 @@ int8_t convert_twoscomp(uint8_t data) {
}
// Don't forget to use the definitions for CPI in the header file.
-void adns_set_cpi(uint8_t cpi) {
- adns_write_reg(REG_MOUSE_CONTROL2, cpi);
+void adns5050_set_cpi(uint16_t cpi) {
+ uint8_t cpival = constrain((cpi / 125), 0x1, 0xD); // limits to 0--119
+
+ adns5050_write_reg(REG_MOUSE_CONTROL2, 0b10000 | cpival);
+}
+
+uint16_t adns5050_get_cpi(void) {
+ uint8_t cpival = adns5050_read_reg(REG_MOUSE_CONTROL2);
+ return (uint16_t)((cpival & 0b10000) * 125);
}
-bool adns_check_signature(void) {
- uint8_t pid = adns_read_reg(REG_PRODUCT_ID);
- uint8_t rid = adns_read_reg(REG_REVISION_ID);
- uint8_t pid2 = adns_read_reg(REG_PRODUCT_ID2);
+bool adns5050_check_signature(void) {
+ uint8_t pid = adns5050_read_reg(REG_PRODUCT_ID);
+ uint8_t rid = adns5050_read_reg(REG_REVISION_ID);
+ uint8_t pid2 = adns5050_read_reg(REG_PRODUCT_ID2);
return (pid == 0x12 && rid == 0x01 && pid2 == 0x26);
}
diff --git a/drivers/sensors/adns5050.h b/drivers/sensors/adns5050.h
index ff8e8f78e9..e45a250196 100644
--- a/drivers/sensors/adns5050.h
+++ b/drivers/sensors/adns5050.h
@@ -21,59 +21,52 @@
#include <stdbool.h>
-// Registers
-#define REG_PRODUCT_ID 0x00
-#define REG_REVISION_ID 0x01
-#define REG_MOTION 0x02
-#define REG_DELTA_X 0x03
-#define REG_DELTA_Y 0x04
-#define REG_SQUAL 0x05
-#define REG_SHUTTER_UPPER 0x06
-#define REG_SHUTTER_LOWER 0x07
-#define REG_MAXIMUM_PIXEL 0x08
-#define REG_PIXEL_SUM 0x09
-#define REG_MINIMUM_PIXEL 0x0a
-#define REG_PIXEL_GRAB 0x0b
-#define REG_MOUSE_CONTROL 0x0d
-#define REG_MOUSE_CONTROL2 0x19
-#define REG_LED_DC_MODE 0x22
-#define REG_CHIP_RESET 0x3a
-#define REG_PRODUCT_ID2 0x3e
-#define REG_INV_REV_ID 0x3f
-#define REG_MOTION_BURST 0x63
-
// CPI values
-#define CPI125 0x11
-#define CPI250 0x12
-#define CPI375 0x13
-#define CPI500 0x14
-#define CPI625 0x15
-#define CPI750 0x16
-#define CPI875 0x17
+// clang-format off
+#define CPI125 0x11
+#define CPI250 0x12
+#define CPI375 0x13
+#define CPI500 0x14
+#define CPI625 0x15
+#define CPI750 0x16
+#define CPI875 0x17
#define CPI1000 0x18
#define CPI1125 0x19
#define CPI1250 0x1a
#define CPI1375 0x1b
+// clang-format on
+
+#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
+
+// Definitions for the ADNS serial line.
+#ifndef ADNS5050_SCLK_PIN
+# error "No clock pin defined -- missing ADNS5050_SCLK_PIN"
+#endif
+
+#ifndef ADNS5050_SDIO_PIN
+# error "No data pin defined -- missing ADNS5050_SDIO_PIN"
+#endif
-#ifdef CONSOLE_ENABLE
-void print_byte(uint8_t byte);
+#ifndef ADNS5050_CS_PIN
+# error "No chip select pin defined -- missing ADNS5050_CS_PIN"
#endif
typedef struct {
int8_t dx;
int8_t dy;
-} report_adns_t;
+} report_adns5050_t;
// A bunch of functions to implement the ADNS5050-specific serial protocol.
// Note that the "serial.h" driver is insufficient, because it does not
// manually manipulate a serial clock signal.
-void adns_init(void);
-void adns_sync(void);
-uint8_t adns_serial_read(void);
-void adns_serial_write(uint8_t data);
-uint8_t adns_read_reg(uint8_t reg_addr);
-void adns_write_reg(uint8_t reg_addr, uint8_t data);
-report_adns_t adns_read_burst(void);
-int8_t convert_twoscomp(uint8_t data);
-void adns_set_cpi(uint8_t cpi);
-bool adns_check_signature(void);
+void adns5050_init(void);
+void adns5050_sync(void);
+uint8_t adns5050_serial_read(void);
+void adns5050_serial_write(uint8_t data);
+uint8_t adns5050_read_reg(uint8_t reg_addr);
+void adns5050_write_reg(uint8_t reg_addr, uint8_t data);
+report_adns5050_t adns5050_read_burst(void);
+void adns5050_set_cpi(uint16_t cpi);
+uint16_t adns5050_get_cpi(void);
+int8_t convert_twoscomp(uint8_t data);
+bool adns5050_check_signature(void);
diff --git a/drivers/sensors/adns9800.c b/drivers/sensors/adns9800.c
index 36213179f7..c52f991804 100644
--- a/drivers/sensors/adns9800.c
+++ b/drivers/sensors/adns9800.c
@@ -15,89 +15,81 @@
*/
#include "spi_master.h"
-#include "quantum.h"
#include "adns9800_srom_A6.h"
#include "adns9800.h"
+#include "wait.h"
// registers
-#define REG_Product_ID 0x00
-#define REG_Revision_ID 0x01
-#define REG_Motion 0x02
-#define REG_Delta_X_L 0x03
-#define REG_Delta_X_H 0x04
-#define REG_Delta_Y_L 0x05
-#define REG_Delta_Y_H 0x06
-#define REG_SQUAL 0x07
-#define REG_Pixel_Sum 0x08
-#define REG_Maximum_Pixel 0x09
-#define REG_Minimum_Pixel 0x0a
-#define REG_Shutter_Lower 0x0b
-#define REG_Shutter_Upper 0x0c
-#define REG_Frame_Period_Lower 0x0d
-#define REG_Frame_Period_Upper 0x0e
-#define REG_Configuration_I 0x0f
-#define REG_Configuration_II 0x10
-#define REG_Frame_Capture 0x12
-#define REG_SROM_Enable 0x13
-#define REG_Run_Downshift 0x14
-#define REG_Rest1_Rate 0x15
-#define REG_Rest1_Downshift 0x16
-#define REG_Rest2_Rate 0x17
-#define REG_Rest2_Downshift 0x18
-#define REG_Rest3_Rate 0x19
-#define REG_Frame_Period_Max_Bound_Lower 0x1a
-#define REG_Frame_Period_Max_Bound_Upper 0x1b
-#define REG_Frame_Period_Min_Bound_Lower 0x1c
-#define REG_Frame_Period_Min_Bound_Upper 0x1d
-#define REG_Shutter_Max_Bound_Lower 0x1e
-#define REG_Shutter_Max_Bound_Upper 0x1f
-#define REG_LASER_CTRL0 0x20
-#define REG_Observation 0x24
-#define REG_Data_Out_Lower 0x25
-#define REG_Data_Out_Upper 0x26
-#define REG_SROM_ID 0x2a
-#define REG_Lift_Detection_Thr 0x2e
-#define REG_Configuration_V 0x2f
-#define REG_Configuration_IV 0x39
-#define REG_Power_Up_Reset 0x3a
-#define REG_Shutdown 0x3b
-#define REG_Inverse_Product_ID 0x3f
-#define REG_Motion_Burst 0x50
-#define REG_SROM_Load_Burst 0x62
-#define REG_Pixel_Burst 0x64
-
-#define ADNS_CLOCK_SPEED 2000000
-#define MIN_CPI 200
-#define MAX_CPI 8200
-#define CPI_STEP 200
-#define CLAMP_CPI(value) value < MIN_CPI ? MIN_CPI : value > MAX_CPI ? MAX_CPI : value
-#define SPI_MODE 3
-#define SPI_DIVISOR (F_CPU / ADNS_CLOCK_SPEED)
+// clang-format off
+#define REG_Product_ID 0x00
+#define REG_Revision_ID 0x01
+#define REG_Motion 0x02
+#define REG_Delta_X_L 0x03
+#define REG_Delta_X_H 0x04
+#define REG_Delta_Y_L 0x05
+#define REG_Delta_Y_H 0x06
+#define REG_SQUAL 0x07
+#define REG_Pixel_Sum 0x08
+#define REG_Maximum_Pixel 0x09
+#define REG_Minimum_Pixel 0x0a
+#define REG_Shutter_Lower 0x0b
+#define REG_Shutter_Upper 0x0c
+#define REG_Frame_Period_Lower 0x0d
+#define REG_Frame_Period_Upper 0x0e
+#define REG_Configuration_I 0x0f
+#define REG_Configuration_II 0x10
+#define REG_Frame_Capture 0x12
+#define REG_SROM_Enable 0x13
+#define REG_Run_Downshift 0x14
+#define REG_Rest1_Rate 0x15
+#define REG_Rest1_Downshift 0x16
+#define REG_Rest2_Rate 0x17
+#define REG_Rest2_Downshift 0x18
+#define REG_Rest3_Rate 0x19
+#define REG_Frame_Period_Max_Bound_Lower 0x1a
+#define REG_Frame_Period_Max_Bound_Upper 0x1b
+#define REG_Frame_Period_Min_Bound_Lower 0x1c
+#define REG_Frame_Period_Min_Bound_Upper 0x1d
+#define REG_Shutter_Max_Bound_Lower 0x1e
+#define REG_Shutter_Max_Bound_Upper 0x1f
+#define REG_LASER_CTRL0 0x20
+#define REG_Observation 0x24
+#define REG_Data_Out_Lower 0x25
+#define REG_Data_Out_Upper 0x26
+#define REG_SROM_ID 0x2a
+#define REG_Lift_Detection_Thr 0x2e
+#define REG_Configuration_V 0x2f
+#define REG_Configuration_IV 0x39
+#define REG_Power_Up_Reset 0x3a
+#define REG_Shutdown 0x3b
+#define REG_Inverse_Product_ID 0x3f
+#define REG_Motion_Burst 0x50
+#define REG_SROM_Load_Burst 0x62
+#define REG_Pixel_Burst 0x64
+
+#define MIN_CPI 200
+#define MAX_CPI 8200
+#define CPI_STEP 200
+#define CLAMP_CPI(value) value<MIN_CPI ? MIN_CPI : value> MAX_CPI ? MAX_CPI : value
#define US_BETWEEN_WRITES 120
-#define US_BETWEEN_READS 20
-#define US_BEFORE_MOTION 100
-#define MSB1 0x80
+#define US_BETWEEN_READS 20
+#define US_BEFORE_MOTION 100
+#define MSB1 0x80
+// clang-format on
-extern const uint16_t adns_firmware_length;
-extern const uint8_t adns_firmware_data[];
+void adns9800_spi_start(void) { spi_start(ADNS9800_CS_PIN, false, ADNS9800_SPI_MODE, ADNS9800_SPI_DIVISOR); }
-void adns_spi_start(void){
- spi_start(SPI_SS_PIN, false, SPI_MODE, SPI_DIVISOR);
-}
-
-void adns_write(uint8_t reg_addr, uint8_t data){
-
- adns_spi_start();
+void adns9800_write(uint8_t reg_addr, uint8_t data) {
+ adns9800_spi_start();
spi_write(reg_addr | MSB1);
spi_write(data);
spi_stop();
wait_us(US_BETWEEN_WRITES);
}
-uint8_t adns_read(uint8_t reg_addr){
-
- adns_spi_start();
- spi_write(reg_addr & 0x7f );
+uint8_t adns9800_read(uint8_t reg_addr) {
+ adns9800_spi_start();
+ spi_write(reg_addr & 0x7f);
uint8_t data = spi_read();
spi_stop();
wait_us(US_BETWEEN_READS);
@@ -105,48 +97,47 @@ uint8_t adns_read(uint8_t reg_addr){
return data;
}
-void adns_init() {
-
- setPinOutput(SPI_SS_PIN);
+void adns9800_init() {
+ setPinOutput(ADNS9800_CS_PIN);
spi_init();
// reboot
- adns_write(REG_Power_Up_Reset, 0x5a);
+ adns9800_write(REG_Power_Up_Reset, 0x5a);
wait_ms(50);
// read registers and discard
- adns_read(REG_Motion);
- adns_read(REG_Delta_X_L);
- adns_read(REG_Delta_X_H);
- adns_read(REG_Delta_Y_L);
- adns_read(REG_Delta_Y_H);
+ adns9800_read(REG_Motion);
+ adns9800_read(REG_Delta_X_L);
+ adns9800_read(REG_Delta_X_H);
+ adns9800_read(REG_Delta_Y_L);
+ adns9800_read(REG_Delta_Y_H);
// upload firmware
// 3k firmware mode
- adns_write(REG_Configuration_IV, 0x02);
+ adns9800_write(REG_Configuration_IV, 0x02);
// enable initialisation
- adns_write(REG_SROM_Enable, 0x1d);
+ adns9800_write(REG_SROM_Enable, 0x1d);
// wait a frame
wait_ms(10);
// start SROM download
- adns_write(REG_SROM_Enable, 0x18);
+ adns9800_write(REG_SROM_Enable, 0x18);
// write the SROM file
- adns_spi_start();
+ adns9800_spi_start();
spi_write(REG_SROM_Load_Burst | 0x80);
wait_us(15);
// send all bytes of the firmware
unsigned char c;
- for(int i = 0; i < adns_firmware_length; i++){
- c = (unsigned char)pgm_read_byte(adns_firmware_data + i);
+ for (int i = 0; i < FIRMWARE_LENGTH; i++) {
+ c = (unsigned char)pgm_read_byte(adns9800_firmware_data + i);
spi_write(c);
wait_us(15);
}
@@ -156,37 +147,46 @@ void adns_init() {
wait_ms(10);
// enable laser
- uint8_t laser_ctrl0 = adns_read(REG_LASER_CTRL0);
- adns_write(REG_LASER_CTRL0, laser_ctrl0 & 0xf0);
+ uint8_t laser_ctrl0 = adns9800_read(REG_LASER_CTRL0);
+ adns9800_write(REG_LASER_CTRL0, laser_ctrl0 & 0xf0);
+
+ adns9800_set_cpi(ADNS9800_CPI);
}
-config_adns_t adns_get_config(void) {
- uint8_t config_1 = adns_read(REG_Configuration_I);
- return (config_adns_t){ (config_1 & 0xFF) * CPI_STEP };
+config_adns9800_t adns9800_get_config(void) {
+ uint8_t config_1 = adns9800_read(REG_Configuration_I);
+ return (config_adns9800_t){(config_1 & 0xFF) * CPI_STEP};
}
-void adns_set_config(config_adns_t config) {
+void adns9800_set_config(config_adns9800_t config) {
uint8_t config_1 = (CLAMP_CPI(config.cpi) / CPI_STEP) & 0xFF;
- adns_write(REG_Configuration_I, config_1);
+ adns9800_write(REG_Configuration_I, config_1);
}
-static int16_t convertDeltaToInt(uint8_t high, uint8_t low){
+uint16_t adns9800_get_cpi(void) {
+ uint8_t config_1 = adns9800_read(REG_Configuration_I);
+ return (uint16_t){(config_1 & 0xFF) * CPI_STEP};
+}
+
+void adns9800_set_cpi(uint16_t cpi) {
+ uint8_t config_1 = (CLAMP_CPI(cpi) / CPI_STEP) & 0xFF;
+ adns9800_write(REG_Configuration_I, config_1);
+}
+static int16_t convertDeltaToInt(uint8_t high, uint8_t low) {
// join bytes into twos compliment
uint16_t twos_comp = (high << 8) | low;
// convert twos comp to int
- if (twos_comp & 0x8000)
- return -1 * (~twos_comp + 1);
+ if (twos_comp & 0x8000) return -1 * (~twos_comp + 1);
return twos_comp;
}
-report_adns_t adns_get_report(void) {
+report_adns9800_t adns9800_get_report(void) {
+ report_adns9800_t report = {0, 0};
- report_adns_t report = {0, 0};
-
- adns_spi_start();
+ adns9800_spi_start();
// start burst mode
spi_write(REG_Motion_Burst & 0x7f);
@@ -195,8 +195,7 @@ report_adns_t adns_get_report(void) {
uint8_t motion = spi_read();
- if(motion & 0x80) {
-
+ if (motion & 0x80) {
// clear observation register
spi_read();
diff --git a/drivers/sensors/adns9800.h b/drivers/sensors/adns9800.h
index 2f50b8f1be..e75a869c03 100644
--- a/drivers/sensors/adns9800.h
+++ b/drivers/sensors/adns9800.h
@@ -18,18 +18,48 @@
#include <stdint.h>
+#ifndef ADNS9800_CPI
+# define ADNS9800_CPI 1600
+#endif
+
+#ifndef ADNS9800_CLOCK_SPEED
+# define ADNS9800_CLOCK_SPEED 2000000
+#endif
+
+#ifndef ADNS9800_SPI_LSBFIRST
+# define ADNS9800_SPI_LSBFIRST false
+#endif
+
+#ifndef ADNS9800_SPI_MODE
+# define ADNS9800_SPI_MODE 3
+#endif
+
+#ifndef ADNS9800_SPI_DIVISOR
+# ifdef __AVR__
+# define ADNS9800_SPI_DIVISOR (F_CPU / ADNS9800_CLOCK_SPEED)
+# else
+# define ADNS9800_SPI_DIVISOR 64
+# endif
+#endif
+
+#ifndef ADNS9800_CS_PIN
+# error "No chip select pin defined -- missing ADNS9800_CS_PIN"
+#endif
+
typedef struct {
/* 200 - 8200 CPI supported */
uint16_t cpi;
-} config_adns_t;
+} config_adns9800_t;
typedef struct {
int16_t x;
int16_t y;
-} report_adns_t;
+} report_adns9800_t;
-void adns_init(void);
-config_adns_t adns_get_config(void);
-void adns_set_config(config_adns_t);
+void adns9800_init(void);
+config_adns9800_t adns9800_get_config(void);
+void adns9800_set_config(config_adns9800_t);
+uint16_t adns9800_get_cpi(void);
+void adns9800_set_cpi(uint16_t cpi);
/* Reads and clears the current delta values on the ADNS sensor */
-report_adns_t adns_get_report(void);
+report_adns9800_t adns9800_get_report(void);
diff --git a/drivers/sensors/adns9800_srom_A6.h b/drivers/sensors/adns9800_srom_A6.h
index f5b3abeb62..d86ecbbd9e 100644
--- a/drivers/sensors/adns9800_srom_A6.h
+++ b/drivers/sensors/adns9800_srom_A6.h
@@ -2,3077 +2,201 @@
#include "progmem.h"
-const uint16_t adns_firmware_length = 3070;
+#define FIRMWARE_LENGTH 3070
-const uint8_t adns_firmware_data[] PROGMEM = {
-0x03,
-0xa6,
-0x68,
-0x1e,
-0x7d,
-0x10,
-0x7e,
-0x7e,
-0x5f,
-0x1c,
-0xb8,
-0xf2,
-0x47,
-0x0c,
-0x7b,
-0x74,
-0x4b,
-0x14,
-0x8b,
-0x75,
-0x66,
-0x51,
-0x0b,
-0x8c,
-0x76,
-0x74,
-0x4b,
-0x14,
-0xaa,
-0xd6,
-0x0f,
-0x9c,
-0xba,
-0xf6,
-0x6e,
-0x3f,
-0xdd,
-0x38,
-0xd5,
-0x02,
-0x80,
-0x9b,
-0x82,
-0x6d,
-0x58,
-0x13,
-0xa4,
-0xab,
-0xb5,
-0xc9,
-0x10,
-0xa2,
-0xc6,
-0x0a,
-0x7f,
-0x5d,
-0x19,
-0x91,
-0xa0,
-0xa3,
-0xce,
-0xeb,
-0x3e,
-0xc9,
-0xf1,
-0x60,
-0x42,
-0xe7,
-0x4c,
-0xfb,
-0x74,
-0x6a,
-0x56,
-0x2e,
-0xbf,
-0xdd,
-0x38,
-0xd3,
-0x05,
-0x88,
-0x92,
-0xa6,
-0xce,
-0xff,
-0x5d,
-0x38,
-0xd1,
-0xcf,
-0xef,
-0x58,
-0xcb,
-0x65,
-0x48,
-0xf0,
-0x35,
-0x85,
-0xa9,
-0xb2,
-0x8f,
-0x5e,
-0xf3,
-0x80,
-0x94,
-0x97,
-0x7e,
-0x75,
-0x97,
-0x87,
-0x73,
-0x13,
-0xb0,
-0x8a,
-0x69,
-0xd4,
-0x0a,
-0xde,
-0xc1,
-0x79,
-0x59,
-0x36,
-0xdb,
-0x9d,
-0xd6,
-0xb8,
-0x15,
-0x6f,
-0xce,
-0x3c,
-0x72,
-0x32,
-0x45,
-0x88,
-0xdf,
-0x6c,
-0xa5,
-0x6d,
-0xe8,
-0x76,
-0x96,
-0x14,
-0x74,
-0x20,
-0xdc,
-0xf4,
-0xfa,
-0x37,
-0x6a,
-0x27,
-0x32,
-0xe3,
-0x29,
-0xbf,
-0xc4,
-0xc7,
-0x06,
-0x9d,
-0x58,
-0xe7,
-0x87,
-0x7c,
-0x2e,
-0x9f,
-0x6e,
-0x49,
-0x07,
-0x5d,
-0x23,
-0x64,
-0x54,
-0x83,
-0x6e,
-0xcb,
-0xb7,
-0x77,
-0xf7,
-0x2b,
-0x6e,
-0x0f,
-0x2e,
-0x66,
-0x12,
-0x60,
-0x55,
-0x65,
-0xfc,
-0x43,
-0xb3,
-0x58,
-0x73,
-0x5b,
-0xe8,
-0x67,
-0x04,
-0x43,
-0x02,
-0xde,
-0xb3,
-0x89,
-0xa0,
-0x6d,
-0x3a,
-0x27,
-0x79,
-0x64,
-0x5b,
-0x0c,
-0x16,
-0x9e,
-0x66,
-0xb1,
-0x8b,
-0x87,
-0x0c,
-0x5d,
-0xf2,
-0xb6,
-0x3d,
-0x71,
-0xdf,
-0x42,
-0x03,
-0x8a,
-0x06,
-0x8d,
-0xef,
-0x1d,
-0xa8,
-0x96,
-0x5c,
-0xed,
-0x31,
-0x61,
-0x5c,
-0xa1,
-0x34,
-0xf6,
-0x8c,
-0x08,
-0x60,
-0x33,
-0x07,
-0x00,
-0x3e,
-0x79,
-0x95,
-0x1b,
-0x43,
-0x7f,
-0xfe,
-0xb6,
-0xa6,
-0xd4,
-0x9d,
-0x76,
-0x72,
-0xbf,
-0xad,
-0xc0,
-0x15,
-0xe8,
-0x37,
-0x31,
-0xa3,
-0x72,
-0x63,
-0x52,
-0x1d,
-0x1c,
-0x5d,
-0x51,
-0x1b,
-0xe1,
-0xa9,
-0xed,
-0x60,
-0x32,
-0x3e,
-0xa9,
-0x50,
-0x28,
-0x53,
-0x06,
-0x59,
-0xe2,
-0xfc,
-0xe7,
-0x02,
-0x64,
-0x39,
-0x21,
-0x56,
-0x4a,
-0xa5,
-0x40,
-0x80,
-0x81,
-0xd5,
-0x5a,
-0x60,
-0x7b,
-0x68,
-0x84,
-0xf1,
-0xe0,
-0xb1,
-0xb6,
-0x5b,
-0xdf,
-0xa8,
-0x1d,
-0x6d,
-0x65,
-0x20,
-0xc0,
-0xa2,
-0xb9,
-0xd9,
-0xbb,
-0x00,
-0xa6,
-0xdb,
-0x8b,
-0x01,
-0x53,
-0x91,
-0xfe,
-0xc4,
-0x51,
-0x85,
-0xb0,
-0x96,
-0x7f,
-0xfd,
-0x51,
-0xdd,
-0x14,
-0x03,
-0x67,
-0x2e,
-0x75,
-0x1c,
-0x76,
-0xd3,
-0x6e,
-0xdd,
-0x99,
-0x55,
-0x76,
-0xe5,
-0xab,
-0x23,
-0xfc,
-0x4a,
-0xd5,
-0xc6,
-0xe8,
-0x2e,
-0xca,
-0x8a,
-0xb3,
-0xf6,
-0x8c,
-0x6c,
-0xb0,
-0xe9,
-0xf2,
-0xe7,
-0x9e,
-0x69,
-0x41,
-0xed,
-0xf1,
-0x6d,
-0xd2,
-0x86,
-0xd8,
-0x7e,
-0xcb,
-0x5d,
-0x47,
-0x6c,
-0x85,
-0x6a,
-0x23,
-0xed,
-0x20,
-0x40,
-0x93,
-0xb4,
-0x20,
-0xc7,
-0xa5,
-0xc9,
-0xaf,
-0x03,
-0x15,
-0xac,
-0x19,
-0xe5,
-0x2a,
-0x36,
-0xdf,
-0x6d,
-0xc5,
-0x8c,
-0x80,
-0x07,
-0xce,
-0x92,
-0x0c,
-0xd8,
-0x06,
-0x62,
-0x0f,
-0xdd,
-0x48,
-0x46,
-0x1a,
-0x53,
-0xc7,
-0x8a,
-0x8c,
-0x5d,
-0x5d,
-0xb4,
-0xa1,
-0x02,
-0xd3,
-0xa9,
-0xb8,
-0xf3,
-0x94,
-0x8f,
-0x3f,
-0xe5,
-0x54,
-0xd4,
-0x11,
-0x65,
-0xb2,
-0x5e,
-0x09,
-0x0b,
-0x81,
-0xe3,
-0x75,
-0xa7,
-0x89,
-0x81,
-0x39,
-0x6c,
-0x46,
-0xf6,
-0x06,
-0x9f,
-0x27,
-0x3b,
-0xb6,
-0x2d,
-0x5f,
-0x1d,
-0x4b,
-0xd4,
-0x7b,
-0x1d,
-0x61,
-0x74,
-0x89,
-0xe4,
-0xe3,
-0xbd,
-0x98,
-0x1b,
-0xc4,
-0x51,
-0x3b,
-0xa4,
-0xfa,
-0xe0,
-0x92,
-0xf7,
-0xbe,
-0xf2,
-0x4d,
-0xbb,
-0xff,
-0xad,
-0x4f,
-0x6d,
-0x68,
-0xc2,
-0x79,
-0x40,
-0xaa,
-0x9b,
-0x8f,
-0x0c,
-0x32,
-0x4b,
-0x5f,
-0x3e,
-0xab,
-0x59,
-0x98,
-0xb3,
-0xf5,
-0x1d,
-0xac,
-0x5e,
-0xbc,
-0x78,
-0xd3,
-0x01,
-0x6c,
-0x64,
-0x15,
-0x2f,
-0xd8,
-0x71,
-0xa6,
-0x2d,
-0x45,
-0xe1,
-0x22,
-0x42,
-0xe4,
-0x4e,
-0x04,
-0x3c,
-0x7d,
-0xf4,
-0x40,
-0x21,
-0xb4,
-0x67,
-0x05,
-0xa8,
-0xe2,
-0xf3,
-0x72,
-0x87,
-0x4c,
-0x7d,
-0xd9,
-0x1b,
-0x65,
-0x97,
-0xf3,
-0xc2,
-0xe3,
-0xe4,
-0xc8,
-0xd2,
-0xde,
-0xf6,
-0xef,
-0xdc,
-0xbb,
-0x44,
-0x08,
-0x5e,
-0xe2,
-0x45,
-0x27,
-0x01,
-0xb0,
-0xf6,
-0x43,
-0xe7,
-0x3a,
-0xf6,
-0xdc,
-0x9d,
-0xed,
-0xf3,
-0xc5,
-0x0c,
-0xb8,
-0x9c,
-0x98,
-0x3a,
-0xd8,
-0x36,
-0xee,
-0x96,
-0x72,
-0x67,
-0xe7,
-0x81,
-0x91,
-0xd5,
-0x05,
-0x0a,
-0xe0,
-0x82,
-0xd5,
-0x8f,
-0xe8,
-0xf9,
-0xb0,
-0xc9,
-0xcf,
-0x93,
-0xe7,
-0x04,
-0xc5,
-0xbc,
-0x2b,
-0x43,
-0x56,
-0x7e,
-0xe8,
-0x67,
-0x7c,
-0xe5,
-0xfb,
-0x49,
-0xad,
-0x5e,
-0x9f,
-0x25,
-0x13,
-0xde,
-0x6e,
-0x6e,
-0xe9,
-0xf1,
-0xec,
-0x87,
-0x0b,
-0x59,
-0x81,
-0x76,
-0x84,
-0x76,
-0xb3,
-0x24,
-0xaf,
-0x30,
-0xfd,
-0x27,
-0x8b,
-0xab,
-0xd8,
-0x00,
-0x8b,
-0x9b,
-0x0c,
-0xd2,
-0xb2,
-0x4e,
-0x5e,
-0x9d,
-0x1d,
-0x96,
-0x01,
-0x00,
-0x67,
-0xc1,
-0x5f,
-0x02,
-0x20,
-0xfd,
-0x45,
-0x6a,
-0x01,
-0x60,
-0x58,
-0x45,
-0xca,
-0x47,
-0x21,
-0x90,
-0x5a,
-0xc4,
-0x43,
-0x26,
-0x1a,
-0xd7,
-0xa5,
-0x4a,
-0xb2,
-0x5d,
-0x2b,
-0x35,
-0x49,
-0xfb,
-0xa5,
-0x17,
-0x92,
-0x21,
-0x1e,
-0x93,
-0x96,
-0x67,
-0xa2,
-0x7e,
-0x36,
-0x7a,
-0xde,
-0x5f,
-0xbe,
-0x7a,
-0x58,
-0x9d,
-0xf8,
-0x78,
-0xa3,
-0xfa,
-0xc8,
-0xd5,
-0x17,
-0xf0,
-0x21,
-0x97,
-0x8c,
-0x80,
-0xb5,
-0x4b,
-0x3b,
-0xbd,
-0xbb,
-0x41,
-0x21,
-0xa8,
-0x50,
-0x67,
-0xf7,
-0xe7,
-0x19,
-0x80,
-0x10,
-0x8e,
-0xce,
-0x04,
-0x18,
-0x3f,
-0x51,
-0x6b,
-0x77,
-0xd8,
-0x9e,
-0x16,
-0xaf,
-0xec,
-0xef,
-0x48,
-0x16,
-0x4d,
-0x9e,
-0x85,
-0x38,
-0x18,
-0x3e,
-0xd4,
-0x28,
-0x87,
-0x60,
-0x2a,
-0xf6,
-0x7f,
-0x09,
-0x86,
-0x6f,
-0x9c,
-0x3c,
-0x3a,
-0xff,
-0xab,
-0xd0,
-0x61,
-0xa2,
-0x97,
-0x0d,
-0x71,
-0x94,
-0x7e,
-0xfd,
-0xb9,
-0x80,
-0x02,
-0x89,
-0x6a,
-0xb3,
-0x84,
-0x6c,
-0x2a,
-0x77,
-0x62,
-0xbe,
-0x0b,
-0xf4,
-0xaf,
-0xac,
-0x7b,
-0x7c,
-0x8e,
-0xca,
-0x01,
-0xba,
-0x71,
-0x78,
-0x94,
-0xfd,
-0xb5,
-0x39,
-0xa4,
-0x4d,
-0x2f,
-0x78,
-0xcf,
-0xca,
-0x92,
-0x0c,
-0x1a,
-0x99,
-0x48,
-0x4c,
-0x11,
-0x96,
-0xb5,
-0x4e,
-0x41,
-0x28,
-0xe4,
-0xa6,
-0xfe,
-0x4b,
-0x72,
-0x91,
-0xe7,
-0xd4,
-0xdd,
-0x9f,
-0x12,
-0xe6,
-0x29,
-0x38,
-0xce,
-0x45,
-0xae,
-0x02,
-0xb8,
-0x24,
-0xae,
-0xbd,
-0xe9,
-0x66,
-0x08,
-0x62,
-0xa2,
-0x2c,
-0x2b,
-0x00,
-0xe2,
-0x23,
-0xd9,
-0xc4,
-0x48,
-0xe4,
-0xd3,
-0xac,
-0xbb,
-0x34,
-0xc7,
-0xf0,
-0xe3,
-0x4f,
-0xb9,
-0x30,
-0xea,
-0xa2,
-0x12,
-0xf1,
-0x30,
-0x2c,
-0x36,
-0xde,
-0x48,
-0xf2,
-0xb0,
-0x4c,
-0x43,
-0x3f,
-0x2e,
-0x58,
-0xe4,
-0x20,
-0xe3,
-0x58,
-0xcd,
-0x31,
-0x22,
-0xf0,
-0xa2,
-0x2a,
-0xe6,
-0x19,
-0x90,
-0x55,
-0x86,
-0xf6,
-0x55,
-0x79,
-0xd1,
-0xd7,
-0x46,
-0x2f,
-0xc0,
-0xdc,
-0x99,
-0xe8,
-0xf3,
-0x6a,
-0xdf,
-0x7f,
-0xeb,
-0x24,
-0x4a,
-0x1e,
-0x5a,
-0x75,
-0xde,
-0x2f,
-0x5c,
-0x19,
-0x61,
-0x03,
-0x53,
-0x54,
-0x6a,
-0x3b,
-0x18,
-0x70,
-0xb6,
-0x4f,
-0xf1,
-0x9c,
-0x0a,
-0x59,
-0x9d,
-0x19,
-0x92,
-0x65,
-0x8c,
-0x83,
-0x14,
-0x2d,
-0x44,
-0x8a,
-0x75,
-0xa9,
-0xf5,
-0x90,
-0xd2,
-0x66,
-0x4e,
-0xfa,
-0x69,
-0x0f,
-0x5b,
-0x0b,
-0x98,
-0x65,
-0xc8,
-0x11,
-0x42,
-0x59,
-0x7f,
-0xdd,
-0x1b,
-0x75,
-0x17,
-0x31,
-0x4c,
-0x75,
-0x58,
-0xeb,
-0x58,
-0x63,
-0x7d,
-0xf2,
-0xa6,
-0xc2,
-0x6e,
-0xb7,
-0x3f,
-0x3e,
-0x5e,
-0x47,
-0xad,
-0xb7,
-0x04,
-0xe8,
-0x05,
-0xf8,
-0xb2,
-0xcf,
-0x19,
-0xf3,
-0xd2,
-0x85,
-0xfe,
-0x3e,
-0x3e,
-0xb1,
-0x62,
-0x08,
-0x2c,
-0x10,
-0x07,
-0x0d,
-0x73,
-0x90,
-0x17,
-0xfa,
-0x9b,
-0x56,
-0x02,
-0x75,
-0xf9,
-0x51,
-0xe0,
-0xe9,
-0x1a,
-0x7b,
-0x9f,
-0xb3,
-0xf3,
-0x98,
-0xb8,
-0x1c,
-0x9c,
-0xe1,
-0xd5,
-0x35,
-0xae,
-0xc8,
-0x60,
-0x48,
-0x11,
-0x09,
-0x94,
-0x6b,
-0xd0,
-0x8b,
-0x15,
-0xbc,
-0x05,
-0x68,
-0xd3,
-0x54,
-0x8a,
-0x51,
-0x39,
-0x5c,
-0x42,
-0x76,
-0xce,
-0xd8,
-0xad,
-0x89,
-0x30,
-0xc9,
-0x05,
-0x1c,
-0xcc,
-0x94,
-0x3f,
-0x0f,
-0x90,
-0x6f,
-0x72,
-0x2d,
-0x85,
-0x64,
-0x9a,
-0xb9,
-0x23,
-0xf9,
-0x0b,
-0xc3,
-0x7c,
-0x39,
-0x0f,
-0x97,
-0x07,
-0x97,
-0xda,
-0x58,
-0x48,
-0x33,
-0x05,
-0x23,
-0xb8,
-0x82,
-0xe8,
-0xd3,
-0x53,
-0x89,
-0xaf,
-0x33,
-0x80,
-0x22,
-0x84,
-0x0c,
-0x95,
-0x5c,
-0x67,
-0xb8,
-0x77,
-0x0c,
-0x5c,
-0xa2,
-0x5f,
-0x3d,
-0x58,
-0x0f,
-0x27,
-0xf3,
-0x2f,
-0xae,
-0x48,
-0xbd,
-0x0b,
-0x6f,
-0x54,
-0xfb,
-0x67,
-0x4c,
-0xea,
-0x32,
-0x27,
-0xf1,
-0xfa,
-0xe2,
-0xb0,
-0xec,
-0x0b,
-0x15,
-0xb4,
-0x70,
-0xf6,
-0x5c,
-0xdd,
-0x71,
-0x60,
-0xc3,
-0xc1,
-0xa8,
-0x32,
-0x65,
-0xac,
-0x7a,
-0x77,
-0x41,
-0xe5,
-0xa9,
-0x6b,
-0x11,
-0x81,
-0xfa,
-0x34,
-0x8d,
-0xfb,
-0xc1,
-0x80,
-0x6e,
-0xc4,
-0x60,
-0x30,
-0x07,
-0xd4,
-0x8b,
-0x67,
-0xbd,
-0xaa,
-0x8c,
-0x9c,
-0x64,
-0xac,
-0xdb,
-0x0b,
-0x24,
-0x8b,
-0x63,
-0x6f,
-0xe6,
-0xbc,
-0xe7,
-0x33,
-0xa4,
-0x4a,
-0x4c,
-0xa7,
-0x9f,
-0x43,
-0x53,
-0xd2,
-0xbb,
-0x8f,
-0x43,
-0xc7,
-0x3d,
-0x78,
-0x68,
-0x3f,
-0xa5,
-0x3d,
-0xca,
-0x69,
-0x84,
-0xa6,
-0x97,
-0x2d,
-0xc0,
-0x7d,
-0x31,
-0x34,
-0x55,
-0x1d,
-0x07,
-0xb1,
-0x5f,
-0x40,
-0x5c,
-0x93,
-0xb0,
-0xbc,
-0x7c,
-0xb0,
-0xbc,
-0xe7,
-0x12,
-0xee,
-0x6b,
-0x2b,
-0xd3,
-0x4d,
-0x67,
-0x70,
-0x3a,
-0x9a,
-0xf2,
-0x3c,
-0x7c,
-0x81,
-0xfa,
-0xd7,
-0xd9,
-0x90,
-0x91,
-0x81,
-0xb8,
-0xb1,
-0xf3,
-0x48,
-0x6a,
-0x26,
-0x4f,
-0x0c,
-0xce,
-0xb0,
-0x9e,
-0xfd,
-0x4a,
-0x3a,
-0xaf,
-0xac,
-0x5b,
-0x3f,
-0xbf,
-0x44,
-0x5a,
-0xa3,
-0x19,
-0x1e,
-0x4b,
-0xe7,
-0x36,
-0x6a,
-0xd7,
-0x20,
-0xae,
-0xd7,
-0x7d,
-0x3b,
-0xe7,
-0xff,
-0x3a,
-0x86,
-0x2e,
-0xd0,
-0x4a,
-0x3e,
-0xaf,
-0x9f,
-0x8e,
-0x01,
-0xbf,
-0xf8,
-0x4f,
-0xc1,
-0xe8,
-0x6f,
-0x74,
-0xe1,
-0x45,
-0xd3,
-0xf7,
-0x04,
-0x6a,
-0x4b,
-0x9d,
-0xec,
-0x33,
-0x27,
-0x76,
-0xd7,
-0xc5,
-0xe1,
-0xb0,
-0x3b,
-0x0e,
-0x23,
-0xec,
-0xf0,
-0x86,
-0xd2,
-0x1a,
-0xbf,
-0x3d,
-0x04,
-0x62,
-0xb3,
-0x6c,
-0xb2,
-0xeb,
-0x17,
-0x05,
-0xa6,
-0x0a,
-0x8a,
-0x7e,
-0x83,
-0x1c,
-0xb6,
-0x37,
-0x09,
-0xc6,
-0x0b,
-0x70,
-0x3c,
-0xb5,
-0x93,
-0x81,
-0xd8,
-0x93,
-0xa0,
-0x5f,
-0x1e,
-0x08,
-0xe2,
-0xc6,
-0xe5,
-0xc9,
-0x72,
-0xf1,
-0xf1,
-0xc1,
-0xed,
-0xd5,
-0x58,
-0x93,
-0x83,
-0xf8,
-0x65,
-0x67,
-0x2e,
-0x0d,
-0xa9,
-0xf1,
-0x64,
-0x12,
-0xe6,
-0x4c,
-0xea,
-0x15,
-0x3f,
-0x8c,
-0x1a,
-0xb6,
-0xbf,
-0xf6,
-0xb9,
-0x52,
-0x35,
-0x09,
-0xb0,
-0xe6,
-0xf7,
-0xcd,
-0xf1,
-0xa5,
-0xaa,
-0x81,
-0xd1,
-0x81,
-0x6f,
-0xb4,
-0xa9,
-0x66,
-0x1f,
-0xfc,
-0x48,
-0xc0,
-0xb6,
-0xd1,
-0x8b,
-0x06,
-0x2f,
-0xf6,
-0xef,
-0x1f,
-0x0a,
-0xe6,
-0xce,
-0x3a,
-0x4a,
-0x55,
-0xbf,
-0x6d,
-0xf9,
-0x4d,
-0xd4,
-0x08,
-0x45,
-0x4b,
-0xc3,
-0x66,
-0x19,
-0x92,
-0x10,
-0xe1,
-0x17,
-0x8e,
-0x28,
-0x91,
-0x16,
-0xbf,
-0x3c,
-0xee,
-0xa3,
-0xa6,
-0x99,
-0x92,
-0x10,
-0xe1,
-0xf6,
-0xcc,
-0xac,
-0xb8,
-0x65,
-0x0b,
-0x43,
-0x66,
-0xf8,
-0xe3,
-0xe5,
-0x3f,
-0x24,
-0x89,
-0x47,
-0x5d,
-0x78,
-0x43,
-0xd0,
-0x61,
-0x17,
-0xbd,
-0x5b,
-0x64,
-0x54,
-0x08,
-0x45,
-0x59,
-0x93,
-0xf6,
-0x95,
-0x8a,
-0x41,
-0x51,
-0x62,
-0x4b,
-0x51,
-0x02,
-0x30,
-0x73,
-0xc7,
-0x87,
-0xc5,
-0x4b,
-0xa2,
-0x97,
-0x0f,
-0xe8,
-0x46,
-0x5f,
-0x7e,
-0x2a,
-0xe1,
-0x30,
-0x20,
-0xb0,
-0xfa,
-0xe7,
-0xce,
-0x61,
-0x42,
-0x57,
-0x6e,
-0x21,
-0xf3,
-0x7a,
-0xec,
-0xe3,
-0x25,
-0xc7,
-0x25,
-0xf3,
-0x67,
-0xa7,
-0x57,
-0x40,
-0x00,
-0x02,
-0xcf,
-0x1c,
-0x80,
-0x77,
-0x67,
-0xbd,
-0x70,
-0xa1,
-0x19,
-0x92,
-0x31,
-0x75,
-0x93,
-0x27,
-0x27,
-0xb6,
-0x82,
-0xe4,
-0xeb,
-0x1d,
-0x78,
-0x48,
-0xe7,
-0xa5,
-0x5e,
-0x57,
-0xef,
-0x64,
-0x28,
-0x64,
-0x1b,
-0xf6,
-0x11,
-0xb2,
-0x03,
-0x9d,
-0xb9,
-0x18,
-0x02,
-0x27,
-0xf7,
-0xbe,
-0x9d,
-0x55,
-0xfc,
-0x00,
-0xd2,
-0xc7,
-0xae,
-0xad,
-0x0b,
-0xc5,
-0xe9,
-0x42,
-0x41,
-0x48,
-0xd8,
-0x32,
-0xcf,
-0xf6,
-0x0f,
-0xf5,
-0xbc,
-0x97,
-0xc6,
-0x99,
-0x47,
-0x76,
-0xbd,
-0x89,
-0x06,
-0x0f,
-0x63,
-0x0c,
-0x51,
-0xd4,
-0x5e,
-0xea,
-0x48,
-0xa8,
-0xa2,
-0x56,
-0x1c,
-0x79,
-0x84,
-0x86,
-0x40,
-0x88,
-0x41,
-0x76,
-0x55,
-0xfc,
-0xc2,
-0xd7,
-0xfd,
-0xc9,
-0xc7,
-0x80,
-0x61,
-0x35,
-0xa7,
-0x43,
-0x20,
-0xf7,
-0xeb,
-0x6c,
-0x66,
-0x13,
-0xb0,
-0xec,
-0x02,
-0x75,
-0x3e,
-0x4b,
-0xaf,
-0xb9,
-0x5d,
-0x40,
-0xda,
-0xd6,
-0x6e,
-0x2d,
-0x39,
-0x54,
-0xc2,
-0x95,
-0x35,
-0x54,
-0x25,
-0x72,
-0xe1,
-0x78,
-0xb8,
-0xeb,
-0xc1,
-0x16,
-0x58,
-0x0f,
-0x9c,
-0x9b,
-0xb4,
-0xea,
-0x37,
-0xec,
-0x3b,
-0x11,
-0xba,
-0xd5,
-0x8a,
-0xa9,
-0xe3,
-0x98,
-0x00,
-0x51,
-0x1c,
-0x14,
-0xe0,
-0x40,
-0x96,
-0xe5,
-0xe9,
-0xf2,
-0x21,
-0x22,
-0xb1,
-0x23,
-0x60,
-0x78,
-0xd3,
-0x17,
-0xf8,
-0x7a,
-0xa5,
-0xa8,
-0xba,
-0x20,
-0xd3,
-0x15,
-0x1e,
-0x32,
-0xe4,
-0x5e,
-0x15,
-0x48,
-0xae,
-0xa9,
-0xe5,
-0xb8,
-0x33,
-0xec,
-0xe8,
-0xa2,
-0x42,
-0xac,
-0xbf,
-0x10,
-0x84,
-0x53,
-0x87,
-0x19,
-0xb4,
-0x5f,
-0x76,
-0x4d,
-0x01,
-0x9d,
-0x56,
-0x74,
-0xd9,
-0x5c,
-0x97,
-0xe7,
-0x88,
-0xea,
-0x3a,
-0xbf,
-0xdc,
-0x4c,
-0x33,
-0x8a,
-0x16,
-0xb9,
-0x5b,
-0xfa,
-0xd8,
-0x42,
-0xa7,
-0xbb,
-0x3c,
-0x04,
-0x27,
-0x78,
-0x49,
-0x81,
-0x2a,
-0x5a,
-0x7d,
-0x7c,
-0x23,
-0xa8,
-0xba,
-0xf7,
-0x9a,
-0x9f,
-0xd2,
-0x66,
-0x3e,
-0x38,
-0x3c,
-0x75,
-0xf9,
-0xd1,
-0x30,
-0x26,
-0x30,
-0x6e,
-0x5a,
-0x6e,
-0xdc,
-0x6a,
-0x69,
-0x32,
-0x50,
-0x33,
-0x47,
-0x9e,
-0xa4,
-0xa8,
-0x64,
-0x66,
-0xf0,
-0x8a,
-0xe4,
-0xfd,
-0x27,
-0x6f,
-0x51,
-0x25,
-0x8b,
-0x43,
-0x74,
-0xc9,
-0x8e,
-0xbd,
-0x88,
-0x31,
-0xbe,
-0xec,
-0x65,
-0xd2,
-0xcb,
-0x8d,
-0x5a,
-0x13,
-0x48,
-0x16,
-0x8c,
-0x61,
-0x0b,
-0x11,
-0xf6,
-0xc6,
-0x66,
-0xae,
-0xc3,
-0xcc,
-0x0c,
-0xd2,
-0xe1,
-0x9f,
-0x82,
-0x41,
-0x3f,
-0x56,
-0xf9,
-0x73,
-0xef,
-0xdc,
-0x30,
-0x50,
-0xcf,
-0xb6,
-0x7f,
-0xbc,
-0xd0,
-0xb3,
-0x10,
-0xab,
-0x24,
-0xe4,
-0xec,
-0xad,
-0x18,
-0x8c,
-0x39,
-0x2d,
-0x30,
-0x4c,
-0xc5,
-0x40,
-0x0d,
-0xf6,
-0xac,
-0xd6,
-0x18,
-0x5d,
-0x96,
-0xbf,
-0x5f,
-0x71,
-0x75,
-0x96,
-0x22,
-0x97,
-0x0f,
-0x02,
-0x94,
-0x6e,
-0xa6,
-0xae,
-0x6d,
-0x8f,
-0x1e,
-0xca,
-0x12,
-0x9b,
-0x2a,
-0x1c,
-0xce,
-0xa9,
-0xee,
-0xfd,
-0x12,
-0x8e,
-0xfc,
-0xed,
-0x09,
-0x33,
-0xba,
-0xf4,
-0x1a,
-0x15,
-0xf6,
-0x9d,
-0x87,
-0x16,
-0x43,
-0x7c,
-0x78,
-0x57,
-0xe1,
-0x44,
-0xc9,
-0xeb,
-0x1f,
-0x58,
-0x4d,
-0xc1,
-0x49,
-0x11,
-0x5c,
-0xb2,
-0x11,
-0xa8,
-0x55,
-0x16,
-0xf1,
-0xc6,
-0x50,
-0xe9,
-0x87,
-0x89,
-0xf6,
-0xcf,
-0xd8,
-0x9c,
-0x51,
-0xa7,
-0xbc,
-0x5b,
-0x31,
-0x6d,
-0x4d,
-0x51,
-0xd0,
-0x4c,
-0xbc,
-0x0d,
-0x58,
-0x2d,
-0x7b,
-0x88,
-0x7a,
-0xf9,
-0x8e,
-0xd6,
-0x40,
-0x4d,
-0xbb,
-0xbe,
-0xc4,
-0xe5,
-0x07,
-0xfc,
-0xd9,
-0x7b,
-0x6d,
-0xa6,
-0x42,
-0x57,
-0x8f,
-0x02,
-0x94,
-0x4f,
-0xe4,
-0x2a,
-0x65,
-0xe2,
-0x19,
-0x5a,
-0x50,
-0xe1,
-0x25,
-0x65,
-0x4a,
-0x60,
-0xc2,
-0xcd,
-0xa8,
-0xec,
-0x05,
-0x2e,
-0x87,
-0x7b,
-0x95,
-0xb7,
-0x4f,
-0xa0,
-0x0b,
-0x1b,
-0x4a,
-0x7f,
-0x92,
-0xc8,
-0x90,
-0xee,
-0x89,
-0x1e,
-0x10,
-0xd2,
-0x85,
-0xe4,
-0x9f,
-0x63,
-0xc8,
-0x12,
-0xbb,
-0x4e,
-0xb8,
-0xcf,
-0x0a,
-0xec,
-0x18,
-0x4e,
-0xe6,
-0x7c,
-0xb3,
-0x33,
-0x26,
-0xc7,
-0x1f,
-0xd2,
-0x04,
-0x23,
-0xea,
-0x07,
-0x0c,
-0x5f,
-0x90,
-0xbd,
-0xa7,
-0x6a,
-0x0f,
-0x4a,
-0xd6,
-0x10,
-0x01,
-0x3c,
-0x12,
-0x29,
-0x2e,
-0x96,
-0xc0,
-0x4d,
-0xbb,
-0xbe,
-0xe5,
-0xa7,
-0x83,
-0xd5,
-0x6a,
-0x3c,
-0xe3,
-0x5b,
-0xb8,
-0xf2,
-0x5c,
-0x6d,
-0x1f,
-0xa6,
-0xf3,
-0x12,
-0x24,
-0xf6,
-0xd6,
-0x3b,
-0x10,
-0x14,
-0x09,
-0x07,
-0x82,
-0xe8,
-0x30,
-0x6a,
-0x99,
-0xdc,
-0x95,
-0x01,
-0x9c,
-0xd4,
-0x68,
-0x3b,
-0xca,
-0x98,
-0x12,
-0xab,
-0x77,
-0x25,
-0x15,
-0x7d,
-0x10,
-0x32,
-0x45,
-0x98,
-0xcd,
-0x7a,
-0xdf,
-0x71,
-0x8a,
-0x75,
-0xc1,
-0x1c,
-0xd4,
-0x68,
-0x25,
-0xeb,
-0xbb,
-0x54,
-0x27,
-0x6f,
-0x2a,
-0xf7,
-0xb9,
-0x98,
-0x03,
-0x27,
-0xde,
-0x24,
-0xa8,
-0xbb,
-0x98,
-0xc2,
-0x84,
-0xff,
-0x9b,
-0x51,
-0xd8,
-0x53,
-0x50,
-0xda,
-0xf5,
-0x88,
-0xaa,
-0x87,
-0x2f,
-0xae,
-0xd6,
-0xea,
-0x6b,
-0xde,
-0xc8,
-0xd7,
-0xa7,
-0x28,
-0x65,
-0x81,
-0xe8,
-0xb2,
-0x3b,
-0x1d,
-0x4f,
-0x75,
-0x8f,
-0x9f,
-0x7a,
-0x74,
-0x8e,
-0xc1,
-0x5f,
-0x9a,
-0xa8,
-0x9d,
-0xfa,
-0x03,
-0xa3,
-0x71,
-0x9b,
-0x37,
-0x6d,
-0xd5,
-0x0b,
-0xf5,
-0xe1,
-0xa1,
-0x1b,
-0x01,
-0x6a,
-0xc6,
-0x67,
-0xaa,
-0xea,
-0x2c,
-0x9d,
-0xa4,
-0xd2,
-0x6e,
-0xfc,
-0xde,
-0x2e,
-0x7f,
-0x94,
-0x69,
-0xe5,
-0x4a,
-0xe0,
-0x01,
-0x48,
-0x3c,
-0x6b,
-0xf7,
-0x1e,
-0xb6,
-0x0b,
-0x5f,
-0xf9,
-0x2e,
-0x07,
-0xc5,
-0xe8,
-0xae,
-0x37,
-0x1b,
-0xbc,
-0x3c,
-0xd8,
-0xd5,
-0x0b,
-0x91,
-0x9e,
-0x80,
-0x24,
-0xf5,
-0x06,
-0x0c,
-0x0e,
-0x98,
-0x07,
-0x96,
-0x2d,
-0x19,
-0xdc,
-0x58,
-0x93,
-0xcc,
-0xfb,
-0x4e,
-0xeb,
-0xbd,
-0x0f,
-0xf5,
-0xaf,
-0x01,
-0xfa,
-0xf1,
-0x7c,
-0x43,
-0x8c,
-0xb8,
-0x56,
-0x3e,
-0xbe,
-0x77,
-0x4e,
-0x2b,
-0xf7,
-0xbb,
-0xb7,
-0x45,
-0x47,
-0xcd,
-0xcc,
-0xa6,
-0x4c,
-0x72,
-0x7b,
-0x6a,
-0x2a,
-0x70,
-0x13,
-0x07,
-0xfd,
-0xb8,
-0x9c,
-0x98,
-0x3a,
-0xd8,
-0x23,
-0x67,
-0x5b,
-0x34,
-0xd5,
-0x14,
-0x0c,
-0xab,
-0x77,
-0x1f,
-0xf8,
-0x3d,
-0x5a,
-0x9f,
-0x92,
-0xb7,
-0x2c,
-0xad,
-0x31,
-0xde,
-0x61,
-0x07,
-0xb3,
-0x6b,
-0xf7,
-0x38,
-0x15,
-0x95,
-0x46,
-0x14,
-0x48,
-0x53,
-0x69,
-0x52,
-0x66,
-0x07,
-0x6d,
-0x83,
-0x71,
-0x8a,
-0x67,
-0x25,
-0x20,
-0x0f,
-0xfe,
-0xd7,
-0x02,
-0xd7,
-0x6e,
-0x2c,
-0xd2,
-0x1a,
-0x0a,
-0x5d,
-0xfd,
-0x0f,
-0x74,
-0xe3,
-0xa4,
-0x36,
-0x07,
-0x9a,
-0xdf,
-0xd4,
-0x79,
-0xbf,
-0xef,
-0x59,
-0xc0,
-0x44,
-0x52,
-0x87,
-0x9a,
-0x6e,
-0x1d,
-0x0e,
-0xee,
-0xde,
-0x2e,
-0x1a,
-0xa9,
-0x8f,
-0x3a,
-0xc9,
-0xba,
-0xec,
-0x99,
-0x78,
-0x2d,
-0x55,
-0x6b,
-0x14,
-0xc2,
-0x06,
-0xd5,
-0xfc,
-0x93,
-0x53,
-0x4d,
-0x11,
-0x8c,
-0xf8,
-0xfa,
-0x79,
-0x7c,
-0xa6,
-0x64,
-0xae,
-0x61,
-0xb8,
-0x7b,
-0x94,
-0x56,
-0xa6,
-0x39,
-0x78,
-0x9a,
-0xe5,
-0xc7,
-0xdf,
-0x18,
-0x63,
-0x23,
-0x9c,
-0xfa,
-0x66,
-0xbb,
-0xb7,
-0x5a,
-0x27,
-0x4c,
-0xd1,
-0xa1,
-0x83,
-0x22,
-0xb3,
-0x52,
-0x49,
-0x35,
-0xb0,
-0x22,
-0x83,
-0x59,
-0x12,
-0x00,
-0x16,
-0x98,
-0xdd,
-0xad,
-0xc2,
-0x94,
-0xf9,
-0xd3,
-0x7b,
-0x64,
-0x7f,
-0x44,
-0x3e,
-0x3c,
-0x8b,
-0x9a,
-0x83,
-0x9c,
-0x69,
-0x6b,
-0xe4,
-0xdf,
-0x9f,
-0xed,
-0x54,
-0x1f,
-0xe5,
-0x5d,
-0x7a,
-0x05,
-0x82,
-0xb3,
-0xdd,
-0xef,
-0xfc,
-0x53,
-0x96,
-0xb0,
-0x2c,
-0x5a,
-0xf8,
-0xdf,
-0x9c,
-0x8b,
-0x16,
-0x4e,
-0xdf,
-0xda,
-0x4d,
-0x09,
-0x09,
-0x69,
-0x50,
-0x03,
-0x65,
-0xd8,
-0x73,
-0x70,
-0xe8,
-0x86,
-0xbf,
-0xbb,
-0x35,
-0xce,
-0xb2,
-0x46,
-0xcb,
-0x02,
-0x00,
-0x5b,
-0xb4,
-0xe2,
-0xc6,
-0x8f,
-0x2f,
-0x98,
-0xaf,
-0x87,
-0x4b,
-0x48,
-0x45,
-0xed,
-0xcc,
-0x1d,
-0xe6,
-0x58,
-0xd6,
-0xf2,
-0x50,
-0x25,
-0x9f,
-0x52,
-0xc7,
-0xcb,
-0x8a,
-0x17,
-0x9d,
-0x5b,
-0xe5,
-0xc8,
-0xd7,
-0x72,
-0xb7,
-0x52,
-0xb2,
-0xc4,
-0x98,
-0xe3,
-0x7a,
-0x17,
-0x3e,
-0xc6,
-0x60,
-0xa7,
-0x97,
-0xb0,
-0xcf,
-0x18,
-0x81,
-0x53,
-0x84,
-0x4c,
-0xd5,
-0x17,
-0x32,
-0x03,
-0x13,
-0x39,
-0x51,
-0x09,
-0x10,
-0xe3,
-0x77,
-0x49,
-0x4f,
-0x62,
-0x01,
-0xbf,
-0x8c,
-0x9a,
-0xe0,
-0x41,
-0x9e,
-0x89,
-0x74,
-0x36,
-0xf9,
-0x96,
-0x86,
-0x2e,
-0x96,
-0x1c,
-0x4a,
-0xb7,
-0x2b,
-0x4a,
-0x97,
-0xbc,
-0x99,
-0x40,
-0xa3,
-0xe0,
-0x3d,
-0xc8,
-0xad,
-0x2f,
-0xdf,
-0x4f,
-0x2c,
-0xc4,
-0x69,
-0x82,
-0x9f,
-0x9b,
-0x81,
-0x0c,
-0x61,
-0x5c,
-0xa5,
-0x9d,
-0x8c,
-0x89,
-0xc0,
-0x2c,
-0xb4,
-0x4a,
-0x33,
-0x4e,
-0xeb,
-0xa2,
-0x56,
-0x40,
-0xc0,
-0xc2,
-0x46,
-0xaf,
-0x6a,
-0xfc,
-0x67,
-0xd1,
-0x80,
-0x5e,
-0xc5,
-0x6d,
-0x84,
-0x43,
-0x27,
-0x3f,
-0x55,
-0x15,
-0x96,
-0x6a,
-0xa0,
-0xa5,
-0xda,
-0xb7,
-0xff,
-0xb7,
-0x75,
-0x6e,
-0x4c,
-0x49,
-0x91,
-0x9d,
-0x22,
-0xa3,
-0x46,
-0xea,
-0xed,
-0x9a,
-0x00,
-0xe2,
-0x32,
-0xc3,
-0xd6,
-0xa9,
-0x71,
-0x20,
-0x55,
-0xa3,
-0x19,
-0xed,
-0xf8,
-0x4f,
-0xa7,
-0x12,
-0x9c,
-0x66,
-0x87,
-0xaf,
-0x4e,
-0xb7,
-0xf0,
-0xdb,
-0xbf,
-0xef,
-0xf0,
-0xf6,
-0xaf,
-0xea,
-0xda,
-0x09,
-0xfe,
-0xde,
-0x38,
-0x5c,
-0xa5,
-0xa2,
-0xdf,
-0x99,
-0x45,
-0xa8,
-0xe4,
-0xe7,
-0x92,
-0xac,
-0x67,
-0xaa,
-0x4f,
-0xbf,
-0x77,
-0x3e,
-0xa2,
-0x40,
-0x49,
-0x22,
-0x4a,
-0x1e,
-0x3b,
-0xaa,
-0x70,
-0x7f,
-0x95,
-0xaf,
-0x37,
-0x4b,
-0xfc,
-0x99,
-0xe2,
-0xe0,
-0xba,
-0xd7,
-0x34,
-0xce,
-0x55,
-0x88,
-0x5b,
-0x84,
-0x1b,
-0x57,
-0xc4,
-0x80,
-0x03,
-0x53,
-0xc9,
-0x2f,
-0x93,
-0x04,
-0x4d,
-0xd5,
-0x96,
-0xe5,
-0x70,
-0xa6,
-0x6e,
-0x63,
-0x5d,
-0x9d,
-0x6c,
-0xdb,
-0x02,
-0x0a,
-0xa9,
-0xda,
-0x8b,
-0x53,
-0xdc,
-0xd9,
-0x9a,
-0xc5,
-0x94,
-0x2c,
-0x91,
-0x92,
-0x2a,
-0xde,
-0xbb,
-0x8b,
-0x13,
-0xb9,
-0x19,
-0x96,
-0x64,
-0xcc,
-0xf2,
-0x64,
-0x39,
-0xb7,
-0x75,
-0x49,
-0xe9,
-0x86,
-0xc2,
-0x86,
-0x62,
-0xd9,
-0x24,
-0xd3,
-0x81,
-0x35,
-0x49,
-0xfc,
-0xa0,
-0xa5,
-0xa0,
-0x93,
-0x05,
-0x64,
-0xb4,
-0x1a,
-0x57,
-0xce,
-0x0c,
-0x90,
-0x02,
-0x27,
-0xc5,
-0x7a,
-0x2b,
-0x5d,
-0xae,
-0x3e,
-0xd5,
-0xdd,
-0x10,
-0x7c,
-0x14,
-0xea,
-0x3a,
-0x08,
-0xac,
-0x72,
-0x4e,
-0x90,
-0x3d,
-0x3b,
-0x7c,
-0x86,
-0x2e,
-0xeb,
-0xd4,
-0x06,
-0x70,
-0xe6,
-0xc7,
-0xfb,
-0x5f,
-0xbd,
-0x18,
-0xf4,
-0x11,
-0xa4,
-0x1a,
-0x93,
-0xc3,
-0xbe,
-0xd9,
-0xfb,
-0x26,
-0x48,
-0x2f,
-0x37,
-0x3c,
-0xd0,
-0x03,
-0x47,
-0x1a,
-0xf7,
-0x62,
-0x19,
-0x24,
-0x5c,
-0xf4,
-0xa8,
-0x92,
-0x20,
-0x7a,
-0xf2,
-0x9e,
-0x2a,
-0xc5,
-0x95,
-0xa2,
-0xfb,
-0xa4,
-0xea,
-0x85,
-0xd8,
-0x56,
-0xb7,
-0x70,
-0xd1,
-0x60,
-0x30,
-0xa5,
-0x30,
-0x82,
-0x70,
-0xdc,
-0x7a,
-0x65,
-0x8a,
-0x36,
-0x3f,
-0x5b,
-0x0c,
-0xae,
-0x54,
-0x7c,
-0xd3,
-0x57,
-0x84,
-0x7b,
-0x3a,
-0x65,
-0x18,
-0x81,
-0xee,
-0x05,
-0x9b,
-0x44,
-0x4d,
-0xb8,
-0xda,
-0xa2,
-0xa1,
-0xc9,
-0x15,
-0xd3,
-0x73,
-0x03,
-0x0e,
-0x43,
-0xe9,
-0x8e,
-0x15,
-0xf9,
-0xbe,
-0xc6,
-0xc5,
-0x8a,
-0xe5,
-0xc0,
-0x1e,
-0xc2,
-0x37,
-0x9e,
-0x2a,
-0x26,
-0xa5,
-0xa0,
-0xbd,
-0x24,
-0x5f,
-0xb9,
-0xc1,
-0xab,
-0x34,
-0x48,
-0xb9,
-0x5d,
-0x98,
-0xb4,
-0x65,
-0x18,
-0xf3,
-0x63,
-0x19,
-0x44,
-0x1b,
-0x11,
-0x16,
-0xff,
-0xdc,
-0xf1,
-0x79,
-0x08,
-0x86,
-0x0f,
-0x52,
-0x98,
-0x73,
-0xc4,
-0x92,
-0x90,
-0x2b,
-0x47,
-0x09,
-0xd0,
-0x43,
-0x6c,
-0x2f,
-0x20,
-0xeb,
-0xdc,
-0xda,
-0xc5,
-0x08,
-0x7b,
-0x94,
-0x42,
-0x30,
-0x6a,
-0xc7,
-0xda,
-0x8c,
-0xc3,
-0x76,
-0xa7,
-0xa5,
-0xcc,
-0x62,
-0x13,
-0x00,
-0x60,
-0x31,
-0x58,
-0x44,
-0x9b,
-0xf5,
-0x64,
-0x14,
-0xf5,
-0x11,
-0xc5,
-0x54,
-0x52,
-0x83,
-0xd4,
-0x73,
-0x01,
-0x16,
-0x0e,
-0xb3,
-0x7a,
-0x29,
-0x69,
-0x35,
-0x56,
-0xd4,
-0xee,
-0x8a,
-0x17,
-0xa2,
-0x99,
-0x24,
-0x9c,
-0xd7,
-0x8f,
-0xdb,
-0x55,
-0xb5,
-0x3e
+// clang-format off
+
+const uint8_t adns9800_firmware_data[FIRMWARE_LENGTH] PROGMEM = {
+ 0x03, 0xA6, 0x68, 0x1E, 0x7D, 0x10, 0x7E, 0x7E, 0x5F, 0x1C, 0xB8, 0xF2, 0x47, 0x0C, 0x7B, 0x74,
+ 0x4B, 0x14, 0x8B, 0x75, 0x66, 0x51, 0x0B, 0x8C, 0x76, 0x74, 0x4B, 0x14, 0xAA, 0xD6, 0x0F, 0x9C,
+ 0xBA, 0xF6, 0x6E, 0x3F, 0xDD, 0x38, 0xD5, 0x02, 0x80, 0x9B, 0x82, 0x6D, 0x58, 0x13, 0xA4, 0xAB,
+ 0xB5, 0xC9, 0x10, 0xA2, 0xC6, 0x0A, 0x7F, 0x5D, 0x19, 0x91, 0xA0, 0xA3, 0xCE, 0xEB, 0x3E, 0xC9,
+ 0xF1, 0x60, 0x42, 0xE7, 0x4C, 0xFB, 0x74, 0x6A, 0x56, 0x2E, 0xBF, 0xDD, 0x38, 0xD3, 0x05, 0x88,
+ 0x92, 0xA6, 0xCE, 0xFF, 0x5D, 0x38, 0xD1, 0xCF, 0xEF, 0x58, 0xCB, 0x65, 0x48, 0xF0, 0x35, 0x85,
+ 0xA9, 0xB2, 0x8F, 0x5E, 0xF3, 0x80, 0x94, 0x97, 0x7E, 0x75, 0x97, 0x87, 0x73, 0x13, 0xB0, 0x8A,
+ 0x69, 0xD4, 0x0A, 0xDE, 0xC1, 0x79, 0x59, 0x36, 0xDB, 0x9D, 0xD6, 0xB8, 0x15, 0x6F, 0xCE, 0x3C,
+ 0x72, 0x32, 0x45, 0x88, 0xDF, 0x6C, 0xA5, 0x6D, 0xE8, 0x76, 0x96, 0x14, 0x74, 0x20, 0xDC, 0xF4,
+ 0xFA, 0x37, 0x6A, 0x27, 0x32, 0xE3, 0x29, 0xBF, 0xC4, 0xC7, 0x06, 0x9D, 0x58, 0xE7, 0x87, 0x7C,
+ 0x2E, 0x9F, 0x6E, 0x49, 0x07, 0x5D, 0x23, 0x64, 0x54, 0x83, 0x6E, 0xCB, 0xB7, 0x77, 0xF7, 0x2B,
+ 0x6E, 0x0F, 0x2E, 0x66, 0x12, 0x60, 0x55, 0x65, 0xFC, 0x43, 0xB3, 0x58, 0x73, 0x5B, 0xE8, 0x67,
+ 0x04, 0x43, 0x02, 0xDE, 0xB3, 0x89, 0xA0, 0x6D, 0x3A, 0x27, 0x79, 0x64, 0x5B, 0x0C, 0x16, 0x9E,
+ 0x66, 0xB1, 0x8B, 0x87, 0x0C, 0x5D, 0xF2, 0xB6, 0x3D, 0x71, 0xDF, 0x42, 0x03, 0x8A, 0x06, 0x8D,
+ 0xEF, 0x1D, 0xA8, 0x96, 0x5C, 0xED, 0x31, 0x61, 0x5C, 0xA1, 0x34, 0xF6, 0x8C, 0x08, 0x60, 0x33,
+ 0x07, 0x00, 0x3E, 0x79, 0x95, 0x1B, 0x43, 0x7F, 0xFE, 0xB6, 0xA6, 0xD4, 0x9D, 0x76, 0x72, 0xBF,
+ 0xAD, 0xC0, 0x15, 0xE8, 0x37, 0x31, 0xA3, 0x72, 0x63, 0x52, 0x1D, 0x1C, 0x5D, 0x51, 0x1B, 0xE1,
+ 0xA9, 0xED, 0x60, 0x32, 0x3E, 0xA9, 0x50, 0x28, 0x53, 0x06, 0x59, 0xE2, 0xFC, 0xE7, 0x02, 0x64,
+ 0x39, 0x21, 0x56, 0x4A, 0xA5, 0x40, 0x80, 0x81, 0xD5, 0x5A, 0x60, 0x7B, 0x68, 0x84, 0xF1, 0xE0,
+ 0xB1, 0xB6, 0x5B, 0xDF, 0xA8, 0x1D, 0x6D, 0x65, 0x20, 0xC0, 0xA2, 0xB9, 0xD9, 0xBB, 0x00, 0xA6,
+ 0xDB, 0x8B, 0x01, 0x53, 0x91, 0xFE, 0xC4, 0x51, 0x85, 0xB0, 0x96, 0x7F, 0xFD, 0x51, 0xDD, 0x14,
+ 0x03, 0x67, 0x2E, 0x75, 0x1C, 0x76, 0xD3, 0x6E, 0xDD, 0x99, 0x55, 0x76, 0xE5, 0xAB, 0x23, 0xFC,
+ 0x4A, 0xD5, 0xC6, 0xE8, 0x2E, 0xCA, 0x8A, 0xB3, 0xF6, 0x8C, 0x6C, 0xB0, 0xE9, 0xF2, 0xE7, 0x9E,
+ 0x69, 0x41, 0xED, 0xF1, 0x6D, 0xD2, 0x86, 0xD8, 0x7E, 0xCB, 0x5D, 0x47, 0x6C, 0x85, 0x6A, 0x23,
+ 0xED, 0x20, 0x40, 0x93, 0xB4, 0x20, 0xC7, 0xA5, 0xC9, 0xAF, 0x03, 0x15, 0xAC, 0x19, 0xE5, 0x2A,
+ 0x36, 0xDF, 0x6D, 0xC5, 0x8C, 0x80, 0x07, 0xCE, 0x92, 0x0C, 0xD8, 0x06, 0x62, 0x0F, 0xDD, 0x48,
+ 0x46, 0x1A, 0x53, 0xC7, 0x8A, 0x8C, 0x5D, 0x5D, 0xB4, 0xA1, 0x02, 0xD3, 0xA9, 0xB8, 0xF3, 0x94,
+ 0x8F, 0x3F, 0xE5, 0x54, 0xD4, 0x11, 0x65, 0xB2, 0x5E, 0x09, 0x0B, 0x81, 0xE3, 0x75, 0xA7, 0x89,
+ 0x81, 0x39, 0x6C, 0x46, 0xF6, 0x06, 0x9F, 0x27, 0x3B, 0xB6, 0x2D, 0x5F, 0x1D, 0x4B, 0xD4, 0x7B,
+ 0x1D, 0x61, 0x74, 0x89, 0xE4, 0xE3, 0xBD, 0x98, 0x1B, 0xC4, 0x51, 0x3B, 0xA4, 0xFA, 0xE0, 0x92,
+ 0xF7, 0xBE, 0xF2, 0x4D, 0xBB, 0xFF, 0xAD, 0x4F, 0x6D, 0x68, 0xC2, 0x79, 0x40, 0xAA, 0x9B, 0x8F,
+ 0x0C, 0x32, 0x4B, 0x5F, 0x3E, 0xAB, 0x59, 0x98, 0xB3, 0xF5, 0x1D, 0xAC, 0x5E, 0xBC, 0x78, 0xD3,
+ 0x01, 0x6C, 0x64, 0x15, 0x2F, 0xD8, 0x71, 0xA6, 0x2D, 0x45, 0xE1, 0x22, 0x42, 0xE4, 0x4E, 0x04,
+ 0x3C, 0x7D, 0xF4, 0x40, 0x21, 0xB4, 0x67, 0x05, 0xA8, 0xE2, 0xF3, 0x72, 0x87, 0x4C, 0x7D, 0xD9,
+ 0x1B, 0x65, 0x97, 0xF3, 0xC2, 0xE3, 0xE4, 0xC8, 0xD2, 0xDE, 0xF6, 0xEF, 0xDC, 0xBB, 0x44, 0x08,
+ 0x5E, 0xE2, 0x45, 0x27, 0x01, 0xB0, 0xF6, 0x43, 0xE7, 0x3A, 0xF6, 0xDC, 0x9D, 0xED, 0xF3, 0xC5,
+ 0x0C, 0xB8, 0x9C, 0x98, 0x3A, 0xD8, 0x36, 0xEE, 0x96, 0x72, 0x67, 0xE7, 0x81, 0x91, 0xD5, 0x05,
+ 0x0A, 0xE0, 0x82, 0xD5, 0x8F, 0xE8, 0xF9, 0xB0, 0xC9, 0xCF, 0x93, 0xE7, 0x04, 0xC5, 0xBC, 0x2B,
+ 0x43, 0x56, 0x7E, 0xE8, 0x67, 0x7C, 0xE5, 0xFB, 0x49, 0xAD, 0x5E, 0x9F, 0x25, 0x13, 0xDE, 0x6E,
+ 0x6E, 0xE9, 0xF1, 0xEC, 0x87, 0x0B, 0x59, 0x81, 0x76, 0x84, 0x76, 0xB3, 0x24, 0xAF, 0x30, 0xFD,
+ 0x27, 0x8B, 0xAB, 0xD8, 0x00, 0x8B, 0x9B, 0x0C, 0xD2, 0xB2, 0x4E, 0x5E, 0x9D, 0x1D, 0x96, 0x01,
+ 0x00, 0x67, 0xC1, 0x5F, 0x02, 0x20, 0xFD, 0x45, 0x6A, 0x01, 0x60, 0x58, 0x45, 0xCA, 0x47, 0x21,
+ 0x90, 0x5A, 0xC4, 0x43, 0x26, 0x1A, 0xD7, 0xA5, 0x4A, 0xB2, 0x5D, 0x2B, 0x35, 0x49, 0xFB, 0xA5,
+ 0x17, 0x92, 0x21, 0x1E, 0x93, 0x96, 0x67, 0xA2, 0x7E, 0x36, 0x7A, 0xDE, 0x5F, 0xBE, 0x7A, 0x58,
+ 0x9D, 0xF8, 0x78, 0xA3, 0xFA, 0xC8, 0xD5, 0x17, 0xF0, 0x21, 0x97, 0x8C, 0x80, 0xB5, 0x4B, 0x3B,
+ 0xBD, 0xBB, 0x41, 0x21, 0xA8, 0x50, 0x67, 0xF7, 0xE7, 0x19, 0x80, 0x10, 0x8E, 0xCE, 0x04, 0x18,
+ 0x3F, 0x51, 0x6B, 0x77, 0xD8, 0x9E, 0x16, 0xAF, 0xEC, 0xEF, 0x48, 0x16, 0x4D, 0x9E, 0x85, 0x38,
+ 0x18, 0x3E, 0xD4, 0x28, 0x87, 0x60, 0x2A, 0xF6, 0x7F, 0x09, 0x86, 0x6F, 0x9C, 0x3C, 0x3A, 0xFF,
+ 0xAB, 0xD0, 0x61, 0xA2, 0x97, 0x0D, 0x71, 0x94, 0x7E, 0xFD, 0xB9, 0x80, 0x02, 0x89, 0x6A, 0xB3,
+ 0x84, 0x6C, 0x2A, 0x77, 0x62, 0xBE, 0x0B, 0xF4, 0xAF, 0xAC, 0x7B, 0x7C, 0x8E, 0xCA, 0x01, 0xBA,
+ 0x71, 0x78, 0x94, 0xFD, 0xB5, 0x39, 0xA4, 0x4D, 0x2F, 0x78, 0xCF, 0xCA, 0x92, 0x0C, 0x1A, 0x99,
+ 0x48, 0x4C, 0x11, 0x96, 0xB5, 0x4E, 0x41, 0x28, 0xE4, 0xA6, 0xFE, 0x4B, 0x72, 0x91, 0xE7, 0xD4,
+ 0xDD, 0x9F, 0x12, 0xE6, 0x29, 0x38, 0xCE, 0x45, 0xAE, 0x02, 0xB8, 0x24, 0xAE, 0xBD, 0xE9, 0x66,
+ 0x08, 0x62, 0xA2, 0x2C, 0x2B, 0x00, 0xE2, 0x23, 0xD9, 0xC4, 0x48, 0xE4, 0xD3, 0xAC, 0xBB, 0x34,
+ 0xC7, 0xF0, 0xE3, 0x4F, 0xB9, 0x30, 0xEA, 0xA2, 0x12, 0xF1, 0x30, 0x2C, 0x36, 0xDE, 0x48, 0xF2,
+ 0xB0, 0x4C, 0x43, 0x3F, 0x2E, 0x58, 0xE4, 0x20, 0xE3, 0x58, 0xCD, 0x31, 0x22, 0xF0, 0xA2, 0x2A,
+ 0xE6, 0x19, 0x90, 0x55, 0x86, 0xF6, 0x55, 0x79, 0xD1, 0xD7, 0x46, 0x2F, 0xC0, 0xDC, 0x99, 0xE8,
+ 0xF3, 0x6A, 0xDF, 0x7F, 0xEB, 0x24, 0x4A, 0x1E, 0x5A, 0x75, 0xDE, 0x2F, 0x5C, 0x19, 0x61, 0x03,
+ 0x53, 0x54, 0x6A, 0x3B, 0x18, 0x70, 0xB6, 0x4F, 0xF1, 0x9C, 0x0A, 0x59, 0x9D, 0x19, 0x92, 0x65,
+ 0x8C, 0x83, 0x14, 0x2D, 0x44, 0x8A, 0x75, 0xA9, 0xF5, 0x90, 0xD2, 0x66, 0x4E, 0xFA, 0x69, 0x0F,
+ 0x5B, 0x0B, 0x98, 0x65, 0xC8, 0x11, 0x42, 0x59, 0x7F, 0xDD, 0x1B, 0x75, 0x17, 0x31, 0x4C, 0x75,
+ 0x58, 0xEB, 0x58, 0x63, 0x7D, 0xF2, 0xA6, 0xC2, 0x6E, 0xB7, 0x3F, 0x3E, 0x5E, 0x47, 0xAD, 0xB7,
+ 0x04, 0xE8, 0x05, 0xF8, 0xB2, 0xCF, 0x19, 0xF3, 0xD2, 0x85, 0xFE, 0x3E, 0x3E, 0xB1, 0x62, 0x08,
+ 0x2C, 0x10, 0x07, 0x0D, 0x73, 0x90, 0x17, 0xFA, 0x9B, 0x56, 0x02, 0x75, 0xF9, 0x51, 0xE0, 0xE9,
+ 0x1A, 0x7B, 0x9F, 0xB3, 0xF3, 0x98, 0xB8, 0x1C, 0x9C, 0xE1, 0xD5, 0x35, 0xAE, 0xC8, 0x60, 0x48,
+ 0x11, 0x09, 0x94, 0x6B, 0xD0, 0x8B, 0x15, 0xBC, 0x05, 0x68, 0xD3, 0x54, 0x8A, 0x51, 0x39, 0x5C,
+ 0x42, 0x76, 0xCE, 0xD8, 0xAD, 0x89, 0x30, 0xC9, 0x05, 0x1C, 0xCC, 0x94, 0x3F, 0x0F, 0x90, 0x6F,
+ 0x72, 0x2D, 0x85, 0x64, 0x9A, 0xB9, 0x23, 0xF9, 0x0B, 0xC3, 0x7C, 0x39, 0x0F, 0x97, 0x07, 0x97,
+ 0xDA, 0x58, 0x48, 0x33, 0x05, 0x23, 0xB8, 0x82, 0xE8, 0xD3, 0x53, 0x89, 0xAF, 0x33, 0x80, 0x22,
+ 0x84, 0x0C, 0x95, 0x5C, 0x67, 0xB8, 0x77, 0x0C, 0x5C, 0xA2, 0x5F, 0x3D, 0x58, 0x0F, 0x27, 0xF3,
+ 0x2F, 0xAE, 0x48, 0xBD, 0x0B, 0x6F, 0x54, 0xFB, 0x67, 0x4C, 0xEA, 0x32, 0x27, 0xF1, 0xFA, 0xE2,
+ 0xB0, 0xEC, 0x0B, 0x15, 0xB4, 0x70, 0xF6, 0x5C, 0xDD, 0x71, 0x60, 0xC3, 0xC1, 0xA8, 0x32, 0x65,
+ 0xAC, 0x7A, 0x77, 0x41, 0xE5, 0xA9, 0x6B, 0x11, 0x81, 0xFA, 0x34, 0x8D, 0xFB, 0xC1, 0x80, 0x6E,
+ 0xC4, 0x60, 0x30, 0x07, 0xD4, 0x8B, 0x67, 0xBD, 0xAA, 0x8C, 0x9C, 0x64, 0xAC, 0xDB, 0x0B, 0x24,
+ 0x8B, 0x63, 0x6F, 0xE6, 0xBC, 0xE7, 0x33, 0xA4, 0x4A, 0x4C, 0xA7, 0x9F, 0x43, 0x53, 0xD2, 0xBB,
+ 0x8F, 0x43, 0xC7, 0x3D, 0x78, 0x68, 0x3F, 0xA5, 0x3D, 0xCA, 0x69, 0x84, 0xA6, 0x97, 0x2D, 0xC0,
+ 0x7D, 0x31, 0x34, 0x55, 0x1D, 0x07, 0xB1, 0x5F, 0x40, 0x5C, 0x93, 0xB0, 0xBC, 0x7C, 0xB0, 0xBC,
+ 0xE7, 0x12, 0xEE, 0x6B, 0x2B, 0xD3, 0x4D, 0x67, 0x70, 0x3A, 0x9A, 0xF2, 0x3C, 0x7C, 0x81, 0xFA,
+ 0xD7, 0xD9, 0x90, 0x91, 0x81, 0xB8, 0xB1, 0xF3, 0x48, 0x6A, 0x26, 0x4F, 0x0C, 0xCE, 0xB0, 0x9E,
+ 0xFD, 0x4A, 0x3A, 0xAF, 0xAC, 0x5B, 0x3F, 0xBF, 0x44, 0x5A, 0xA3, 0x19, 0x1E, 0x4B, 0xE7, 0x36,
+ 0x6A, 0xD7, 0x20, 0xAE, 0xD7, 0x7D, 0x3B, 0xE7, 0xFF, 0x3A, 0x86, 0x2E, 0xD0, 0x4A, 0x3E, 0xAF,
+ 0x9F, 0x8E, 0x01, 0xBF, 0xF8, 0x4F, 0xC1, 0xE8, 0x6F, 0x74, 0xE1, 0x45, 0xD3, 0xF7, 0x04, 0x6A,
+ 0x4B, 0x9D, 0xEC, 0x33, 0x27, 0x76, 0xD7, 0xC5, 0xE1, 0xB0, 0x3B, 0x0E, 0x23, 0xEC, 0xF0, 0x86,
+ 0xD2, 0x1A, 0xBF, 0x3D, 0x04, 0x62, 0xB3, 0x6C, 0xB2, 0xEB, 0x17, 0x05, 0xA6, 0x0A, 0x8A, 0x7E,
+ 0x83, 0x1C, 0xB6, 0x37, 0x09, 0xC6, 0x0B, 0x70, 0x3C, 0xB5, 0x93, 0x81, 0xD8, 0x93, 0xA0, 0x5F,
+ 0x1E, 0x08, 0xE2, 0xC6, 0xE5, 0xC9, 0x72, 0xF1, 0xF1, 0xC1, 0xED, 0xD5, 0x58, 0x93, 0x83, 0xF8,
+ 0x65, 0x67, 0x2E, 0x0D, 0xA9, 0xF1, 0x64, 0x12, 0xE6, 0x4C, 0xEA, 0x15, 0x3F, 0x8C, 0x1A, 0xB6,
+ 0xBF, 0xF6, 0xB9, 0x52, 0x35, 0x09, 0xB0, 0xE6, 0xF7, 0xCD, 0xF1, 0xA5, 0xAA, 0x81, 0xD1, 0x81,
+ 0x6F, 0xB4, 0xA9, 0x66, 0x1F, 0xFC, 0x48, 0xC0, 0xB6, 0xD1, 0x8B, 0x06, 0x2F, 0xF6, 0xEF, 0x1F,
+ 0x0A, 0xE6, 0xCE, 0x3A, 0x4A, 0x55, 0xBF, 0x6D, 0xF9, 0x4D, 0xD4, 0x08, 0x45, 0x4B, 0xC3, 0x66,
+ 0x19, 0x92, 0x10, 0xE1, 0x17, 0x8E, 0x28, 0x91, 0x16, 0xBF, 0x3C, 0xEE, 0xA3, 0xA6, 0x99, 0x92,
+ 0x10, 0xE1, 0xF6, 0xCC, 0xAC, 0xB8, 0x65, 0x0B, 0x43, 0x66, 0xF8, 0xE3, 0xE5, 0x3F, 0x24, 0x89,
+ 0x47, 0x5D, 0x78, 0x43, 0xD0, 0x61, 0x17, 0xBD, 0x5B, 0x64, 0x54, 0x08, 0x45, 0x59, 0x93, 0xF6,
+ 0x95, 0x8A, 0x41, 0x51, 0x62, 0x4B, 0x51, 0x02, 0x30, 0x73, 0xC7, 0x87, 0xC5, 0x4B, 0xA2, 0x97,
+ 0x0F, 0xE8, 0x46, 0x5F, 0x7E, 0x2A, 0xE1, 0x30, 0x20, 0xB0, 0xFA, 0xE7, 0xCE, 0x61, 0x42, 0x57,
+ 0x6E, 0x21, 0xF3, 0x7A, 0xEC, 0xE3, 0x25, 0xC7, 0x25, 0xF3, 0x67, 0xA7, 0x57, 0x40, 0x00, 0x02,
+ 0xCF, 0x1C, 0x80, 0x77, 0x67, 0xBD, 0x70, 0xA1, 0x19, 0x92, 0x31, 0x75, 0x93, 0x27, 0x27, 0xB6,
+ 0x82, 0xE4, 0xEB, 0x1D, 0x78, 0x48, 0xE7, 0xA5, 0x5E, 0x57, 0xEF, 0x64, 0x28, 0x64, 0x1B, 0xF6,
+ 0x11, 0xB2, 0x03, 0x9D, 0xB9, 0x18, 0x02, 0x27, 0xF7, 0xBE, 0x9D, 0x55, 0xFC, 0x00, 0xD2, 0xC7,
+ 0xAE, 0xAD, 0x0B, 0xC5, 0xE9, 0x42, 0x41, 0x48, 0xD8, 0x32, 0xCF, 0xF6, 0x0F, 0xF5, 0xBC, 0x97,
+ 0xC6, 0x99, 0x47, 0x76, 0xBD, 0x89, 0x06, 0x0F, 0x63, 0x0C, 0x51, 0xD4, 0x5E, 0xEA, 0x48, 0xA8,
+ 0xA2, 0x56, 0x1C, 0x79, 0x84, 0x86, 0x40, 0x88, 0x41, 0x76, 0x55, 0xFC, 0xC2, 0xD7, 0xFD, 0xC9,
+ 0xC7, 0x80, 0x61, 0x35, 0xA7, 0x43, 0x20, 0xF7, 0xEB, 0x6C, 0x66, 0x13, 0xB0, 0xEC, 0x02, 0x75,
+ 0x3E, 0x4B, 0xAF, 0xB9, 0x5D, 0x40, 0xDA, 0xD6, 0x6E, 0x2D, 0x39, 0x54, 0xC2, 0x95, 0x35, 0x54,
+ 0x25, 0x72, 0xE1, 0x78, 0xB8, 0xEB, 0xC1, 0x16, 0x58, 0x0F, 0x9C, 0x9B, 0xB4, 0xEA, 0x37, 0xEC,
+ 0x3B, 0x11, 0xBA, 0xD5, 0x8A, 0xA9, 0xE3, 0x98, 0x00, 0x51, 0x1C, 0x14, 0xE0, 0x40, 0x96, 0xE5,
+ 0xE9, 0xF2, 0x21, 0x22, 0xB1, 0x23, 0x60, 0x78, 0xD3, 0x17, 0xF8, 0x7A, 0xA5, 0xA8, 0xBA, 0x20,
+ 0xD3, 0x15, 0x1E, 0x32, 0xE4, 0x5E, 0x15, 0x48, 0xAE, 0xA9, 0xE5, 0xB8, 0x33, 0xEC, 0xE8, 0xA2,
+ 0x42, 0xAC, 0xBF, 0x10, 0x84, 0x53, 0x87, 0x19, 0xB4, 0x5F, 0x76, 0x4D, 0x01, 0x9D, 0x56, 0x74,
+ 0xD9, 0x5C, 0x97, 0xE7, 0x88, 0xEA, 0x3A, 0xBF, 0xDC, 0x4C, 0x33, 0x8A, 0x16, 0xB9, 0x5B, 0xFA,
+ 0xD8, 0x42, 0xA7, 0xBB, 0x3C, 0x04, 0x27, 0x78, 0x49, 0x81, 0x2A, 0x5A, 0x7D, 0x7C, 0x23, 0xA8,
+ 0xBA, 0xF7, 0x9A, 0x9F, 0xD2, 0x66, 0x3E, 0x38, 0x3C, 0x75, 0xF9, 0xD1, 0x30, 0x26, 0x30, 0x6E,
+ 0x5A, 0x6E, 0xDC, 0x6A, 0x69, 0x32, 0x50, 0x33, 0x47, 0x9E, 0xA4, 0xA8, 0x64, 0x66, 0xF0, 0x8A,
+ 0xE4, 0xFD, 0x27, 0x6F, 0x51, 0x25, 0x8B, 0x43, 0x74, 0xC9, 0x8E, 0xBD, 0x88, 0x31, 0xBE, 0xEC,
+ 0x65, 0xD2, 0xCB, 0x8D, 0x5A, 0x13, 0x48, 0x16, 0x8C, 0x61, 0x0B, 0x11, 0xF6, 0xC6, 0x66, 0xAE,
+ 0xC3, 0xCC, 0x0C, 0xD2, 0xE1, 0x9F, 0x82, 0x41, 0x3F, 0x56, 0xF9, 0x73, 0xEF, 0xDC, 0x30, 0x50,
+ 0xCF, 0xB6, 0x7F, 0xBC, 0xD0, 0xB3, 0x10, 0xAB, 0x24, 0xE4, 0xEC, 0xAD, 0x18, 0x8C, 0x39, 0x2D,
+ 0x30, 0x4C, 0xC5, 0x40, 0x0D, 0xF6, 0xAC, 0xD6, 0x18, 0x5D, 0x96, 0xBF, 0x5F, 0x71, 0x75, 0x96,
+ 0x22, 0x97, 0x0F, 0x02, 0x94, 0x6E, 0xA6, 0xAE, 0x6D, 0x8F, 0x1E, 0xCA, 0x12, 0x9B, 0x2A, 0x1C,
+ 0xCE, 0xA9, 0xEE, 0xFD, 0x12, 0x8E, 0xFC, 0xED, 0x09, 0x33, 0xBA, 0xF4, 0x1A, 0x15, 0xF6, 0x9D,
+ 0x87, 0x16, 0x43, 0x7C, 0x78, 0x57, 0xE1, 0x44, 0xC9, 0xEB, 0x1F, 0x58, 0x4D, 0xC1, 0x49, 0x11,
+ 0x5C, 0xB2, 0x11, 0xA8, 0x55, 0x16, 0xF1, 0xC6, 0x50, 0xE9, 0x87, 0x89, 0xF6, 0xCF, 0xD8, 0x9C,
+ 0x51, 0xA7, 0xBC, 0x5B, 0x31, 0x6D, 0x4D, 0x51, 0xD0, 0x4C, 0xBC, 0x0D, 0x58, 0x2D, 0x7B, 0x88,
+ 0x7A, 0xF9, 0x8E, 0xD6, 0x40, 0x4D, 0xBB, 0xBE, 0xC4, 0xE5, 0x07, 0xFC, 0xD9, 0x7B, 0x6D, 0xA6,
+ 0x42, 0x57, 0x8F, 0x02, 0x94, 0x4F, 0xE4, 0x2A, 0x65, 0xE2, 0x19, 0x5A, 0x50, 0xE1, 0x25, 0x65,
+ 0x4A, 0x60, 0xC2, 0xCD, 0xA8, 0xEC, 0x05, 0x2E, 0x87, 0x7B, 0x95, 0xB7, 0x4F, 0xA0, 0x0B, 0x1B,
+ 0x4A, 0x7F, 0x92, 0xC8, 0x90, 0xEE, 0x89, 0x1E, 0x10, 0xD2, 0x85, 0xE4, 0x9F, 0x63, 0xC8, 0x12,
+ 0xBB, 0x4E, 0xB8, 0xCF, 0x0A, 0xEC, 0x18, 0x4E, 0xE6, 0x7C, 0xB3, 0x33, 0x26, 0xC7, 0x1F, 0xD2,
+ 0x04, 0x23, 0xEA, 0x07, 0x0C, 0x5F, 0x90, 0xBD, 0xA7, 0x6A, 0x0F, 0x4A, 0xD6, 0x10, 0x01, 0x3C,
+ 0x12, 0x29, 0x2E, 0x96, 0xC0, 0x4D, 0xBB, 0xBE, 0xE5, 0xA7, 0x83, 0xD5, 0x6A, 0x3C, 0xE3, 0x5B,
+ 0xB8, 0xF2, 0x5C, 0x6D, 0x1F, 0xA6, 0xF3, 0x12, 0x24, 0xF6, 0xD6, 0x3B, 0x10, 0x14, 0x09, 0x07,
+ 0x82, 0xE8, 0x30, 0x6A, 0x99, 0xDC, 0x95, 0x01, 0x9C, 0xD4, 0x68, 0x3B, 0xCA, 0x98, 0x12, 0xAB,
+ 0x77, 0x25, 0x15, 0x7D, 0x10, 0x32, 0x45, 0x98, 0xCD, 0x7A, 0xDF, 0x71, 0x8A, 0x75, 0xC1, 0x1C,
+ 0xD4, 0x68, 0x25, 0xEB, 0xBB, 0x54, 0x27, 0x6F, 0x2A, 0xF7, 0xB9, 0x98, 0x03, 0x27, 0xDE, 0x24,
+ 0xA8, 0xBB, 0x98, 0xC2, 0x84, 0xFF, 0x9B, 0x51, 0xD8, 0x53, 0x50, 0xDA, 0xF5, 0x88, 0xAA, 0x87,
+ 0x2F, 0xAE, 0xD6, 0xEA, 0x6B, 0xDE, 0xC8, 0xD7, 0xA7, 0x28, 0x65, 0x81, 0xE8, 0xB2, 0x3B, 0x1D,
+ 0x4F, 0x75, 0x8F, 0x9F, 0x7A, 0x74, 0x8E, 0xC1, 0x5F, 0x9A, 0xA8, 0x9D, 0xFA, 0x03, 0xA3, 0x71,
+ 0x9B, 0x37, 0x6D, 0xD5, 0x0B, 0xF5, 0xE1, 0xA1, 0x1B, 0x01, 0x6A, 0xC6, 0x67, 0xAA, 0xEA, 0x2C,
+ 0x9D, 0xA4, 0xD2, 0x6E, 0xFC, 0xDE, 0x2E, 0x7F, 0x94, 0x69, 0xE5, 0x4A, 0xE0, 0x01, 0x48, 0x3C,
+ 0x6B, 0xF7, 0x1E, 0xB6, 0x0B, 0x5F, 0xF9, 0x2E, 0x07, 0xC5, 0xE8, 0xAE, 0x37, 0x1B, 0xBC, 0x3C,
+ 0xD8, 0xD5, 0x0B, 0x91, 0x9E, 0x80, 0x24, 0xF5, 0x06, 0x0C, 0x0E, 0x98, 0x07, 0x96, 0x2D, 0x19,
+ 0xDC, 0x58, 0x93, 0xCC, 0xFB, 0x4E, 0xEB, 0xBD, 0x0F, 0xF5, 0xAF, 0x01, 0xFA, 0xF1, 0x7C, 0x43,
+ 0x8C, 0xB8, 0x56, 0x3E, 0xBE, 0x77, 0x4E, 0x2B, 0xF7, 0xBB, 0xB7, 0x45, 0x47, 0xCD, 0xCC, 0xA6,
+ 0x4C, 0x72, 0x7B, 0x6A, 0x2A, 0x70, 0x13, 0x07, 0xFD, 0xB8, 0x9C, 0x98, 0x3A, 0xD8, 0x23, 0x67,
+ 0x5B, 0x34, 0xD5, 0x14, 0x0C, 0xAB, 0x77, 0x1F, 0xF8, 0x3D, 0x5A, 0x9F, 0x92, 0xB7, 0x2C, 0xAD,
+ 0x31, 0xDE, 0x61, 0x07, 0xB3, 0x6B, 0xF7, 0x38, 0x15, 0x95, 0x46, 0x14, 0x48, 0x53, 0x69, 0x52,
+ 0x66, 0x07, 0x6D, 0x83, 0x71, 0x8A, 0x67, 0x25, 0x20, 0x0F, 0xFE, 0xD7, 0x02, 0xD7, 0x6E, 0x2C,
+ 0xD2, 0x1A, 0x0A, 0x5D, 0xFD, 0x0F, 0x74, 0xE3, 0xA4, 0x36, 0x07, 0x9A, 0xDF, 0xD4, 0x79, 0xBF,
+ 0xEF, 0x59, 0xC0, 0x44, 0x52, 0x87, 0x9A, 0x6E, 0x1D, 0x0E, 0xEE, 0xDE, 0x2E, 0x1A, 0xA9, 0x8F,
+ 0x3A, 0xC9, 0xBA, 0xEC, 0x99, 0x78, 0x2D, 0x55, 0x6B, 0x14, 0xC2, 0x06, 0xD5, 0xFC, 0x93, 0x53,
+ 0x4D, 0x11, 0x8C, 0xF8, 0xFA, 0x79, 0x7C, 0xA6, 0x64, 0xAE, 0x61, 0xB8, 0x7B, 0x94, 0x56, 0xA6,
+ 0x39, 0x78, 0x9A, 0xE5, 0xC7, 0xDF, 0x18, 0x63, 0x23, 0x9C, 0xFA, 0x66, 0xBB, 0xB7, 0x5A, 0x27,
+ 0x4C, 0xD1, 0xA1, 0x83, 0x22, 0xB3, 0x52, 0x49, 0x35, 0xB0, 0x22, 0x83, 0x59, 0x12, 0x00, 0x16,
+ 0x98, 0xDD, 0xAD, 0xC2, 0x94, 0xF9, 0xD3, 0x7B, 0x64, 0x7F, 0x44, 0x3E, 0x3C, 0x8B, 0x9A, 0x83,
+ 0x9C, 0x69, 0x6B, 0xE4, 0xDF, 0x9F, 0xED, 0x54, 0x1F, 0xE5, 0x5D, 0x7A, 0x05, 0x82, 0xB3, 0xDD,
+ 0xEF, 0xFC, 0x53, 0x96, 0xB0, 0x2C, 0x5A, 0xF8, 0xDF, 0x9C, 0x8B, 0x16, 0x4E, 0xDF, 0xDA, 0x4D,
+ 0x09, 0x09, 0x69, 0x50, 0x03, 0x65, 0xD8, 0x73, 0x70, 0xE8, 0x86, 0xBF, 0xBB, 0x35, 0xCE, 0xB2,
+ 0x46, 0xCB, 0x02, 0x00, 0x5B, 0xB4, 0xE2, 0xC6, 0x8F, 0x2F, 0x98, 0xAF, 0x87, 0x4B, 0x48, 0x45,
+ 0xED, 0xCC, 0x1D, 0xE6, 0x58, 0xD6, 0xF2, 0x50, 0x25, 0x9F, 0x52, 0xC7, 0xCB, 0x8A, 0x17, 0x9D,
+ 0x5B, 0xE5, 0xC8, 0xD7, 0x72, 0xB7, 0x52, 0xB2, 0xC4, 0x98, 0xE3, 0x7A, 0x17, 0x3E, 0xC6, 0x60,
+ 0xA7, 0x97, 0xB0, 0xCF, 0x18, 0x81, 0x53, 0x84, 0x4C, 0xD5, 0x17, 0x32, 0x03, 0x13, 0x39, 0x51,
+ 0x09, 0x10, 0xE3, 0x77, 0x49, 0x4F, 0x62, 0x01, 0xBF, 0x8C, 0x9A, 0xE0, 0x41, 0x9E, 0x89, 0x74,
+ 0x36, 0xF9, 0x96, 0x86, 0x2E, 0x96, 0x1C, 0x4A, 0xB7, 0x2B, 0x4A, 0x97, 0xBC, 0x99, 0x40, 0xA3,
+ 0xE0, 0x3D, 0xC8, 0xAD, 0x2F, 0xDF, 0x4F, 0x2C, 0xC4, 0x69, 0x82, 0x9F, 0x9B, 0x81, 0x0C, 0x61,
+ 0x5C, 0xA5, 0x9D, 0x8C, 0x89, 0xC0, 0x2C, 0xB4, 0x4A, 0x33, 0x4E, 0xEB, 0xA2, 0x56, 0x40, 0xC0,
+ 0xC2, 0x46, 0xAF, 0x6A, 0xFC, 0x67, 0xD1, 0x80, 0x5E, 0xC5, 0x6D, 0x84, 0x43, 0x27, 0x3F, 0x55,
+ 0x15, 0x96, 0x6A, 0xA0, 0xA5, 0xDA, 0xB7, 0xFF, 0xB7, 0x75, 0x6E, 0x4C, 0x49, 0x91, 0x9D, 0x22,
+ 0xA3, 0x46, 0xEA, 0xED, 0x9A, 0x00, 0xE2, 0x32, 0xC3, 0xD6, 0xA9, 0x71, 0x20, 0x55, 0xA3, 0x19,
+ 0xED, 0xF8, 0x4F, 0xA7, 0x12, 0x9C, 0x66, 0x87, 0xAF, 0x4E, 0xB7, 0xF0, 0xDB, 0xBF, 0xEF, 0xF0,
+ 0xF6, 0xAF, 0xEA, 0xDA, 0x09, 0xFE, 0xDE, 0x38, 0x5C, 0xA5, 0xA2, 0xDF, 0x99, 0x45, 0xA8, 0xE4,
+ 0xE7, 0x92, 0xAC, 0x67, 0xAA, 0x4F, 0xBF, 0x77, 0x3E, 0xA2, 0x40, 0x49, 0x22, 0x4A, 0x1E, 0x3B,
+ 0xAA, 0x70, 0x7F, 0x95, 0xAF, 0x37, 0x4B, 0xFC, 0x99, 0xE2, 0xE0, 0xBA, 0xD7, 0x34, 0xCE, 0x55,
+ 0x88, 0x5B, 0x84, 0x1B, 0x57, 0xC4, 0x80, 0x03, 0x53, 0xC9, 0x2F, 0x93, 0x04, 0x4D, 0xD5, 0x96,
+ 0xE5, 0x70, 0xA6, 0x6E, 0x63, 0x5D, 0x9D, 0x6C, 0xDB, 0x02, 0x0A, 0xA9, 0xDA, 0x8B, 0x53, 0xDC,
+ 0xD9, 0x9A, 0xC5, 0x94, 0x2C, 0x91, 0x92, 0x2A, 0xDE, 0xBB, 0x8B, 0x13, 0xB9, 0x19, 0x96, 0x64,
+ 0xCC, 0xF2, 0x64, 0x39, 0xB7, 0x75, 0x49, 0xE9, 0x86, 0xC2, 0x86, 0x62, 0xD9, 0x24, 0xD3, 0x81,
+ 0x35, 0x49, 0xFC, 0xA0, 0xA5, 0xA0, 0x93, 0x05, 0x64, 0xB4, 0x1A, 0x57, 0xCE, 0x0C, 0x90, 0x02,
+ 0x27, 0xC5, 0x7A, 0x2B, 0x5D, 0xAE, 0x3E, 0xD5, 0xDD, 0x10, 0x7C, 0x14, 0xEA, 0x3A, 0x08, 0xAC,
+ 0x72, 0x4E, 0x90, 0x3D, 0x3B, 0x7C, 0x86, 0x2E, 0xEB, 0xD4, 0x06, 0x70, 0xE6, 0xC7, 0xFB, 0x5F,
+ 0xBD, 0x18, 0xF4, 0x11, 0xA4, 0x1A, 0x93, 0xC3, 0xBE, 0xD9, 0xFB, 0x26, 0x48, 0x2F, 0x37, 0x3C,
+ 0xD0, 0x03, 0x47, 0x1A, 0xF7, 0x62, 0x19, 0x24, 0x5C, 0xF4, 0xA8, 0x92, 0x20, 0x7A, 0xF2, 0x9E,
+ 0x2A, 0xC5, 0x95, 0xA2, 0xFB, 0xA4, 0xEA, 0x85, 0xD8, 0x56, 0xB7, 0x70, 0xD1, 0x60, 0x30, 0xA5,
+ 0x30, 0x82, 0x70, 0xDC, 0x7A, 0x65, 0x8A, 0x36, 0x3F, 0x5B, 0x0C, 0xAE, 0x54, 0x7C, 0xD3, 0x57,
+ 0x84, 0x7B, 0x3A, 0x65, 0x18, 0x81, 0xEE, 0x05, 0x9B, 0x44, 0x4D, 0xB8, 0xDA, 0xA2, 0xA1, 0xC9,
+ 0x15, 0xD3, 0x73, 0x03, 0x0E, 0x43, 0xE9, 0x8E, 0x15, 0xF9, 0xBE, 0xC6, 0xC5, 0x8A, 0xE5, 0xC0,
+ 0x1E, 0xC2, 0x37, 0x9E, 0x2A, 0x26, 0xA5, 0xA0, 0xBD, 0x24, 0x5F, 0xB9, 0xC1, 0xAB, 0x34, 0x48,
+ 0xB9, 0x5D, 0x98, 0xB4, 0x65, 0x18, 0xF3, 0x63, 0x19, 0x44, 0x1B, 0x11, 0x16, 0xFF, 0xDC, 0xF1,
+ 0x79, 0x08, 0x86, 0x0F, 0x52, 0x98, 0x73, 0xC4, 0x92, 0x90, 0x2B, 0x47, 0x09, 0xD0, 0x43, 0x6C,
+ 0x2F, 0x20, 0xEB, 0xDC, 0xDA, 0xC5, 0x08, 0x7B, 0x94, 0x42, 0x30, 0x6A, 0xC7, 0xDA, 0x8C, 0xC3,
+ 0x76, 0xA7, 0xA5, 0xCC, 0x62, 0x13, 0x00, 0x60, 0x31, 0x58, 0x44, 0x9B, 0xF5, 0x64, 0x14, 0xF5,
+ 0x11, 0xC5, 0x54, 0x52, 0x83, 0xD4, 0x73, 0x01, 0x16, 0x0E, 0xB3, 0x7A, 0x29, 0x69, 0x35, 0x56,
+ 0xD4, 0xEE, 0x8A, 0x17, 0xA2, 0x99, 0x24, 0x9C, 0xD7, 0x8F, 0xDB, 0x55, 0xB5, 0x3E
};
diff --git a/drivers/sensors/analog_joystick.c b/drivers/sensors/analog_joystick.c
new file mode 100644
index 0000000000..0f4d1d7a4c
--- /dev/null
+++ b/drivers/sensors/analog_joystick.c
@@ -0,0 +1,94 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "analog_joystick.h"
+#include "analog.h"
+#include "gpio.h"
+#include "wait.h"
+
+// Set Parameters
+uint16_t minAxisValue = ANALOG_JOYSTICK_AXIS_MIN;
+uint16_t maxAxisValue = ANALOG_JOYSTICK_AXIS_MAX;
+
+uint8_t maxCursorSpeed = ANALOG_JOYSTICK_SPEED_MAX;
+uint8_t speedRegulator = ANALOG_JOYSTICK_SPEED_REGULATOR; // Lower Values Create Faster Movement
+
+int16_t xOrigin, yOrigin;
+
+uint16_t lastCursor = 0;
+
+int16_t axisCoordinate(uint8_t pin, uint16_t origin) {
+ int8_t direction;
+ int16_t distanceFromOrigin;
+ int16_t range;
+
+ int16_t position = analogReadPin(pin);
+
+ if (origin == position) {
+ return 0;
+ } else if (origin > position) {
+ distanceFromOrigin = origin - position;
+ range = origin - minAxisValue;
+ direction = -1;
+ } else {
+ distanceFromOrigin = position - origin;
+ range = maxAxisValue - origin;
+ direction = 1;
+ }
+
+ float percent = (float)distanceFromOrigin / range;
+ int16_t coordinate = (int16_t)(percent * 100);
+ if (coordinate < 0) {
+ return 0;
+ } else if (coordinate > 100) {
+ return 100 * direction;
+ } else {
+ return coordinate * direction;
+ }
+}
+
+int8_t axisToMouseComponent(uint8_t pin, int16_t origin, uint8_t maxSpeed) {
+ int16_t coordinate = axisCoordinate(pin, origin);
+ if (coordinate != 0) {
+ float percent = (float)coordinate / 100;
+ return percent * maxCursorSpeed * (abs(coordinate) / speedRegulator);
+ } else {
+ return 0;
+ }
+}
+
+report_analog_joystick_t analog_joystick_read(void) {
+ report_analog_joystick_t report = {0};
+
+ if (timer_elapsed(lastCursor) > ANALOG_JOYSTICK_READ_INTERVAL) {
+ lastCursor = timer_read();
+ report.x = axisToMouseComponent(ANALOG_JOYSTICK_X_AXIS_PIN, xOrigin, maxCursorSpeed);
+ report.y = axisToMouseComponent(ANALOG_JOYSTICK_Y_AXIS_PIN, yOrigin, maxCursorSpeed);
+ }
+#ifdef ANALOG_JOYSTICK_CLICK_PIN
+ report.button = !readPin(ANALOG_JOYSTICK_CLICK_PIN);
+#endif
+ return report;
+}
+
+void analog_joystick_init(void) {
+#ifdef ANALOG_JOYSTICK_CLICK_PIN
+ setPinInputHigh(ANALOG_JOYSTICK_CLICK_PIN);
+#endif
+ // Account for drift
+ xOrigin = analogReadPin(ANALOG_JOYSTICK_X_AXIS_PIN);
+ yOrigin = analogReadPin(ANALOG_JOYSTICK_Y_AXIS_PIN);
+}
diff --git a/drivers/sensors/analog_joystick.h b/drivers/sensors/analog_joystick.h
new file mode 100644
index 0000000000..6892a08817
--- /dev/null
+++ b/drivers/sensors/analog_joystick.h
@@ -0,0 +1,51 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifndef ANALOG_JOYSTICK_X_AXIS_PIN
+# error No pin specified for X Axis
+#endif
+#ifndef ANALOG_JOYSTICK_Y_AXIS_PIN
+# error No pin specified for Y Axis
+#endif
+
+#ifndef ANALOG_JOYSTICK_AXIS_MIN
+# define ANALOG_JOYSTICK_AXIS_MIN 0
+#endif
+#ifndef ANALOG_JOYSTICK_AXIS_MAX
+# define ANALOG_JOYSTICK_AXIS_MAX 1023
+#endif
+#ifndef ANALOG_JOYSTICK_SPEED_REGULATOR
+# define ANALOG_JOYSTICK_SPEED_REGULATOR 20
+#endif
+#ifndef ANALOG_JOYSTICK_READ_INTERVAL
+# define ANALOG_JOYSTICK_READ_INTERVAL 10
+#endif
+#ifndef ANALOG_JOYSTICK_SPEED_MAX
+# define ANALOG_JOYSTICK_SPEED_MAX 2
+#endif
+
+typedef struct {
+ int8_t x;
+ int8_t y;
+ bool button;
+} report_analog_joystick_t;
+report_analog_joystick_t analog_joystick_read(void);
+void analog_joystick_init(void);
diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c
new file mode 100644
index 0000000000..b807c4f076
--- /dev/null
+++ b/drivers/sensors/cirque_pinnacle.c
@@ -0,0 +1,232 @@
+// Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license
+#include "cirque_pinnacle.h"
+#include "print.h"
+#include "debug.h"
+#include "wait.h"
+
+// Registers for RAP
+// clang-format off
+#define FIRMWARE_ID 0x00
+#define FIRMWARE_VERSION_C 0x01
+#define STATUS_1 0x02
+#define SYSCONFIG_1 0x03
+#define FEEDCONFIG_1 0x04
+#define FEEDCONFIG_2 0x05
+#define CALIBRATION_CONFIG_1 0x07
+#define PS2_AU_CONTROL 0x08
+#define SAMPLE_RATE 0x09
+#define Z_IDLE_COUNT 0x0A
+#define Z_SCALER 0x0B
+#define SLEEP_INTERVAL 0x0C
+#define SLEEP_TIMER 0x0D
+#define PACKET_BYTE_0 0x12
+#define PACKET_BYTE_1 0x13
+#define PACKET_BYTE_2 0x14
+#define PACKET_BYTE_3 0x15
+#define PACKET_BYTE_4 0x16
+#define PACKET_BYTE_5 0x17
+
+#define ERA_VALUE 0x1B
+#define ERA_HIGH_BYTE 0x1C
+#define ERA_LOW_BYTE 0x1D
+#define ERA_CONTROL 0x1E
+
+// ADC-attenuation settings (held in BIT_7 and BIT_6)
+// 1X = most sensitive, 4X = least sensitive
+#define ADC_ATTENUATE_1X 0x00
+#define ADC_ATTENUATE_2X 0x40
+#define ADC_ATTENUATE_3X 0x80
+#define ADC_ATTENUATE_4X 0xC0
+
+// Register config values for this demo
+#define SYSCONFIG_1_VALUE 0x00
+#define FEEDCONFIG_1_VALUE 0x03 // 0x03 for absolute mode 0x01 for relative mode
+#define FEEDCONFIG_2_VALUE 0x1C // 0x1F for normal functionality 0x1E for intellimouse disabled
+#define Z_IDLE_COUNT_VALUE 0x05
+// clang-format on
+
+bool touchpad_init;
+uint16_t scale_data = 1024;
+
+void cirque_pinnacle_clear_flags(void);
+void cirque_pinnacle_enable_feed(bool feedEnable);
+void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count);
+void RAP_Write(uint8_t address, uint8_t data);
+
+#ifdef CONSOLE_ENABLE
+void print_byte(uint8_t byte) { xprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
+#endif
+
+/* Logical Scaling Functions */
+// Clips raw coordinates to "reachable" window of sensor
+// NOTE: values outside this window can only appear as a result of noise
+void ClipCoordinates(pinnacle_data_t* coordinates) {
+ if (coordinates->xValue < CIRQUE_PINNACLE_X_LOWER) {
+ coordinates->xValue = CIRQUE_PINNACLE_X_LOWER;
+ } else if (coordinates->xValue > CIRQUE_PINNACLE_X_UPPER) {
+ coordinates->xValue = CIRQUE_PINNACLE_X_UPPER;
+ }
+ if (coordinates->yValue < CIRQUE_PINNACLE_Y_LOWER) {
+ coordinates->yValue = CIRQUE_PINNACLE_Y_LOWER;
+ } else if (coordinates->yValue > CIRQUE_PINNACLE_Y_UPPER) {
+ coordinates->yValue = CIRQUE_PINNACLE_Y_UPPER;
+ }
+}
+
+uint16_t cirque_pinnacle_get_scale(void) { return scale_data; }
+void cirque_pinnacle_set_scale(uint16_t scale) { scale_data = scale; }
+
+// Scales data to desired X & Y resolution
+void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution) {
+ uint32_t xTemp = 0;
+ uint32_t yTemp = 0;
+
+ ClipCoordinates(coordinates);
+
+ xTemp = coordinates->xValue;
+ yTemp = coordinates->yValue;
+
+ // translate coordinates to (0, 0) reference by subtracting edge-offset
+ xTemp -= CIRQUE_PINNACLE_X_LOWER;
+ yTemp -= CIRQUE_PINNACLE_Y_LOWER;
+
+ // scale coordinates to (xResolution, yResolution) range
+ coordinates->xValue = (uint16_t)(xTemp * xResolution / CIRQUE_PINNACLE_X_RANGE);
+ coordinates->yValue = (uint16_t)(yTemp * yResolution / CIRQUE_PINNACLE_Y_RANGE);
+}
+
+// Clears Status1 register flags (SW_CC and SW_DR)
+void cirque_pinnacle_clear_flags() {
+ RAP_Write(STATUS_1, 0x00);
+ wait_us(50);
+}
+
+// Enables/Disables the feed
+void cirque_pinnacle_enable_feed(bool feedEnable) {
+ uint8_t temp;
+
+ RAP_ReadBytes(FEEDCONFIG_1, &temp, 1); // Store contents of FeedConfig1 register
+
+ if (feedEnable) {
+ temp |= 0x01; // Set Feed Enable bit
+ RAP_Write(0x04, temp);
+ } else {
+ temp &= ~0x01; // Clear Feed Enable bit
+ RAP_Write(0x04, temp);
+ }
+}
+
+/* ERA (Extended Register Access) Functions */
+// Reads <count> bytes from an extended register at <address> (16-bit address),
+// stores values in <*data>
+void ERA_ReadBytes(uint16_t address, uint8_t* data, uint16_t count) {
+ uint8_t ERAControlValue = 0xFF;
+
+ cirque_pinnacle_enable_feed(false); // Disable feed
+
+ RAP_Write(ERA_HIGH_BYTE, (uint8_t)(address >> 8)); // Send upper byte of ERA address
+ RAP_Write(ERA_LOW_BYTE, (uint8_t)(address & 0x00FF)); // Send lower byte of ERA address
+
+ for (uint16_t i = 0; i < count; i++) {
+ RAP_Write(ERA_CONTROL, 0x05); // Signal ERA-read (auto-increment) to Pinnacle
+
+ // Wait for status register 0x1E to clear
+ do {
+ RAP_ReadBytes(ERA_CONTROL, &ERAControlValue, 1);
+ } while (ERAControlValue != 0x00);
+
+ RAP_ReadBytes(ERA_VALUE, data + i, 1);
+
+ cirque_pinnacle_clear_flags();
+ }
+}
+
+// Writes a byte, <data>, to an extended register at <address> (16-bit address)
+void ERA_WriteByte(uint16_t address, uint8_t data) {
+ uint8_t ERAControlValue = 0xFF;
+
+ cirque_pinnacle_enable_feed(false); // Disable feed
+
+ RAP_Write(ERA_VALUE, data); // Send data byte to be written
+
+ RAP_Write(ERA_HIGH_BYTE, (uint8_t)(address >> 8)); // Upper byte of ERA address
+ RAP_Write(ERA_LOW_BYTE, (uint8_t)(address & 0x00FF)); // Lower byte of ERA address
+
+ RAP_Write(ERA_CONTROL, 0x02); // Signal an ERA-write to Pinnacle
+
+ // Wait for status register 0x1E to clear
+ do {
+ RAP_ReadBytes(ERA_CONTROL, &ERAControlValue, 1);
+ } while (ERAControlValue != 0x00);
+
+ cirque_pinnacle_clear_flags();
+}
+
+void cirque_pinnacle_set_adc_attenuation(uint8_t adcGain) {
+ uint8_t temp = 0x00;
+
+ ERA_ReadBytes(0x0187, &temp, 1);
+ temp &= 0x3F; // clear top two bits
+ temp |= adcGain;
+ ERA_WriteByte(0x0187, temp);
+ ERA_ReadBytes(0x0187, &temp, 1);
+}
+
+// Changes thresholds to improve detection of fingers
+void cirque_pinnacle_tune_edge_sensitivity(void) {
+ uint8_t temp = 0x00;
+
+ ERA_ReadBytes(0x0149, &temp, 1);
+ ERA_WriteByte(0x0149, 0x04);
+ ERA_ReadBytes(0x0149, &temp, 1);
+
+ ERA_ReadBytes(0x0168, &temp, 1);
+ ERA_WriteByte(0x0168, 0x03);
+ ERA_ReadBytes(0x0168, &temp, 1);
+}
+
+/* Pinnacle-based TM040040 Functions */
+void cirque_pinnacle_init(void) {
+#if defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
+ spi_init();
+#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c)
+ i2c_init();
+#endif
+
+ touchpad_init = true;
+ // Host clears SW_CC flag
+ cirque_pinnacle_clear_flags();
+
+ // Host configures bits of registers 0x03 and 0x05
+ RAP_Write(SYSCONFIG_1, SYSCONFIG_1_VALUE);
+ RAP_Write(FEEDCONFIG_2, FEEDCONFIG_2_VALUE);
+
+ // Host enables preferred output mode (absolute)
+ RAP_Write(FEEDCONFIG_1, FEEDCONFIG_1_VALUE);
+
+ // Host sets z-idle packet count to 5 (default is 30)
+ RAP_Write(Z_IDLE_COUNT, Z_IDLE_COUNT_VALUE);
+
+ cirque_pinnacle_set_adc_attenuation(0xFF);
+ cirque_pinnacle_tune_edge_sensitivity();
+ cirque_pinnacle_enable_feed(true);
+}
+
+// Reads XYZ data from Pinnacle registers 0x14 through 0x17
+// Stores result in pinnacle_data_t struct with xValue, yValue, and zValue members
+pinnacle_data_t cirque_pinnacle_read_data(void) {
+ uint8_t data[6] = {0};
+ pinnacle_data_t result = {0};
+ RAP_ReadBytes(PACKET_BYTE_0, data, 6);
+
+ cirque_pinnacle_clear_flags();
+
+ result.buttonFlags = data[0] & 0x3F;
+ result.xValue = data[2] | ((data[4] & 0x0F) << 8);
+ result.yValue = data[3] | ((data[4] & 0xF0) << 4);
+ result.zValue = data[5] & 0x3F;
+
+ result.touchDown = (result.xValue != 0 || result.yValue != 0);
+
+ return result;
+}
diff --git a/drivers/sensors/cirque_pinnacle.h b/drivers/sensors/cirque_pinnacle.h
new file mode 100644
index 0000000000..db891122a6
--- /dev/null
+++ b/drivers/sensors/cirque_pinnacle.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+// Convenient way to store and access measurements
+typedef struct {
+ uint16_t xValue;
+ uint16_t yValue;
+ uint16_t zValue;
+ uint8_t buttonFlags;
+ bool touchDown;
+} pinnacle_data_t;
+
+void cirque_pinnacle_init(void);
+pinnacle_data_t cirque_pinnacle_read_data(void);
+void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution);
+uint16_t cirque_pinnacle_get_scale(void);
+void cirque_pinnacle_set_scale(uint16_t scale);
+
+#ifndef CIRQUE_PINNACLE_TIMEOUT
+# define CIRQUE_PINNACLE_TIMEOUT 20
+#endif
+
+// Coordinate scaling values
+#ifndef CIRQUE_PINNACLE_X_LOWER
+# define CIRQUE_PINNACLE_X_LOWER 127 // min "reachable" X value
+#endif
+#ifndef CIRQUE_PINNACLE_X_UPPER
+# define CIRQUE_PINNACLE_X_UPPER 1919 // max "reachable" X value
+#endif
+#ifndef CIRQUE_PINNACLE_Y_LOWER
+# define CIRQUE_PINNACLE_Y_LOWER 63 // min "reachable" Y value
+#endif
+#ifndef CIRQUE_PINNACLE_Y_UPPER
+# define CIRQUE_PINNACLE_Y_UPPER 1471 // max "reachable" Y value
+#endif
+#ifndef CIRQUE_PINNACLE_X_RANGE
+# define CIRQUE_PINNACLE_X_RANGE (CIRQUE_PINNACLE_X_UPPER - CIRQUE_PINNACLE_X_LOWER)
+#endif
+#ifndef CIRQUE_PINNACLE_Y_RANGE
+# define CIRQUE_PINNACLE_Y_RANGE (CIRQUE_PINNACLE_Y_UPPER - CIRQUE_PINNACLE_Y_LOWER)
+#endif
+
+#if defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c)
+# include "i2c_master.h"
+// Cirque's 7-bit I2C Slave Address
+# ifndef CIRQUE_PINNACLE_ADDR
+# define CIRQUE_PINNACLE_ADDR 0x2A
+# endif
+#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
+# include "spi_master.h"
+# ifndef CIRQUE_PINNACLE_CLOCK_SPEED
+# define CIRQUE_PINNACLE_CLOCK_SPEED 10000000
+# endif
+# ifndef CIRQUE_PINNACLE_SPI_LSBFIRST
+# define CIRQUE_PINNACLE_SPI_LSBFIRST false
+# endif
+# ifndef CIRQUE_PINNACLE_SPI_MODE
+# define CIRQUE_PINNACLE_SPI_MODE 1
+# endif
+# ifndef CIRQUE_PINNACLE_SPI_DIVISOR
+# ifdef __AVR__
+# define CIRQUE_PINNACLE_SPI_DIVISOR (F_CPU / CIRQUE_PINNACLE_CLOCK_SPEED)
+# else
+# define CIRQUE_PINNACLE_SPI_DIVISOR 64
+# endif
+# ifndef CIRQUE_PINNACLE_SPI_CS_PIN
+# error "No Chip Select pin has been defined -- missing CIRQUE_PINNACLE_SPI_CS_PIN define"
+# endif
+# endif
+#endif
diff --git a/drivers/sensors/cirque_pinnacle_i2c.c b/drivers/sensors/cirque_pinnacle_i2c.c
new file mode 100644
index 0000000000..81dd982b0c
--- /dev/null
+++ b/drivers/sensors/cirque_pinnacle_i2c.c
@@ -0,0 +1,43 @@
+// Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license
+#include "cirque_pinnacle.h"
+#include "i2c_master.h"
+#include "print.h"
+#include "debug.h"
+#include "stdio.h"
+
+// Masks for Cirque Register Access Protocol (RAP)
+#define WRITE_MASK 0x80
+#define READ_MASK 0xA0
+
+extern bool touchpad_init;
+
+/* RAP Functions */
+// Reads <count> Pinnacle registers starting at <address>
+void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
+ uint8_t cmdByte = READ_MASK | address; // Form the READ command byte
+ if (touchpad_init) {
+ i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, NULL, 0, CIRQUE_PINNACLE_TIMEOUT);
+ if (i2c_readReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, data, count, CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) {
+#ifdef CONSOLE_ENABLE
+ dprintf("error right touchpad\n");
+#endif
+ touchpad_init = false;
+ }
+ i2c_stop();
+ }
+}
+
+// Writes single-byte <data> to <address>
+void RAP_Write(uint8_t address, uint8_t data) {
+ uint8_t cmdByte = WRITE_MASK | address; // Form the WRITE command byte
+
+ if (touchpad_init) {
+ if (i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, &data, sizeof(data), CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) {
+#ifdef CONSOLE_ENABLE
+ dprintf("error right touchpad\n");
+#endif
+ touchpad_init = false;
+ }
+ i2c_stop();
+ }
+}
diff --git a/drivers/sensors/cirque_pinnacle_spi.c b/drivers/sensors/cirque_pinnacle_spi.c
new file mode 100644
index 0000000000..f3eee88758
--- /dev/null
+++ b/drivers/sensors/cirque_pinnacle_spi.c
@@ -0,0 +1,52 @@
+// Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license
+#include "cirque_pinnacle.h"
+#include "spi_master.h"
+#include "print.h"
+#include "debug.h"
+
+// Masks for Cirque Register Access Protocol (RAP)
+#define WRITE_MASK 0x80
+#define READ_MASK 0xA0
+
+extern bool touchpad_init;
+
+/* RAP Functions */
+// Reads <count> Pinnacle registers starting at <address>
+void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
+ uint8_t cmdByte = READ_MASK | address; // Form the READ command byte
+ if (touchpad_init) {
+ if (spi_start(CIRQUE_PINNACLE_SPI_CS_PIN, CIRQUE_TRACKPAD_SPI_LSBFIRST, CIRQUE_PINNACLE_SPI_MODE, CIRQUE_PINNACLE_SPI_DIVISOR)) {
+ spi_write(cmdByte);
+ spi_read(); // filler
+ spi_read(); // filler
+ for (uint8_t i = 0; i < count; i++) {
+ data[i] = spi_read(); // each sepsequent read gets another register's contents
+ }
+ } else {
+#ifdef CONSOLE_ENABLE
+ dprintf("error right touchpad\n");
+#endif
+ touchpad_init = false;
+ j
+ }
+ spi_stop();
+ }
+}
+
+// Writes single-byte <data> to <address>
+void RAP_Write(uint8_t address, uint8_t data) {
+ uint8_t cmdByte = WRITE_MASK | address; // Form the WRITE command byte
+
+ if (touchpad_init) {
+ if (spi_start(CIRQUE_PINNACLE_SPI_CS_PIN, CIRQUE_TRACKPAD_SPI_LSBFIRST, CIRQUE_PINNACLE_SPI_MODE, CIRQUE_PINNACLE_SPI_DIVISOR)) {
+ spi_write(cmdByte);
+ spi_write(data);
+ } else {
+#ifdef CONSOLE_ENABLE
+ dprintf("error right touchpad\n");
+#endif
+ touchpad_init = false;
+ }
+ spi_stop();
+ }
+}
diff --git a/drivers/sensors/pimoroni_trackball.c b/drivers/sensors/pimoroni_trackball.c
index 48098ff0cc..7d390056ea 100644
--- a/drivers/sensors/pimoroni_trackball.c
+++ b/drivers/sensors/pimoroni_trackball.c
@@ -17,73 +17,55 @@
#include "pimoroni_trackball.h"
#include "i2c_master.h"
#include "print.h"
-
-#ifndef PIMORONI_TRACKBALL_ADDRESS
-# define PIMORONI_TRACKBALL_ADDRESS 0x0A
-#endif
-#ifndef PIMORONI_TRACKBALL_INTERVAL_MS
-# define PIMORONI_TRACKBALL_INTERVAL_MS 8
-#endif
-#ifndef PIMORONI_TRACKBALL_MOUSE_SCALE
-# define PIMORONI_TRACKBALL_MOUSE_SCALE 5
-#endif
-#ifndef PIMORONI_TRACKBALL_SCROLL_SCALE
-# define PIMORONI_TRACKBALL_SCROLL_SCALE 1
-#endif
-#ifndef PIMORONI_TRACKBALL_DEBOUNCE_CYCLES
-# define PIMORONI_TRACKBALL_DEBOUNCE_CYCLES 20
-#endif
-#ifndef PIMORONI_TRACKBALL_ERROR_COUNT
-# define PIMORONI_TRACKBALL_ERROR_COUNT 10
-#endif
-
-#define TRACKBALL_TIMEOUT 100
-#define TRACKBALL_REG_LED_RED 0x00
-#define TRACKBALL_REG_LED_GRN 0x01
-#define TRACKBALL_REG_LED_BLU 0x02
-#define TRACKBALL_REG_LED_WHT 0x03
-#define TRACKBALL_REG_LEFT 0x04
-#define TRACKBALL_REG_RIGHT 0x05
-#define TRACKBALL_REG_UP 0x06
-#define TRACKBALL_REG_DOWN 0x07
-
-static pimoroni_data current_pimoroni_data;
-static report_mouse_t mouse_report;
-static bool scrolling = false;
-static int16_t x_offset = 0;
-static int16_t y_offset = 0;
-static int16_t h_offset = 0;
-static int16_t v_offset = 0;
-static uint16_t precision = 128;
-static uint8_t error_count = 0;
-
-float trackball_get_precision(void) { return ((float)precision / 128); }
-void trackball_set_precision(float floatprecision) { precision = (floatprecision * 128); }
-bool trackball_is_scrolling(void) { return scrolling; }
-void trackball_set_scrolling(bool scroll) { scrolling = scroll; }
-
-void trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
+#include "debug.h"
+#include "timer.h"
+
+// clang-format off
+#define PIMORONI_TRACKBALL_REG_LED_RED 0x00
+#define PIMORONI_TRACKBALL_REG_LED_GRN 0x01
+#define PIMORONI_TRACKBALL_REG_LED_BLU 0x02
+#define PIMORONI_TRACKBALL_REG_LED_WHT 0x03
+#define PIMORONI_TRACKBALL_REG_LEFT 0x04
+#define PIMORONI_TRACKBALL_REG_RIGHT 0x05
+#define PIMORONI_TRACKBALL_REG_UP 0x06
+#define PIMORONI_TRACKBALL_REG_DOWN 0x07
+// clang-format on
+
+static uint16_t precision = 128;
+
+float pimoroni_trackball_get_precision(void) { return ((float)precision / 128); }
+void pimoroni_trackball_set_precision(float floatprecision) { precision = (floatprecision * 128); }
+
+void pimoroni_trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
uint8_t data[4] = {r, g, b, w};
- __attribute__((unused)) i2c_status_t status = i2c_writeReg(PIMORONI_TRACKBALL_ADDRESS << 1, TRACKBALL_REG_LED_RED, data, sizeof(data), TRACKBALL_TIMEOUT);
-#ifdef TRACKBALL_DEBUG
- dprintf("Trackball RGBW i2c_status_t: %d\n", status);
+ __attribute__((unused)) i2c_status_t status = i2c_writeReg(PIMORONI_TRACKBALL_ADDRESS << 1, PIMORONI_TRACKBALL_REG_LED_RED, data, sizeof(data), PIMORONI_TRACKBALL_TIMEOUT);
+
+#ifdef CONSOLE_ENABLE
+ if (debug_mouse) dprintf("Trackball RGBW i2c_status_t: %d\n", status);
#endif
}
-i2c_status_t read_pimoroni_trackball(pimoroni_data* data) {
- i2c_status_t status = i2c_readReg(PIMORONI_TRACKBALL_ADDRESS << 1, TRACKBALL_REG_LEFT, (uint8_t*)data, sizeof(*data), TRACKBALL_TIMEOUT);
-#ifdef TRACKBALL_DEBUG
- dprintf("Trackball READ i2c_status_t: %d\nLeft: %d\nRight: %d\nUp: %d\nDown: %d\nSwtich: %d\n", status, data->left, data->right, data->up, data->down, data->click);
+i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data) {
+ i2c_status_t status = i2c_readReg(PIMORONI_TRACKBALL_ADDRESS << 1, PIMORONI_TRACKBALL_REG_LEFT, (uint8_t*)data, sizeof(*data), PIMORONI_TRACKBALL_TIMEOUT);
+#ifdef CONSOLE_ENABLE
+ if (debug_mouse) {
+ static uint16_t d_timer;
+ if (timer_elapsed(d_timer) > PIMORONI_TRACKBALL_DEBUG_INTERVAL) {
+ dprintf("Trackball READ i2c_status_t: %d L: %d R: %d Up: %d D: %d SW: %d\n", status, data->left, data->right, data->up, data->down, data->click);
+ d_timer = timer_read();
+ }
+ }
#endif
+
return status;
}
-__attribute__((weak)) void pointing_device_init(void) {
+__attribute__((weak)) void pimironi_trackball_device_init(void) {
i2c_init();
- trackball_set_rgbw(0x00, 0x00, 0x00, 0x00);
+ pimoroni_trackball_set_rgbw(0x00, 0x00, 0x00, 0x00);
}
-int16_t trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale) {
+int16_t pimoroni_trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale) {
uint8_t offset = 0;
bool isnegative = false;
if (negative_dir > positive_dir) {
@@ -96,7 +78,7 @@ int16_t trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_
return isnegative ? -(int16_t)(magnitude) : (int16_t)(magnitude);
}
-void trackball_adapt_values(int8_t* mouse, int16_t* offset) {
+void pimoroni_trackball_adapt_values(int8_t* mouse, int16_t* offset) {
if (*offset > 127) {
*mouse = 127;
*offset -= 127;
@@ -108,94 +90,3 @@ void trackball_adapt_values(int8_t* mouse, int16_t* offset) {
*offset = 0;
}
}
-
-__attribute__((weak)) void trackball_click(bool pressed, report_mouse_t* mouse) {
-#ifdef PIMORONI_TRACKBALL_CLICK
- if (pressed) {
- mouse->buttons |= MOUSE_BTN1;
- } else {
- mouse->buttons &= ~MOUSE_BTN1;
- }
-#endif
-}
-
-__attribute__((weak)) bool pointing_device_task_user(pimoroni_data* trackball_data) { return true; };
-
-__attribute__((weak)) void pointing_device_task() {
- static fast_timer_t throttle = 0;
- static uint16_t debounce = 0;
-
- if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) {
- i2c_status_t status = read_pimoroni_trackball(&current_pimoroni_data);
-
- if (status == I2C_STATUS_SUCCESS) {
- error_count = 0;
-
- if (pointing_device_task_user(&current_pimoroni_data)) {
- mouse_report = pointing_device_get_report();
-
- if (!(current_pimoroni_data.click & 128)) {
- trackball_click(false, &mouse_report);
- if (!debounce) {
- if (scrolling) {
-#ifdef PIMORONI_TRACKBALL_INVERT_X
- h_offset += trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_SCROLL_SCALE);
-#else
- h_offset -= trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_SCROLL_SCALE);
-#endif
-#ifdef PIMORONI_TRACKBALL_INVERT_Y
- v_offset += trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_SCROLL_SCALE);
-#else
- v_offset -= trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_SCROLL_SCALE);
-#endif
- } else {
-#ifdef PIMORONI_TRACKBALL_INVERT_X
- x_offset -= trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_MOUSE_SCALE);
-#else
- x_offset += trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_MOUSE_SCALE);
-#endif
-#ifdef PIMORONI_TRACKBALL_INVERT_Y
- y_offset -= trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_MOUSE_SCALE);
-#else
- y_offset += trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_MOUSE_SCALE);
-#endif
- }
- if (scrolling) {
-#ifndef PIMORONI_TRACKBALL_ROTATE
- trackball_adapt_values(&mouse_report.h, &h_offset);
- trackball_adapt_values(&mouse_report.v, &v_offset);
-#else
- trackball_adapt_values(&mouse_report.h, &v_offset);
- trackball_adapt_values(&mouse_report.v, &h_offset);
-#endif
- mouse_report.x = 0;
- mouse_report.y = 0;
- } else {
-#ifndef PIMORONI_TRACKBALL_ROTATE
- trackball_adapt_values(&mouse_report.x, &x_offset);
- trackball_adapt_values(&mouse_report.y, &y_offset);
-#else
- trackball_adapt_values(&mouse_report.x, &y_offset);
- trackball_adapt_values(&mouse_report.y, &x_offset);
-#endif
- mouse_report.h = 0;
- mouse_report.v = 0;
- }
- } else {
- debounce--;
- }
- } else {
- trackball_click(true, &mouse_report);
- debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES;
- }
- }
- } else {
- error_count++;
- }
-
- pointing_device_set_report(mouse_report);
- pointing_device_send();
-
- throttle = timer_read_fast();
- }
-}
diff --git a/drivers/sensors/pimoroni_trackball.h b/drivers/sensors/pimoroni_trackball.h
index 6b2a41425d..59ee8724ba 100644
--- a/drivers/sensors/pimoroni_trackball.h
+++ b/drivers/sensors/pimoroni_trackball.h
@@ -16,22 +16,46 @@
*/
#pragma once
-#include "quantum.h"
-#include "pointing_device.h"
+#include <stdint.h>
+#include "report.h"
+#include "i2c_master.h"
-typedef struct pimoroni_data {
+#ifndef PIMORONI_TRACKBALL_ADDRESS
+# define PIMORONI_TRACKBALL_ADDRESS 0x0A
+#endif
+#ifndef PIMORONI_TRACKBALL_INTERVAL_MS
+# define PIMORONI_TRACKBALL_INTERVAL_MS 8
+#endif
+#ifndef PIMORONI_TRACKBALL_SCALE
+# define PIMORONI_TRACKBALL_SCALE 5
+#endif
+#ifndef PIMORONI_TRACKBALL_DEBOUNCE_CYCLES
+# define PIMORONI_TRACKBALL_DEBOUNCE_CYCLES 20
+#endif
+#ifndef PIMORONI_TRACKBALL_ERROR_COUNT
+# define PIMORONI_TRACKBALL_ERROR_COUNT 10
+#endif
+
+#ifndef PIMORONI_TRACKBALL_TIMEOUT
+# define PIMORONI_TRACKBALL_TIMEOUT 100
+#endif
+
+#ifndef PIMORONI_TRACKBALL_DEBUG_INTERVAL
+# define PIMORONI_TRACKBALL_DEBUG_INTERVAL 100
+#endif
+
+typedef struct {
uint8_t left;
uint8_t right;
uint8_t up;
uint8_t down;
uint8_t click;
-} pimoroni_data;
+} pimoroni_data_t;
-void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
-void trackball_click(bool pressed, report_mouse_t* mouse);
-int16_t trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale);
-void trackball_adapt_values(int8_t* mouse, int16_t* offset);
-float trackball_get_precision(void);
-void trackball_set_precision(float precision);
-bool trackball_is_scrolling(void);
-void trackball_set_scrolling(bool scroll);
+void pimironi_trackball_device_init(void);
+void pimoroni_trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
+int16_t pimoroni_trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale);
+void pimoroni_trackball_adapt_values(int8_t* mouse, int16_t* offset);
+float pimoroni_trackball_get_precision(void);
+void pimoroni_trackball_set_precision(float precision);
+i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data);
diff --git a/drivers/sensors/pmw3360.c b/drivers/sensors/pmw3360.c
index 17c4675ffa..2b27dccbb6 100644
--- a/drivers/sensors/pmw3360.c
+++ b/drivers/sensors/pmw3360.c
@@ -20,9 +20,10 @@
#include "wait.h"
#include "debug.h"
#include "print.h"
-#include "pmw3360_firmware.h"
+#include PMW3360_FIRMWARE_H
// Registers
+// clang-format off
#define REG_Product_ID 0x00
#define REG_Revision_ID 0x01
#define REG_Motion 0x02
@@ -72,10 +73,18 @@
#define REG_Lift_Config 0x63
#define REG_Raw_Data_Burst 0x64
#define REG_LiftCutoff_Tune2 0x65
+// clang-format on
+
+#ifndef MAX_CPI
+# define MAX_CPI 0x77 // limits to 0--119, should be max cpi/100
+#endif
bool _inBurst = false;
+#ifdef CONSOLE_ENABLE
void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
+#endif
+#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
bool spi_start_adv(void) {
bool status = spi_start(PMW3360_CS_PIN, PMW3360_SPI_LSBFIRST, PMW3360_SPI_MODE, PMW3360_SPI_DIVISOR);
@@ -124,20 +133,20 @@ uint8_t spi_read_adv(uint8_t reg_addr) {
return data;
}
-void pmw_set_cpi(uint16_t cpi) {
- uint8_t cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119
+void pmw3360_set_cpi(uint16_t cpi) {
+ uint8_t cpival = constrain((cpi / 100) - 1, 0, MAX_CPI);
spi_start_adv();
spi_write_adv(REG_Config1, cpival);
spi_stop();
}
-uint16_t pmw_get_cpi(void) {
+uint16_t pmw3360_get_cpi(void) {
uint8_t cpival = spi_read_adv(REG_Config1);
return (uint16_t)(cpival & 0xFF) * 100;
}
-bool pmw_spi_init(void) {
+bool pmw3360_init(void) {
setPinOutput(PMW3360_CS_PIN);
spi_init();
@@ -164,12 +173,12 @@ bool pmw_spi_init(void) {
spi_read_adv(REG_Delta_Y_L);
spi_read_adv(REG_Delta_Y_H);
- pmw_upload_firmware();
+ pmw3360_upload_firmware();
spi_stop_adv();
wait_ms(10);
- pmw_set_cpi(PMW3360_CPI);
+ pmw3360_set_cpi(PMW3360_CPI);
wait_ms(1);
@@ -177,14 +186,14 @@ bool pmw_spi_init(void) {
spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30));
- bool init_success = pmw_check_signature();
+ bool init_success = pmw3360_check_signature();
writePinLow(PMW3360_CS_PIN);
return init_success;
}
-void pmw_upload_firmware(void) {
+void pmw3360_upload_firmware(void) {
spi_write_adv(REG_SROM_Enable, 0x1d);
wait_ms(10);
@@ -196,7 +205,7 @@ void pmw_upload_firmware(void) {
wait_us(15);
unsigned char c;
- for (int i = 0; i < firmware_length; i++) {
+ for (int i = 0; i < FIRMWARE_LENGTH; i++) {
c = (unsigned char)pgm_read_byte(firmware_data + i);
spi_write(c);
wait_us(15);
@@ -211,16 +220,18 @@ void pmw_upload_firmware(void) {
wait_ms(10);
}
-bool pmw_check_signature(void) {
+bool pmw3360_check_signature(void) {
uint8_t pid = spi_read_adv(REG_Product_ID);
uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID);
uint8_t SROM_ver = spi_read_adv(REG_SROM_ID);
- return (pid == 0x42 && iv_pid == 0xBD && SROM_ver == 0x04); // signature for SROM 0x04
+ return (pid == firmware_signature[0] && iv_pid == firmware_signature[1] && SROM_ver == firmware_signature[2]); // signature for SROM 0x04
}
-report_pmw_t pmw_read_burst(void) {
+report_pmw3360_t pmw3360_read_burst(void) {
if (!_inBurst) {
+#ifdef CONSOLE_ENABLE
dprintf("burst on");
+#endif
spi_write_adv(REG_Motion_Burst, 0x00);
_inBurst = true;
}
@@ -229,12 +240,7 @@ report_pmw_t pmw_read_burst(void) {
spi_write(REG_Motion_Burst);
wait_us(35); // waits for tSRAD
- report_pmw_t data;
- data.motion = 0;
- data.dx = 0;
- data.mdx = 0;
- data.dy = 0;
- data.mdx = 0;
+ report_pmw3360_t data = {0};
data.motion = spi_read();
spi_write(0x00); // skip Observation
@@ -245,6 +251,7 @@ report_pmw_t pmw_read_burst(void) {
spi_stop();
+#ifdef CONSOLE_ENABLE
if (debug_mouse) {
print_byte(data.motion);
print_byte(data.dx);
@@ -253,6 +260,7 @@ report_pmw_t pmw_read_burst(void) {
print_byte(data.mdy);
dprintf("\n");
}
+#endif
data.isMotion = (data.motion & 0x80) != 0;
data.isOnSurface = (data.motion & 0x08) == 0;
diff --git a/drivers/sensors/pmw3360.h b/drivers/sensors/pmw3360.h
index 124c62cf00..7b2bef5b80 100644
--- a/drivers/sensors/pmw3360.h
+++ b/drivers/sensors/pmw3360.h
@@ -18,6 +18,8 @@
#pragma once
+#include <stdint.h>
+#include "report.h"
#include "spi_master.h"
#ifndef PMW3360_CPI
@@ -25,7 +27,7 @@
#endif
#ifndef PMW3360_CLOCK_SPEED
-# define PMW3360_CLOCK_SPEED 70000000
+# define PMW3360_CLOCK_SPEED 2000000
#endif
#ifndef PMW3360_SPI_LSBFIRST
@@ -52,6 +54,17 @@
# error "No chip select pin defined -- missing PMW3360_CS_PIN"
#endif
+/*
+The pmw33660 and pmw3389 use the same registers and timing and such.
+The only differences between the two is the firmware used, and the
+range for the DPI. So add a semi-secret hack to allow use of the
+pmw3389's firmware blob. Also, can set the max cpi range too.
+This should work for the 3390 and 3391 too, in theory.
+*/
+#ifndef PMW3360_FIRMWARE_H
+# define PMW3360_FIRMWARE_H "pmw3360_firmware.h"
+#endif
+
#ifdef CONSOLE_ENABLE
void print_byte(uint8_t byte);
#endif
@@ -64,22 +77,18 @@ typedef struct {
int8_t mdx;
int16_t dy; // displacement on y directions.
int8_t mdy;
-} report_pmw_t;
-
-
-
-bool spi_start_adv(void);
-void spi_stop_adv(void);
-spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data);
-uint8_t spi_read_adv(uint8_t reg_addr);
-bool pmw_spi_init(void);
-void pmw_set_cpi(uint16_t cpi);
-uint16_t pmw_get_cpi(void);
-void pmw_upload_firmware(void);
-bool pmw_check_signature(void);
-report_pmw_t pmw_read_burst(void);
-
+} report_pmw3360_t;
+
+bool spi_start_adv(void);
+void spi_stop_adv(void);
+spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data);
+uint8_t spi_read_adv(uint8_t reg_addr);
+bool pmw3360_init(void);
+void pmw3360_set_cpi(uint16_t cpi);
+uint16_t pmw3360_get_cpi(void);
+void pmw3360_upload_firmware(void);
+bool pmw3360_check_signature(void);
+report_pmw3360_t pmw3360_read_burst(void);
#define degToRad(angleInDegrees) ((angleInDegrees)*M_PI / 180.0)
#define radToDeg(angleInRadians) ((angleInRadians)*180.0 / M_PI)
-#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
diff --git a/drivers/sensors/pmw3360_firmware.h b/drivers/sensors/pmw3360_firmware.h
index cca5a6a4d8..ed9fda5a75 100644
--- a/drivers/sensors/pmw3360_firmware.h
+++ b/drivers/sensors/pmw3360_firmware.h
@@ -18,283 +18,271 @@
#pragma once
-// clang-format off
+#include "progmem.h"
+
+// PID, Inverse PID, SROM version
+const uint8_t firmware_signature[] PROGMEM = {0x42, 0xBD, 0x04};
+
+#define FIRMWARE_LENGTH 4094
+
// Firmware Blob foor PMW3360
-const uint16_t firmware_length = 4094;
-// clang-format off
-const uint8_t firmware_data[] PROGMEM = { // SROM 0x04
-0x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
-0xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
-0xc3, 0xe5, 0x29, 0xb1, 0xe0, 0x23, 0xa5, 0xa9, 0xb1, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0x1a,
-0x97, 0x8d, 0x79, 0x51, 0x20, 0xc7, 0x06, 0x8e, 0x7c, 0x7c, 0x7a, 0x76, 0x4f, 0xfd, 0x59,
-0x30, 0xe2, 0x46, 0x0e, 0x9e, 0xbe, 0xdf, 0x1d, 0x99, 0x91, 0xa0, 0xa5, 0xa1, 0xa9, 0xd0,
-0x22, 0xc6, 0xef, 0x5c, 0x1b, 0x95, 0x89, 0x90, 0xa2, 0xa7, 0xcc, 0xfb, 0x55, 0x28, 0xb3,
-0xe4, 0x4a, 0xf7, 0x6c, 0x3b, 0xf4, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0x9d, 0xb8, 0xd3, 0x05,
-0x88, 0x92, 0xa6, 0xce, 0x1e, 0xbe, 0xdf, 0x1d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x5c, 0x07,
-0x11, 0x5d, 0x98, 0x0b, 0x9d, 0x94, 0x97, 0xee, 0x4e, 0x45, 0x33, 0x6b, 0x44, 0xc7, 0x29,
-0x56, 0x27, 0x30, 0xc6, 0xa7, 0xd5, 0xf2, 0x56, 0xdf, 0xb4, 0x38, 0x62, 0xcb, 0xa0, 0xb6,
-0xe3, 0x0f, 0x84, 0x06, 0x24, 0x05, 0x65, 0x6f, 0x76, 0x89, 0xb5, 0x77, 0x41, 0x27, 0x82,
-0x66, 0x65, 0x82, 0xcc, 0xd5, 0xe6, 0x20, 0xd5, 0x27, 0x17, 0xc5, 0xf8, 0x03, 0x23, 0x7c,
-0x5f, 0x64, 0xa5, 0x1d, 0xc1, 0xd6, 0x36, 0xcb, 0x4c, 0xd4, 0xdb, 0x66, 0xd7, 0x8b, 0xb1,
-0x99, 0x7e, 0x6f, 0x4c, 0x36, 0x40, 0x06, 0xd6, 0xeb, 0xd7, 0xa2, 0xe4, 0xf4, 0x95, 0x51,
-0x5a, 0x54, 0x96, 0xd5, 0x53, 0x44, 0xd7, 0x8c, 0xe0, 0xb9, 0x40, 0x68, 0xd2, 0x18, 0xe9,
-0xdd, 0x9a, 0x23, 0x92, 0x48, 0xee, 0x7f, 0x43, 0xaf, 0xea, 0x77, 0x38, 0x84, 0x8c, 0x0a,
-0x72, 0xaf, 0x69, 0xf8, 0xdd, 0xf1, 0x24, 0x83, 0xa3, 0xf8, 0x4a, 0xbf, 0xf5, 0x94, 0x13,
-0xdb, 0xbb, 0xd8, 0xb4, 0xb3, 0xa0, 0xfb, 0x45, 0x50, 0x60, 0x30, 0x59, 0x12, 0x31, 0x71,
-0xa2, 0xd3, 0x13, 0xe7, 0xfa, 0xe7, 0xce, 0x0f, 0x63, 0x15, 0x0b, 0x6b, 0x94, 0xbb, 0x37,
-0x83, 0x26, 0x05, 0x9d, 0xfb, 0x46, 0x92, 0xfc, 0x0a, 0x15, 0xd1, 0x0d, 0x73, 0x92, 0xd6,
-0x8c, 0x1b, 0x8c, 0xb8, 0x55, 0x8a, 0xce, 0xbd, 0xfe, 0x8e, 0xfc, 0xed, 0x09, 0x12, 0x83,
-0x91, 0x82, 0x51, 0x31, 0x23, 0xfb, 0xb4, 0x0c, 0x76, 0xad, 0x7c, 0xd9, 0xb4, 0x4b, 0xb2,
-0x67, 0x14, 0x09, 0x9c, 0x7f, 0x0c, 0x18, 0xba, 0x3b, 0xd6, 0x8e, 0x14, 0x2a, 0xe4, 0x1b,
-0x52, 0x9f, 0x2b, 0x7d, 0xe1, 0xfb, 0x6a, 0x33, 0x02, 0xfa, 0xac, 0x5a, 0xf2, 0x3e, 0x88,
-0x7e, 0xae, 0xd1, 0xf3, 0x78, 0xe8, 0x05, 0xd1, 0xe3, 0xdc, 0x21, 0xf6, 0xe1, 0x9a, 0xbd,
-0x17, 0x0e, 0xd9, 0x46, 0x9b, 0x88, 0x03, 0xea, 0xf6, 0x66, 0xbe, 0x0e, 0x1b, 0x50, 0x49,
-0x96, 0x40, 0x97, 0xf1, 0xf1, 0xe4, 0x80, 0xa6, 0x6e, 0xe8, 0x77, 0x34, 0xbf, 0x29, 0x40,
-0x44, 0xc2, 0xff, 0x4e, 0x98, 0xd3, 0x9c, 0xa3, 0x32, 0x2b, 0x76, 0x51, 0x04, 0x09, 0xe7,
-0xa9, 0xd1, 0xa6, 0x32, 0xb1, 0x23, 0x53, 0xe2, 0x47, 0xab, 0xd6, 0xf5, 0x69, 0x5c, 0x3e,
-0x5f, 0xfa, 0xae, 0x45, 0x20, 0xe5, 0xd2, 0x44, 0xff, 0x39, 0x32, 0x6d, 0xfd, 0x27, 0x57,
-0x5c, 0xfd, 0xf0, 0xde, 0xc1, 0xb5, 0x99, 0xe5, 0xf5, 0x1c, 0x77, 0x01, 0x75, 0xc5, 0x6d,
-0x58, 0x92, 0xf2, 0xb2, 0x47, 0x00, 0x01, 0x26, 0x96, 0x7a, 0x30, 0xff, 0xb7, 0xf0, 0xef,
-0x77, 0xc1, 0x8a, 0x5d, 0xdc, 0xc0, 0xd1, 0x29, 0x30, 0x1e, 0x77, 0x38, 0x7a, 0x94, 0xf1,
-0xb8, 0x7a, 0x7e, 0xef, 0xa4, 0xd1, 0xac, 0x31, 0x4a, 0xf2, 0x5d, 0x64, 0x3d, 0xb2, 0xe2,
-0xf0, 0x08, 0x99, 0xfc, 0x70, 0xee, 0x24, 0xa7, 0x7e, 0xee, 0x1e, 0x20, 0x69, 0x7d, 0x44,
-0xbf, 0x87, 0x42, 0xdf, 0x88, 0x3b, 0x0c, 0xda, 0x42, 0xc9, 0x04, 0xf9, 0x45, 0x50, 0xfc,
-0x83, 0x8f, 0x11, 0x6a, 0x72, 0xbc, 0x99, 0x95, 0xf0, 0xac, 0x3d, 0xa7, 0x3b, 0xcd, 0x1c,
-0xe2, 0x88, 0x79, 0x37, 0x11, 0x5f, 0x39, 0x89, 0x95, 0x0a, 0x16, 0x84, 0x7a, 0xf6, 0x8a,
-0xa4, 0x28, 0xe4, 0xed, 0x83, 0x80, 0x3b, 0xb1, 0x23, 0xa5, 0x03, 0x10, 0xf4, 0x66, 0xea,
-0xbb, 0x0c, 0x0f, 0xc5, 0xec, 0x6c, 0x69, 0xc5, 0xd3, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0x99,
-0x88, 0x76, 0x08, 0xa0, 0xa8, 0x95, 0x7c, 0xd8, 0x38, 0x6d, 0xcd, 0x59, 0x02, 0x51, 0x4b,
-0xf1, 0xb5, 0x2b, 0x50, 0xe3, 0xb6, 0xbd, 0xd0, 0x72, 0xcf, 0x9e, 0xfd, 0x6e, 0xbb, 0x44,
-0xc8, 0x24, 0x8a, 0x77, 0x18, 0x8a, 0x13, 0x06, 0xef, 0x97, 0x7d, 0xfa, 0x81, 0xf0, 0x31,
-0xe6, 0xfa, 0x77, 0xed, 0x31, 0x06, 0x31, 0x5b, 0x54, 0x8a, 0x9f, 0x30, 0x68, 0xdb, 0xe2,
-0x40, 0xf8, 0x4e, 0x73, 0xfa, 0xab, 0x74, 0x8b, 0x10, 0x58, 0x13, 0xdc, 0xd2, 0xe6, 0x78,
-0xd1, 0x32, 0x2e, 0x8a, 0x9f, 0x2c, 0x58, 0x06, 0x48, 0x27, 0xc5, 0xa9, 0x5e, 0x81, 0x47,
-0x89, 0x46, 0x21, 0x91, 0x03, 0x70, 0xa4, 0x3e, 0x88, 0x9c, 0xda, 0x33, 0x0a, 0xce, 0xbc,
-0x8b, 0x8e, 0xcf, 0x9f, 0xd3, 0x71, 0x80, 0x43, 0xcf, 0x6b, 0xa9, 0x51, 0x83, 0x76, 0x30,
-0x82, 0xc5, 0x6a, 0x85, 0x39, 0x11, 0x50, 0x1a, 0x82, 0xdc, 0x1e, 0x1c, 0xd5, 0x7d, 0xa9,
-0x71, 0x99, 0x33, 0x47, 0x19, 0x97, 0xb3, 0x5a, 0xb1, 0xdf, 0xed, 0xa4, 0xf2, 0xe6, 0x26,
-0x84, 0xa2, 0x28, 0x9a, 0x9e, 0xdf, 0xa6, 0x6a, 0xf4, 0xd6, 0xfc, 0x2e, 0x5b, 0x9d, 0x1a,
-0x2a, 0x27, 0x68, 0xfb, 0xc1, 0x83, 0x21, 0x4b, 0x90, 0xe0, 0x36, 0xdd, 0x5b, 0x31, 0x42,
-0x55, 0xa0, 0x13, 0xf7, 0xd0, 0x89, 0x53, 0x71, 0x99, 0x57, 0x09, 0x29, 0xc5, 0xf3, 0x21,
-0xf8, 0x37, 0x2f, 0x40, 0xf3, 0xd4, 0xaf, 0x16, 0x08, 0x36, 0x02, 0xfc, 0x77, 0xc5, 0x8b,
-0x04, 0x90, 0x56, 0xb9, 0xc9, 0x67, 0x9a, 0x99, 0xe8, 0x00, 0xd3, 0x86, 0xff, 0x97, 0x2d,
-0x08, 0xe9, 0xb7, 0xb3, 0x91, 0xbc, 0xdf, 0x45, 0xc6, 0xed, 0x0f, 0x8c, 0x4c, 0x1e, 0xe6,
-0x5b, 0x6e, 0x38, 0x30, 0xe4, 0xaa, 0xe3, 0x95, 0xde, 0xb9, 0xe4, 0x9a, 0xf5, 0xb2, 0x55,
-0x9a, 0x87, 0x9b, 0xf6, 0x6a, 0xb2, 0xf2, 0x77, 0x9a, 0x31, 0xf4, 0x7a, 0x31, 0xd1, 0x1d,
-0x04, 0xc0, 0x7c, 0x32, 0xa2, 0x9e, 0x9a, 0xf5, 0x62, 0xf8, 0x27, 0x8d, 0xbf, 0x51, 0xff,
-0xd3, 0xdf, 0x64, 0x37, 0x3f, 0x2a, 0x6f, 0x76, 0x3a, 0x7d, 0x77, 0x06, 0x9e, 0x77, 0x7f,
-0x5e, 0xeb, 0x32, 0x51, 0xf9, 0x16, 0x66, 0x9a, 0x09, 0xf3, 0xb0, 0x08, 0xa4, 0x70, 0x96,
-0x46, 0x30, 0xff, 0xda, 0x4f, 0xe9, 0x1b, 0xed, 0x8d, 0xf8, 0x74, 0x1f, 0x31, 0x92, 0xb3,
-0x73, 0x17, 0x36, 0xdb, 0x91, 0x30, 0xd6, 0x88, 0x55, 0x6b, 0x34, 0x77, 0x87, 0x7a, 0xe7,
-0xee, 0x06, 0xc6, 0x1c, 0x8c, 0x19, 0x0c, 0x48, 0x46, 0x23, 0x5e, 0x9c, 0x07, 0x5c, 0xbf,
-0xb4, 0x7e, 0xd6, 0x4f, 0x74, 0x9c, 0xe2, 0xc5, 0x50, 0x8b, 0xc5, 0x8b, 0x15, 0x90, 0x60,
-0x62, 0x57, 0x29, 0xd0, 0x13, 0x43, 0xa1, 0x80, 0x88, 0x91, 0x00, 0x44, 0xc7, 0x4d, 0x19,
-0x86, 0xcc, 0x2f, 0x2a, 0x75, 0x5a, 0xfc, 0xeb, 0x97, 0x2a, 0x70, 0xe3, 0x78, 0xd8, 0x91,
-0xb0, 0x4f, 0x99, 0x07, 0xa3, 0x95, 0xea, 0x24, 0x21, 0xd5, 0xde, 0x51, 0x20, 0x93, 0x27,
-0x0a, 0x30, 0x73, 0xa8, 0xff, 0x8a, 0x97, 0xe9, 0xa7, 0x6a, 0x8e, 0x0d, 0xe8, 0xf0, 0xdf,
-0xec, 0xea, 0xb4, 0x6c, 0x1d, 0x39, 0x2a, 0x62, 0x2d, 0x3d, 0x5a, 0x8b, 0x65, 0xf8, 0x90,
-0x05, 0x2e, 0x7e, 0x91, 0x2c, 0x78, 0xef, 0x8e, 0x7a, 0xc1, 0x2f, 0xac, 0x78, 0xee, 0xaf,
-0x28, 0x45, 0x06, 0x4c, 0x26, 0xaf, 0x3b, 0xa2, 0xdb, 0xa3, 0x93, 0x06, 0xb5, 0x3c, 0xa5,
-0xd8, 0xee, 0x8f, 0xaf, 0x25, 0xcc, 0x3f, 0x85, 0x68, 0x48, 0xa9, 0x62, 0xcc, 0x97, 0x8f,
-0x7f, 0x2a, 0xea, 0xe0, 0x15, 0x0a, 0xad, 0x62, 0x07, 0xbd, 0x45, 0xf8, 0x41, 0xd8, 0x36,
-0xcb, 0x4c, 0xdb, 0x6e, 0xe6, 0x3a, 0xe7, 0xda, 0x15, 0xe9, 0x29, 0x1e, 0x12, 0x10, 0xa0,
-0x14, 0x2c, 0x0e, 0x3d, 0xf4, 0xbf, 0x39, 0x41, 0x92, 0x75, 0x0b, 0x25, 0x7b, 0xa3, 0xce,
-0x39, 0x9c, 0x15, 0x64, 0xc8, 0xfa, 0x3d, 0xef, 0x73, 0x27, 0xfe, 0x26, 0x2e, 0xce, 0xda,
-0x6e, 0xfd, 0x71, 0x8e, 0xdd, 0xfe, 0x76, 0xee, 0xdc, 0x12, 0x5c, 0x02, 0xc5, 0x3a, 0x4e,
-0x4e, 0x4f, 0xbf, 0xca, 0x40, 0x15, 0xc7, 0x6e, 0x8d, 0x41, 0xf1, 0x10, 0xe0, 0x4f, 0x7e,
-0x97, 0x7f, 0x1c, 0xae, 0x47, 0x8e, 0x6b, 0xb1, 0x25, 0x31, 0xb0, 0x73, 0xc7, 0x1b, 0x97,
-0x79, 0xf9, 0x80, 0xd3, 0x66, 0x22, 0x30, 0x07, 0x74, 0x1e, 0xe4, 0xd0, 0x80, 0x21, 0xd6,
-0xee, 0x6b, 0x6c, 0x4f, 0xbf, 0xf5, 0xb7, 0xd9, 0x09, 0x87, 0x2f, 0xa9, 0x14, 0xbe, 0x27,
-0xd9, 0x72, 0x50, 0x01, 0xd4, 0x13, 0x73, 0xa6, 0xa7, 0x51, 0x02, 0x75, 0x25, 0xe1, 0xb3,
-0x45, 0x34, 0x7d, 0xa8, 0x8e, 0xeb, 0xf3, 0x16, 0x49, 0xcb, 0x4f, 0x8c, 0xa1, 0xb9, 0x36,
-0x85, 0x39, 0x75, 0x5d, 0x08, 0x00, 0xae, 0xeb, 0xf6, 0xea, 0xd7, 0x13, 0x3a, 0x21, 0x5a,
-0x5f, 0x30, 0x84, 0x52, 0x26, 0x95, 0xc9, 0x14, 0xf2, 0x57, 0x55, 0x6b, 0xb1, 0x10, 0xc2,
-0xe1, 0xbd, 0x3b, 0x51, 0xc0, 0xb7, 0x55, 0x4c, 0x71, 0x12, 0x26, 0xc7, 0x0d, 0xf9, 0x51,
-0xa4, 0x38, 0x02, 0x05, 0x7f, 0xb8, 0xf1, 0x72, 0x4b, 0xbf, 0x71, 0x89, 0x14, 0xf3, 0x77,
-0x38, 0xd9, 0x71, 0x24, 0xf3, 0x00, 0x11, 0xa1, 0xd8, 0xd4, 0x69, 0x27, 0x08, 0x37, 0x35,
-0xc9, 0x11, 0x9d, 0x90, 0x1c, 0x0e, 0xe7, 0x1c, 0xff, 0x2d, 0x1e, 0xe8, 0x92, 0xe1, 0x18,
-0x10, 0x95, 0x7c, 0xe0, 0x80, 0xf4, 0x96, 0x43, 0x21, 0xf9, 0x75, 0x21, 0x64, 0x38, 0xdd,
-0x9f, 0x1e, 0x95, 0x16, 0xda, 0x56, 0x1d, 0x4f, 0x9a, 0x53, 0xb2, 0xe2, 0xe4, 0x18, 0xcb,
-0x6b, 0x1a, 0x65, 0xeb, 0x56, 0xc6, 0x3b, 0xe5, 0xfe, 0xd8, 0x26, 0x3f, 0x3a, 0x84, 0x59,
-0x72, 0x66, 0xa2, 0xf3, 0x75, 0xff, 0xfb, 0x60, 0xb3, 0x22, 0xad, 0x3f, 0x2d, 0x6b, 0xf9,
-0xeb, 0xea, 0x05, 0x7c, 0xd8, 0x8f, 0x6d, 0x2c, 0x98, 0x9e, 0x2b, 0x93, 0xf1, 0x5e, 0x46,
-0xf0, 0x87, 0x49, 0x29, 0x73, 0x68, 0xd7, 0x7f, 0xf9, 0xf0, 0xe5, 0x7d, 0xdb, 0x1d, 0x75,
-0x19, 0xf3, 0xc4, 0x58, 0x9b, 0x17, 0x88, 0xa8, 0x92, 0xe0, 0xbe, 0xbd, 0x8b, 0x1d, 0x8d,
-0x9f, 0x56, 0x76, 0xad, 0xaf, 0x29, 0xe2, 0xd9, 0xd5, 0x52, 0xf6, 0xb5, 0x56, 0x35, 0x57,
-0x3a, 0xc8, 0xe1, 0x56, 0x43, 0x19, 0x94, 0xd3, 0x04, 0x9b, 0x6d, 0x35, 0xd8, 0x0b, 0x5f,
-0x4d, 0x19, 0x8e, 0xec, 0xfa, 0x64, 0x91, 0x0a, 0x72, 0x20, 0x2b, 0xbc, 0x1a, 0x4a, 0xfe,
-0x8b, 0xfd, 0xbb, 0xed, 0x1b, 0x23, 0xea, 0xad, 0x72, 0x82, 0xa1, 0x29, 0x99, 0x71, 0xbd,
-0xf0, 0x95, 0xc1, 0x03, 0xdd, 0x7b, 0xc2, 0xb2, 0x3c, 0x28, 0x54, 0xd3, 0x68, 0xa4, 0x72,
-0xc8, 0x66, 0x96, 0xe0, 0xd1, 0xd8, 0x7f, 0xf8, 0xd1, 0x26, 0x2b, 0xf7, 0xad, 0xba, 0x55,
-0xca, 0x15, 0xb9, 0x32, 0xc3, 0xe5, 0x88, 0x97, 0x8e, 0x5c, 0xfb, 0x92, 0x25, 0x8b, 0xbf,
-0xa2, 0x45, 0x55, 0x7a, 0xa7, 0x6f, 0x8b, 0x57, 0x5b, 0xcf, 0x0e, 0xcb, 0x1d, 0xfb, 0x20,
-0x82, 0x77, 0xa8, 0x8c, 0xcc, 0x16, 0xce, 0x1d, 0xfa, 0xde, 0xcc, 0x0b, 0x62, 0xfe, 0xcc,
-0xe1, 0xb7, 0xf0, 0xc3, 0x81, 0x64, 0x73, 0x40, 0xa0, 0xc2, 0x4d, 0x89, 0x11, 0x75, 0x33,
-0x55, 0x33, 0x8d, 0xe8, 0x4a, 0xfd, 0xea, 0x6e, 0x30, 0x0b, 0xd7, 0x31, 0x2c, 0xde, 0x47,
-0xe3, 0xbf, 0xf8, 0x55, 0x42, 0xe2, 0x7f, 0x59, 0xe5, 0x17, 0xef, 0x99, 0x34, 0x69, 0x91,
-0xb1, 0x23, 0x8e, 0x20, 0x87, 0x2d, 0xa8, 0xfe, 0xd5, 0x8a, 0xf3, 0x84, 0x3a, 0xf0, 0x37,
-0xe4, 0x09, 0x00, 0x54, 0xee, 0x67, 0x49, 0x93, 0xe4, 0x81, 0x70, 0xe3, 0x90, 0x4d, 0xef,
-0xfe, 0x41, 0xb7, 0x99, 0x7b, 0xc1, 0x83, 0xba, 0x62, 0x12, 0x6f, 0x7d, 0xde, 0x6b, 0xaf,
-0xda, 0x16, 0xf9, 0x55, 0x51, 0xee, 0xa6, 0x0c, 0x2b, 0x02, 0xa3, 0xfd, 0x8d, 0xfb, 0x30,
-0x17, 0xe4, 0x6f, 0xdf, 0x36, 0x71, 0xc4, 0xca, 0x87, 0x25, 0x48, 0xb0, 0x47, 0xec, 0xea,
-0xb4, 0xbf, 0xa5, 0x4d, 0x9b, 0x9f, 0x02, 0x93, 0xc4, 0xe3, 0xe4, 0xe8, 0x42, 0x2d, 0x68,
-0x81, 0x15, 0x0a, 0xeb, 0x84, 0x5b, 0xd6, 0xa8, 0x74, 0xfb, 0x7d, 0x1d, 0xcb, 0x2c, 0xda,
-0x46, 0x2a, 0x76, 0x62, 0xce, 0xbc, 0x5c, 0x9e, 0x8b, 0xe7, 0xcf, 0xbe, 0x78, 0xf5, 0x7c,
-0xeb, 0xb3, 0x3a, 0x9c, 0xaa, 0x6f, 0xcc, 0x72, 0xd1, 0x59, 0xf2, 0x11, 0x23, 0xd6, 0x3f,
-0x48, 0xd1, 0xb7, 0xce, 0xb0, 0xbf, 0xcb, 0xea, 0x80, 0xde, 0x57, 0xd4, 0x5e, 0x97, 0x2f,
-0x75, 0xd1, 0x50, 0x8e, 0x80, 0x2c, 0x66, 0x79, 0xbf, 0x72, 0x4b, 0xbd, 0x8a, 0x81, 0x6c,
-0xd3, 0xe1, 0x01, 0xdc, 0xd2, 0x15, 0x26, 0xc5, 0x36, 0xda, 0x2c, 0x1a, 0xc0, 0x27, 0x94,
-0xed, 0xb7, 0x9b, 0x85, 0x0b, 0x5e, 0x80, 0x97, 0xc5, 0xec, 0x4f, 0xec, 0x88, 0x5d, 0x50,
-0x07, 0x35, 0x47, 0xdc, 0x0b, 0x3b, 0x3d, 0xdd, 0x60, 0xaf, 0xa8, 0x5d, 0x81, 0x38, 0x24,
-0x25, 0x5d, 0x5c, 0x15, 0xd1, 0xde, 0xb3, 0xab, 0xec, 0x05, 0x69, 0xef, 0x83, 0xed, 0x57,
-0x54, 0xb8, 0x64, 0x64, 0x11, 0x16, 0x32, 0x69, 0xda, 0x9f, 0x2d, 0x7f, 0x36, 0xbb, 0x44,
-0x5a, 0x34, 0xe8, 0x7f, 0xbf, 0x03, 0xeb, 0x00, 0x7f, 0x59, 0x68, 0x22, 0x79, 0xcf, 0x73,
-0x6c, 0x2c, 0x29, 0xa7, 0xa1, 0x5f, 0x38, 0xa1, 0x1d, 0xf0, 0x20, 0x53, 0xe0, 0x1a, 0x63,
-0x14, 0x58, 0x71, 0x10, 0xaa, 0x08, 0x0c, 0x3e, 0x16, 0x1a, 0x60, 0x22, 0x82, 0x7f, 0xba,
-0xa4, 0x43, 0xa0, 0xd0, 0xac, 0x1b, 0xd5, 0x6b, 0x64, 0xb5, 0x14, 0x93, 0x31, 0x9e, 0x53,
-0x50, 0xd0, 0x57, 0x66, 0xee, 0x5a, 0x4f, 0xfb, 0x03, 0x2a, 0x69, 0x58, 0x76, 0xf1, 0x83,
-0xf7, 0x4e, 0xba, 0x8c, 0x42, 0x06, 0x60, 0x5d, 0x6d, 0xce, 0x60, 0x88, 0xae, 0xa4, 0xc3,
-0xf1, 0x03, 0xa5, 0x4b, 0x98, 0xa1, 0xff, 0x67, 0xe1, 0xac, 0xa2, 0xb8, 0x62, 0xd7, 0x6f,
-0xa0, 0x31, 0xb4, 0xd2, 0x77, 0xaf, 0x21, 0x10, 0x06, 0xc6, 0x9a, 0xff, 0x1d, 0x09, 0x17,
-0x0e, 0x5f, 0xf1, 0xaa, 0x54, 0x34, 0x4b, 0x45, 0x8a, 0x87, 0x63, 0xa6, 0xdc, 0xf9, 0x24,
-0x30, 0x67, 0xc6, 0xb2, 0xd6, 0x61, 0x33, 0x69, 0xee, 0x50, 0x61, 0x57, 0x28, 0xe7, 0x7e,
-0xee, 0xec, 0x3a, 0x5a, 0x73, 0x4e, 0xa8, 0x8d, 0xe4, 0x18, 0xea, 0xec, 0x41, 0x64, 0xc8,
-0xe2, 0xe8, 0x66, 0xb6, 0x2d, 0xb6, 0xfb, 0x6a, 0x6c, 0x16, 0xb3, 0xdd, 0x46, 0x43, 0xb9,
-0x73, 0x00, 0x6a, 0x71, 0xed, 0x4e, 0x9d, 0x25, 0x1a, 0xc3, 0x3c, 0x4a, 0x95, 0x15, 0x99,
-0x35, 0x81, 0x14, 0x02, 0xd6, 0x98, 0x9b, 0xec, 0xd8, 0x23, 0x3b, 0x84, 0x29, 0xaf, 0x0c,
-0x99, 0x83, 0xa6, 0x9a, 0x34, 0x4f, 0xfa, 0xe8, 0xd0, 0x3c, 0x4b, 0xd0, 0xfb, 0xb6, 0x68,
-0xb8, 0x9e, 0x8f, 0xcd, 0xf7, 0x60, 0x2d, 0x7a, 0x22, 0xe5, 0x7d, 0xab, 0x65, 0x1b, 0x95,
-0xa7, 0xa8, 0x7f, 0xb6, 0x77, 0x47, 0x7b, 0x5f, 0x8b, 0x12, 0x72, 0xd0, 0xd4, 0x91, 0xef,
-0xde, 0x19, 0x50, 0x3c, 0xa7, 0x8b, 0xc4, 0xa9, 0xb3, 0x23, 0xcb, 0x76, 0xe6, 0x81, 0xf0,
-0xc1, 0x04, 0x8f, 0xa3, 0xb8, 0x54, 0x5b, 0x97, 0xac, 0x19, 0xff, 0x3f, 0x55, 0x27, 0x2f,
-0xe0, 0x1d, 0x42, 0x9b, 0x57, 0xfc, 0x4b, 0x4e, 0x0f, 0xce, 0x98, 0xa9, 0x43, 0x57, 0x03,
-0xbd, 0xe7, 0xc8, 0x94, 0xdf, 0x6e, 0x36, 0x73, 0x32, 0xb4, 0xef, 0x2e, 0x85, 0x7a, 0x6e,
-0xfc, 0x6c, 0x18, 0x82, 0x75, 0x35, 0x90, 0x07, 0xf3, 0xe4, 0x9f, 0x3e, 0xdc, 0x68, 0xf3,
-0xb5, 0xf3, 0x19, 0x80, 0x92, 0x06, 0x99, 0xa2, 0xe8, 0x6f, 0xff, 0x2e, 0x7f, 0xae, 0x42,
-0xa4, 0x5f, 0xfb, 0xd4, 0x0e, 0x81, 0x2b, 0xc3, 0x04, 0xff, 0x2b, 0xb3, 0x74, 0x4e, 0x36,
-0x5b, 0x9c, 0x15, 0x00, 0xc6, 0x47, 0x2b, 0xe8, 0x8b, 0x3d, 0xf1, 0x9c, 0x03, 0x9a, 0x58,
-0x7f, 0x9b, 0x9c, 0xbf, 0x85, 0x49, 0x79, 0x35, 0x2e, 0x56, 0x7b, 0x41, 0x14, 0x39, 0x47,
-0x83, 0x26, 0xaa, 0x07, 0x89, 0x98, 0x11, 0x1b, 0x86, 0xe7, 0x73, 0x7a, 0xd8, 0x7d, 0x78,
-0x61, 0x53, 0xe9, 0x79, 0xf5, 0x36, 0x8d, 0x44, 0x92, 0x84, 0xf9, 0x13, 0x50, 0x58, 0x3b,
-0xa4, 0x6a, 0x36, 0x65, 0x49, 0x8e, 0x3c, 0x0e, 0xf1, 0x6f, 0xd2, 0x84, 0xc4, 0x7e, 0x8e,
-0x3f, 0x39, 0xae, 0x7c, 0x84, 0xf1, 0x63, 0x37, 0x8e, 0x3c, 0xcc, 0x3e, 0x44, 0x81, 0x45,
-0xf1, 0x4b, 0xb9, 0xed, 0x6b, 0x36, 0x5d, 0xbb, 0x20, 0x60, 0x1a, 0x0f, 0xa3, 0xaa, 0x55,
-0x77, 0x3a, 0xa9, 0xae, 0x37, 0x4d, 0xba, 0xb8, 0x86, 0x6b, 0xbc, 0x08, 0x50, 0xf6, 0xcc,
-0xa4, 0xbd, 0x1d, 0x40, 0x72, 0xa5, 0x86, 0xfa, 0xe2, 0x10, 0xae, 0x3d, 0x58, 0x4b, 0x97,
-0xf3, 0x43, 0x74, 0xa9, 0x9e, 0xeb, 0x21, 0xb7, 0x01, 0xa4, 0x86, 0x93, 0x97, 0xee, 0x2f,
-0x4f, 0x3b, 0x86, 0xa1, 0x41, 0x6f, 0x41, 0x26, 0x90, 0x78, 0x5c, 0x7f, 0x30, 0x38, 0x4b,
-0x3f, 0xaa, 0xec, 0xed, 0x5c, 0x6f, 0x0e, 0xad, 0x43, 0x87, 0xfd, 0x93, 0x35, 0xe6, 0x01,
-0xef, 0x41, 0x26, 0x90, 0x99, 0x9e, 0xfb, 0x19, 0x5b, 0xad, 0xd2, 0x91, 0x8a, 0xe0, 0x46,
-0xaf, 0x65, 0xfa, 0x4f, 0x84, 0xc1, 0xa1, 0x2d, 0xcf, 0x45, 0x8b, 0xd3, 0x85, 0x50, 0x55,
-0x7c, 0xf9, 0x67, 0x88, 0xd4, 0x4e, 0xe9, 0xd7, 0x6b, 0x61, 0x54, 0xa1, 0xa4, 0xa6, 0xa2,
-0xc2, 0xbf, 0x30, 0x9c, 0x40, 0x9f, 0x5f, 0xd7, 0x69, 0x2b, 0x24, 0x82, 0x5e, 0xd9, 0xd6,
-0xa7, 0x12, 0x54, 0x1a, 0xf7, 0x55, 0x9f, 0x76, 0x50, 0xa9, 0x95, 0x84, 0xe6, 0x6b, 0x6d,
-0xb5, 0x96, 0x54, 0xd6, 0xcd, 0xb3, 0xa1, 0x9b, 0x46, 0xa7, 0x94, 0x4d, 0xc4, 0x94, 0xb4,
-0x98, 0xe3, 0xe1, 0xe2, 0x34, 0xd5, 0x33, 0x16, 0x07, 0x54, 0xcd, 0xb7, 0x77, 0x53, 0xdb,
-0x4f, 0x4d, 0x46, 0x9d, 0xe9, 0xd4, 0x9c, 0x8a, 0x36, 0xb6, 0xb8, 0x38, 0x26, 0x6c, 0x0e,
-0xff, 0x9c, 0x1b, 0x43, 0x8b, 0x80, 0xcc, 0xb9, 0x3d, 0xda, 0xc7, 0xf1, 0x8a, 0xf2, 0x6d,
-0xb8, 0xd7, 0x74, 0x2f, 0x7e, 0x1e, 0xb7, 0xd3, 0x4a, 0xb4, 0xac, 0xfc, 0x79, 0x48, 0x6c,
-0xbc, 0x96, 0xb6, 0x94, 0x46, 0x57, 0x2d, 0xb0, 0xa3, 0xfc, 0x1e, 0xb9, 0x52, 0x60, 0x85,
-0x2d, 0x41, 0xd0, 0x43, 0x01, 0x1e, 0x1c, 0xd5, 0x7d, 0xfc, 0xf3, 0x96, 0x0d, 0xc7, 0xcb,
-0x2a, 0x29, 0x9a, 0x93, 0xdd, 0x88, 0x2d, 0x37, 0x5d, 0xaa, 0xfb, 0x49, 0x68, 0xa0, 0x9c,
-0x50, 0x86, 0x7f, 0x68, 0x56, 0x57, 0xf9, 0x79, 0x18, 0x39, 0xd4, 0xe0, 0x01, 0x84, 0x33,
-0x61, 0xca, 0xa5, 0xd2, 0xd6, 0xe4, 0xc9, 0x8a, 0x4a, 0x23, 0x44, 0x4e, 0xbc, 0xf0, 0xdc,
-0x24, 0xa1, 0xa0, 0xc4, 0xe2, 0x07, 0x3c, 0x10, 0xc4, 0xb5, 0x25, 0x4b, 0x65, 0x63, 0xf4,
-0x80, 0xe7, 0xcf, 0x61, 0xb1, 0x71, 0x82, 0x21, 0x87, 0x2c, 0xf5, 0x91, 0x00, 0x32, 0x0c,
-0xec, 0xa9, 0xb5, 0x9a, 0x74, 0x85, 0xe3, 0x36, 0x8f, 0x76, 0x4f, 0x9c, 0x6d, 0xce, 0xbc,
-0xad, 0x0a, 0x4b, 0xed, 0x76, 0x04, 0xcb, 0xc3, 0xb9, 0x33, 0x9e, 0x01, 0x93, 0x96, 0x69,
-0x7d, 0xc5, 0xa2, 0x45, 0x79, 0x9b, 0x04, 0x5c, 0x84, 0x09, 0xed, 0x88, 0x43, 0xc7, 0xab,
-0x93, 0x14, 0x26, 0xa1, 0x40, 0xb5, 0xce, 0x4e, 0xbf, 0x2a, 0x42, 0x85, 0x3e, 0x2c, 0x3b,
-0x54, 0xe8, 0x12, 0x1f, 0x0e, 0x97, 0x59, 0xb2, 0x27, 0x89, 0xfa, 0xf2, 0xdf, 0x8e, 0x68,
-0x59, 0xdc, 0x06, 0xbc, 0xb6, 0x85, 0x0d, 0x06, 0x22, 0xec, 0xb1, 0xcb, 0xe5, 0x04, 0xe6,
-0x3d, 0xb3, 0xb0, 0x41, 0x73, 0x08, 0x3f, 0x3c, 0x58, 0x86, 0x63, 0xeb, 0x50, 0xee, 0x1d,
-0x2c, 0x37, 0x74, 0xa9, 0xd3, 0x18, 0xa3, 0x47, 0x6e, 0x93, 0x54, 0xad, 0x0a, 0x5d, 0xb8,
-0x2a, 0x55, 0x5d, 0x78, 0xf6, 0xee, 0xbe, 0x8e, 0x3c, 0x76, 0x69, 0xb9, 0x40, 0xc2, 0x34,
-0xec, 0x2a, 0xb9, 0xed, 0x7e, 0x20, 0xe4, 0x8d, 0x00, 0x38, 0xc7, 0xe6, 0x8f, 0x44, 0xa8,
-0x86, 0xce, 0xeb, 0x2a, 0xe9, 0x90, 0xf1, 0x4c, 0xdf, 0x32, 0xfb, 0x73, 0x1b, 0x6d, 0x92,
-0x1e, 0x95, 0xfe, 0xb4, 0xdb, 0x65, 0xdf, 0x4d, 0x23, 0x54, 0x89, 0x48, 0xbf, 0x4a, 0x2e,
-0x70, 0xd6, 0xd7, 0x62, 0xb4, 0x33, 0x29, 0xb1, 0x3a, 0x33, 0x4c, 0x23, 0x6d, 0xa6, 0x76,
-0xa5, 0x21, 0x63, 0x48, 0xe6, 0x90, 0x5d, 0xed, 0x90, 0x95, 0x0b, 0x7a, 0x84, 0xbe, 0xb8,
-0x0d, 0x5e, 0x63, 0x0c, 0x62, 0x26, 0x4c, 0x14, 0x5a, 0xb3, 0xac, 0x23, 0xa4, 0x74, 0xa7,
-0x6f, 0x33, 0x30, 0x05, 0x60, 0x01, 0x42, 0xa0, 0x28, 0xb7, 0xee, 0x19, 0x38, 0xf1, 0x64,
-0x80, 0x82, 0x43, 0xe1, 0x41, 0x27, 0x1f, 0x1f, 0x90, 0x54, 0x7a, 0xd5, 0x23, 0x2e, 0xd1,
-0x3d, 0xcb, 0x28, 0xba, 0x58, 0x7f, 0xdc, 0x7c, 0x91, 0x24, 0xe9, 0x28, 0x51, 0x83, 0x6e,
-0xc5, 0x56, 0x21, 0x42, 0xed, 0xa0, 0x56, 0x22, 0xa1, 0x40, 0x80, 0x6b, 0xa8, 0xf7, 0x94,
-0xca, 0x13, 0x6b, 0x0c, 0x39, 0xd9, 0xfd, 0xe9, 0xf3, 0x6f, 0xa6, 0x9e, 0xfc, 0x70, 0x8a,
-0xb3, 0xbc, 0x59, 0x3c, 0x1e, 0x1d, 0x6c, 0xf9, 0x7c, 0xaf, 0xf9, 0x88, 0x71, 0x95, 0xeb,
-0x57, 0x00, 0xbd, 0x9f, 0x8c, 0x4f, 0xe1, 0x24, 0x83, 0xc5, 0x22, 0xea, 0xfd, 0xd3, 0x0c,
-0xe2, 0x17, 0x18, 0x7c, 0x6a, 0x4c, 0xde, 0x77, 0xb4, 0x53, 0x9b, 0x4c, 0x81, 0xcd, 0x23,
-0x60, 0xaa, 0x0e, 0x25, 0x73, 0x9c, 0x02, 0x79, 0x32, 0x30, 0xdf, 0x74, 0xdf, 0x75, 0x19,
-0xf4, 0xa5, 0x14, 0x5c, 0xf7, 0x7a, 0xa8, 0xa5, 0x91, 0x84, 0x7c, 0x60, 0x03, 0x06, 0x3b,
-0xcd, 0x50, 0xb6, 0x27, 0x9c, 0xfe, 0xb1, 0xdd, 0xcc, 0xd3, 0xb0, 0x59, 0x24, 0xb2, 0xca,
-0xe2, 0x1c, 0x81, 0x22, 0x9d, 0x07, 0x8f, 0x8e, 0xb9, 0xbe, 0x4e, 0xfa, 0xfc, 0x39, 0x65,
-0xba, 0xbf, 0x9d, 0x12, 0x37, 0x5e, 0x97, 0x7e, 0xf3, 0x89, 0xf5, 0x5d, 0xf5, 0xe3, 0x09,
-0x8c, 0x62, 0xb5, 0x20, 0x9d, 0x0c, 0x53, 0x8a, 0x68, 0x1b, 0xd2, 0x8f, 0x75, 0x17, 0x5d,
-0xd4, 0xe5, 0xda, 0x75, 0x62, 0x19, 0x14, 0x6a, 0x26, 0x2d, 0xeb, 0xf8, 0xaf, 0x37, 0xf0,
-0x6c, 0xa4, 0x55, 0xb1, 0xbc, 0xe2, 0x33, 0xc0, 0x9a, 0xca, 0xb0, 0x11, 0x49, 0x4f, 0x68,
-0x9b, 0x3b, 0x6b, 0x3c, 0xcc, 0x13, 0xf6, 0xc7, 0x85, 0x61, 0x68, 0x42, 0xae, 0xbb, 0xdd,
-0xcd, 0x45, 0x16, 0x29, 0x1d, 0xea, 0xdb, 0xc8, 0x03, 0x94, 0x3c, 0xee, 0x4f, 0x82, 0x11,
-0xc3, 0xec, 0x28, 0xbd, 0x97, 0x05, 0x99, 0xde, 0xd7, 0xbb, 0x5e, 0x22, 0x1f, 0xd4, 0xeb,
-0x64, 0xd9, 0x92, 0xd9, 0x85, 0xb7, 0x6a, 0x05, 0x6a, 0xe4, 0x24, 0x41, 0xf1, 0xcd, 0xf0,
-0xd8, 0x3f, 0xf8, 0x9e, 0x0e, 0xcd, 0x0b, 0x7a, 0x70, 0x6b, 0x5a, 0x75, 0x0a, 0x6a, 0x33,
-0x88, 0xec, 0x17, 0x75, 0x08, 0x70, 0x10, 0x2f, 0x24, 0xcf, 0xc4, 0xe9, 0x42, 0x00, 0x61,
-0x94, 0xca, 0x1f, 0x3a, 0x76, 0x06, 0xfa, 0xd2, 0x48, 0x81, 0xf0, 0x77, 0x60, 0x03, 0x45,
-0xd9, 0x61, 0xf4, 0xa4, 0x6f, 0x3d, 0xd9, 0x30, 0xc3, 0x04, 0x6b, 0x54, 0x2a, 0xb7, 0xec,
-0x3b, 0xf4, 0x4b, 0xf5, 0x68, 0x52, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xa5,
-0xa9, 0xb1, 0xe0, 0x23, 0xc4, 0x0a, 0x77, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xa5, 0xa9, 0xb1,
-0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0xeb, 0x54, 0x0b,
-0x75, 0x68, 0x52, 0x07, 0x8c, 0x9a, 0x97, 0x8d, 0x79, 0x70, 0x62, 0x46, 0xef, 0x5c, 0x1b,
-0x95, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x67, 0x4c, 0x1a, 0xb6,
-0xcf, 0xfd, 0x78, 0x53, 0x24, 0xab, 0xb5, 0xc9, 0xf1, 0x60, 0x23, 0xa5, 0xc8, 0x12, 0x87,
-0x6d, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xc7, 0x0c, 0x9a, 0x97, 0xac,
-0xda, 0x36, 0xee, 0x5e, 0x3e, 0xdf, 0x1d, 0xb8, 0xf2, 0x66, 0x2f, 0xbd, 0xf8, 0x72, 0x47,
-0xed, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x8c, 0x7b, 0x55, 0x09, 0x90, 0xa2, 0xc6, 0xef,
-0x3d, 0xf8, 0x53, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0xec, 0x5a, 0x36, 0xee, 0x5e, 0x3e, 0xdf,
-0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x59, 0x30, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x53, 0x05, 0x69,
-0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0xb0, 0xe2, 0x27, 0xcc, 0xfb, 0x74,
-0x4b, 0x14, 0x8b, 0x94, 0x8b, 0x75, 0x68, 0x33, 0xc5, 0x08, 0x92, 0x87, 0x8c, 0x9a, 0xb6,
-0xcf, 0x1c, 0xba, 0xd7, 0x0d, 0x98, 0xb2, 0xe6, 0x2f, 0xdc, 0x1b, 0x95, 0x89, 0x71, 0x60,
-0x23, 0xc4, 0x0a, 0x96, 0x8f, 0x9c, 0xba, 0xf6, 0x6e, 0x3f, 0xfc, 0x5b, 0x15, 0xa8, 0xd2,
-0x26, 0xaf, 0xbd, 0xf8, 0x72, 0x66, 0x2f, 0xdc, 0x1b, 0xb4, 0xcb, 0x14, 0x8b, 0x94, 0xaa,
-0xb7, 0xcd, 0xf9, 0x51, 0x01, 0x80, 0x82, 0x86, 0x6f, 0x3d, 0xd9, 0x30, 0xe2, 0x27, 0xcc,
-0xfb, 0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x70, 0x43, 0x04, 0x6b, 0x35, 0xc9, 0xf1,
-0x60, 0x23, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xe6, 0x2f, 0xbd,
-0xf8, 0x72, 0x66, 0x4e, 0x1e, 0xbe, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x1d, 0x99, 0x91, 0xa0,
-0xa3, 0xc4, 0x0a, 0x77, 0x4d, 0x18, 0x93, 0xa4, 0xab, 0xd4, 0x0b, 0x75, 0x49, 0x10, 0xa2,
-0xc6, 0xef, 0x3d, 0xf8, 0x53, 0x24, 0xab, 0xb5, 0xe8, 0x33, 0xe4, 0x4a, 0x16, 0xae, 0xde,
-0x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xb3, 0xc5, 0x08, 0x73, 0x45, 0xe9, 0x31, 0xc1, 0xe1, 0x21,
-0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x86, 0x6f, 0x5c, 0x3a, 0xd7, 0x0d, 0x98, 0x93, 0xa4, 0xca,
-0x16, 0xae, 0xde, 0x1f, 0x9d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x72, 0x47, 0x0c,
-0x9a, 0xb6, 0xcf, 0xfd, 0x59, 0x11, 0xa0, 0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87,
-0x6d, 0x39, 0xf0, 0x43, 0x04, 0x8a, 0x96, 0xae, 0xde, 0x3e, 0xdf, 0x1d, 0x99, 0x91, 0xa0,
-0xc2, 0x06, 0x6f, 0x3d, 0xf8, 0x72, 0x47, 0x0c, 0x9a, 0x97, 0x8d, 0x98, 0x93, 0x85, 0x88,
-0x73, 0x45, 0xe9, 0x31, 0xe0, 0x23, 0xa5, 0xa9, 0xd0, 0x03, 0x84, 0x8a, 0x96, 0xae, 0xde,
-0x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xd2, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0x81, 0x80, 0x82,
-0x67, 0x2d, 0xd8, 0x13, 0xa4, 0xab, 0xd4, 0x0b, 0x94, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20,
-0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0xe9, 0x50, 0x22, 0xc6, 0xef, 0x5c, 0x3a, 0xd7, 0x0d, 0x98,
-0x93, 0x85, 0x88, 0x73, 0x64, 0x4a, 0xf7, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0x0a, 0x96,
-0xae, 0xde, 0x3e, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x78, 0x72,
-0x66, 0x2f, 0xbd, 0xd9, 0x30, 0xc3, 0xe5, 0x48, 0x12, 0x87, 0x8c, 0x7b, 0x55, 0x28, 0xd2,
-0x07, 0x8c, 0x9a, 0x97, 0xac, 0xda, 0x17, 0x8d, 0x79, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x54,
-0x0b, 0x94, 0x8b, 0x94, 0xaa, 0xd6, 0x2e, 0xbf, 0xfc, 0x5b, 0x15, 0xa8, 0xd2, 0x26, 0xaf,
-0xdc, 0x1b, 0xb4, 0xea, 0x37, 0xec, 0x3b, 0xf4, 0x6a, 0x37, 0xcd, 0x18, 0x93, 0x85, 0x69,
-0x31, 0xc1, 0xe1, 0x40, 0xe3, 0x25, 0xc8, 0x12, 0x87, 0x8c, 0x9a, 0xb6, 0xcf, 0xfd, 0x59,
-0x11, 0xa0, 0xc2, 0x06, 0x8e, 0x7f, 0x5d, 0x38, 0xf2, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x37,
-0xec, 0x5a, 0x36, 0xee, 0x3f, 0xfc, 0x7a, 0x76, 0x4f, 0x1c, 0x9b, 0x95, 0x89, 0x71, 0x41,
-0x00, 0x63, 0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x0f, 0x9c, 0xba, 0xd7, 0x0d, 0x98, 0x93, 0x85,
-0x69, 0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x9e, 0xbe, 0xdf, 0x3c, 0xfa, 0x57, 0x2c, 0xda,
-0x36, 0xee, 0x3f, 0xfc, 0x5b, 0x15, 0x89, 0x71, 0x41, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d,
-0x38, 0xf2, 0x47, 0xed, 0x58, 0x13, 0xa4, 0xca, 0xf7, 0x4d, 0xf9, 0x51, 0x01, 0x80, 0x63,
-0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0x91, 0xa0, 0xa3, 0xa5, 0xa9, 0xb1,
-0xe0, 0x42, 0x06, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0x0a, 0x96, 0x8f, 0x7d,
-0x78, 0x72, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0xbc, 0xfa, 0x57, 0x0d,
-0x79, 0x51, 0x01, 0x61, 0x21, 0xa1, 0xc0, 0xe3, 0x25, 0xa9, 0xb1, 0xc1, 0xe1, 0x40, 0x02,
-0x67, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0x93, 0xa4, 0xab, 0xd4, 0x2a, 0xd6, 0x0f, 0x9c, 0x9b,
-0xb4, 0xcb, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x35, 0xc9, 0xf1,
-0x60, 0x42, 0x06, 0x8e, 0x7f, 0x7c, 0x7a, 0x76, 0x6e, 0x3f, 0xfc, 0x7a, 0x76, 0x6e, 0x5e,
-0x3e, 0xfe, 0x7e, 0x5f, 0x3c, 0xdb, 0x15, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xc0, 0xe3, 0x44,
-0xeb, 0x54, 0x2a, 0xb7, 0xcd, 0xf9, 0x70, 0x62, 0x27, 0xad, 0xd8, 0x32, 0xc7, 0x0c, 0x7b,
-0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xec, 0x3b, 0xd5, 0x28, 0xd2, 0x07, 0x6d, 0x39, 0xd1, 0x20,
-0xc2, 0xe7, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0xb2, 0xc7, 0x0c, 0x59, 0x28, 0xf3, 0x9b };
// clang-format off
+const uint8_t firmware_data[FIRMWARE_LENGTH] PROGMEM = {
+ 0x01, 0x04, 0x8E, 0x96, 0x6E, 0x77, 0x3E, 0xFE, 0x7E, 0x5F, 0x1D, 0xB8, 0xF2, 0x66, 0x4E, 0xFF,
+ 0x5D, 0x19, 0xB0, 0xC2, 0x04, 0x69, 0x54, 0x2A, 0xD6, 0x2E, 0xBF, 0xDD, 0x19, 0xB0, 0xC3, 0xE5,
+ 0x29, 0xB1, 0xE0, 0x23, 0xA5, 0xA9, 0xB1, 0xC1, 0x00, 0x82, 0x67, 0x4C, 0x1A, 0x97, 0x8D, 0x79,
+ 0x51, 0x20, 0xC7, 0x06, 0x8E, 0x7C, 0x7C, 0x7A, 0x76, 0x4F, 0xFD, 0x59, 0x30, 0xE2, 0x46, 0x0E,
+ 0x9E, 0xBE, 0xDF, 0x1D, 0x99, 0x91, 0xA0, 0xA5, 0xA1, 0xA9, 0xD0, 0x22, 0xC6, 0xEF, 0x5C, 0x1B,
+ 0x95, 0x89, 0x90, 0xA2, 0xA7, 0xCC, 0xFB, 0x55, 0x28, 0xB3, 0xE4, 0x4A, 0xF7, 0x6C, 0x3B, 0xF4,
+ 0x6A, 0x56, 0x2E, 0xDE, 0x1F, 0x9D, 0xB8, 0xD3, 0x05, 0x88, 0x92, 0xA6, 0xCE, 0x1E, 0xBE, 0xDF,
+ 0x1D, 0x99, 0xB0, 0xE2, 0x46, 0xEF, 0x5C, 0x07, 0x11, 0x5D, 0x98, 0x0B, 0x9D, 0x94, 0x97, 0xEE,
+ 0x4E, 0x45, 0x33, 0x6B, 0x44, 0xC7, 0x29, 0x56, 0x27, 0x30, 0xC6, 0xA7, 0xD5, 0xF2, 0x56, 0xDF,
+ 0xB4, 0x38, 0x62, 0xCB, 0xA0, 0xB6, 0xE3, 0x0F, 0x84, 0x06, 0x24, 0x05, 0x65, 0x6F, 0x76, 0x89,
+ 0xB5, 0x77, 0x41, 0x27, 0x82, 0x66, 0x65, 0x82, 0xCC, 0xD5, 0xE6, 0x20, 0xD5, 0x27, 0x17, 0xC5,
+ 0xF8, 0x03, 0x23, 0x7C, 0x5F, 0x64, 0xA5, 0x1D, 0xC1, 0xD6, 0x36, 0xCB, 0x4C, 0xD4, 0xDB, 0x66,
+ 0xD7, 0x8B, 0xB1, 0x99, 0x7E, 0x6F, 0x4C, 0x36, 0x40, 0x06, 0xD6, 0xEB, 0xD7, 0xA2, 0xE4, 0xF4,
+ 0x95, 0x51, 0x5A, 0x54, 0x96, 0xD5, 0x53, 0x44, 0xD7, 0x8C, 0xE0, 0xB9, 0x40, 0x68, 0xD2, 0x18,
+ 0xE9, 0xDD, 0x9A, 0x23, 0x92, 0x48, 0xEE, 0x7F, 0x43, 0xAF, 0xEA, 0x77, 0x38, 0x84, 0x8C, 0x0A,
+ 0x72, 0xAF, 0x69, 0xF8, 0xDD, 0xF1, 0x24, 0x83, 0xA3, 0xF8, 0x4A, 0xBF, 0xF5, 0x94, 0x13, 0xDB,
+ 0xBB, 0xD8, 0xB4, 0xB3, 0xA0, 0xFB, 0x45, 0x50, 0x60, 0x30, 0x59, 0x12, 0x31, 0x71, 0xA2, 0xD3,
+ 0x13, 0xE7, 0xFA, 0xE7, 0xCE, 0x0F, 0x63, 0x15, 0x0B, 0x6B, 0x94, 0xBB, 0x37, 0x83, 0x26, 0x05,
+ 0x9D, 0xFB, 0x46, 0x92, 0xFC, 0x0A, 0x15, 0xD1, 0x0D, 0x73, 0x92, 0xD6, 0x8C, 0x1B, 0x8C, 0xB8,
+ 0x55, 0x8A, 0xCE, 0xBD, 0xFE, 0x8E, 0xFC, 0xED, 0x09, 0x12, 0x83, 0x91, 0x82, 0x51, 0x31, 0x23,
+ 0xFB, 0xB4, 0x0C, 0x76, 0xAD, 0x7C, 0xD9, 0xB4, 0x4B, 0xB2, 0x67, 0x14, 0x09, 0x9C, 0x7F, 0x0C,
+ 0x18, 0xBA, 0x3B, 0xD6, 0x8E, 0x14, 0x2A, 0xE4, 0x1B, 0x52, 0x9F, 0x2B, 0x7D, 0xE1, 0xFB, 0x6A,
+ 0x33, 0x02, 0xFA, 0xAC, 0x5A, 0xF2, 0x3E, 0x88, 0x7E, 0xAE, 0xD1, 0xF3, 0x78, 0xE8, 0x05, 0xD1,
+ 0xE3, 0xDC, 0x21, 0xF6, 0xE1, 0x9A, 0xBD, 0x17, 0x0E, 0xD9, 0x46, 0x9B, 0x88, 0x03, 0xEA, 0xF6,
+ 0x66, 0xBE, 0x0E, 0x1B, 0x50, 0x49, 0x96, 0x40, 0x97, 0xF1, 0xF1, 0xE4, 0x80, 0xA6, 0x6E, 0xE8,
+ 0x77, 0x34, 0xBF, 0x29, 0x40, 0x44, 0xC2, 0xFF, 0x4E, 0x98, 0xD3, 0x9C, 0xA3, 0x32, 0x2B, 0x76,
+ 0x51, 0x04, 0x09, 0xE7, 0xA9, 0xD1, 0xA6, 0x32, 0xB1, 0x23, 0x53, 0xE2, 0x47, 0xAB, 0xD6, 0xF5,
+ 0x69, 0x5C, 0x3E, 0x5F, 0xFA, 0xAE, 0x45, 0x20, 0xE5, 0xD2, 0x44, 0xFF, 0x39, 0x32, 0x6D, 0xFD,
+ 0x27, 0x57, 0x5C, 0xFD, 0xF0, 0xDE, 0xC1, 0xB5, 0x99, 0xE5, 0xF5, 0x1C, 0x77, 0x01, 0x75, 0xC5,
+ 0x6D, 0x58, 0x92, 0xF2, 0xB2, 0x47, 0x00, 0x01, 0x26, 0x96, 0x7A, 0x30, 0xFF, 0xB7, 0xF0, 0xEF,
+ 0x77, 0xC1, 0x8A, 0x5D, 0xDC, 0xC0, 0xD1, 0x29, 0x30, 0x1E, 0x77, 0x38, 0x7A, 0x94, 0xF1, 0xB8,
+ 0x7A, 0x7E, 0xEF, 0xA4, 0xD1, 0xAC, 0x31, 0x4A, 0xF2, 0x5D, 0x64, 0x3D, 0xB2, 0xE2, 0xF0, 0x08,
+ 0x99, 0xFC, 0x70, 0xEE, 0x24, 0xA7, 0x7E, 0xEE, 0x1E, 0x20, 0x69, 0x7D, 0x44, 0xBF, 0x87, 0x42,
+ 0xDF, 0x88, 0x3B, 0x0C, 0xDA, 0x42, 0xC9, 0x04, 0xF9, 0x45, 0x50, 0xFC, 0x83, 0x8F, 0x11, 0x6A,
+ 0x72, 0xBC, 0x99, 0x95, 0xF0, 0xAC, 0x3D, 0xA7, 0x3B, 0xCD, 0x1C, 0xE2, 0x88, 0x79, 0x37, 0x11,
+ 0x5F, 0x39, 0x89, 0x95, 0x0A, 0x16, 0x84, 0x7A, 0xF6, 0x8A, 0xA4, 0x28, 0xE4, 0xED, 0x83, 0x80,
+ 0x3B, 0xB1, 0x23, 0xA5, 0x03, 0x10, 0xF4, 0x66, 0xEA, 0xBB, 0x0C, 0x0F, 0xC5, 0xEC, 0x6C, 0x69,
+ 0xC5, 0xD3, 0x24, 0xAB, 0xD4, 0x2A, 0xB7, 0x99, 0x88, 0x76, 0x08, 0xA0, 0xA8, 0x95, 0x7C, 0xD8,
+ 0x38, 0x6D, 0xCD, 0x59, 0x02, 0x51, 0x4B, 0xF1, 0xB5, 0x2B, 0x50, 0xE3, 0xB6, 0xBD, 0xD0, 0x72,
+ 0xCF, 0x9E, 0xFD, 0x6E, 0xBB, 0x44, 0xC8, 0x24, 0x8A, 0x77, 0x18, 0x8A, 0x13, 0x06, 0xEF, 0x97,
+ 0x7D, 0xFA, 0x81, 0xF0, 0x31, 0xE6, 0xFA, 0x77, 0xED, 0x31, 0x06, 0x31, 0x5B, 0x54, 0x8A, 0x9F,
+ 0x30, 0x68, 0xDB, 0xE2, 0x40, 0xF8, 0x4E, 0x73, 0xFA, 0xAB, 0x74, 0x8B, 0x10, 0x58, 0x13, 0xDC,
+ 0xD2, 0xE6, 0x78, 0xD1, 0x32, 0x2E, 0x8A, 0x9F, 0x2C, 0x58, 0x06, 0x48, 0x27, 0xC5, 0xA9, 0x5E,
+ 0x81, 0x47, 0x89, 0x46, 0x21, 0x91, 0x03, 0x70, 0xA4, 0x3E, 0x88, 0x9C, 0xDA, 0x33, 0x0A, 0xCE,
+ 0xBC, 0x8B, 0x8E, 0xCF, 0x9F, 0xD3, 0x71, 0x80, 0x43, 0xCF, 0x6B, 0xA9, 0x51, 0x83, 0x76, 0x30,
+ 0x82, 0xC5, 0x6A, 0x85, 0x39, 0x11, 0x50, 0x1A, 0x82, 0xDC, 0x1E, 0x1C, 0xD5, 0x7D, 0xA9, 0x71,
+ 0x99, 0x33, 0x47, 0x19, 0x97, 0xB3, 0x5A, 0xB1, 0xDF, 0xED, 0xA4, 0xF2, 0xE6, 0x26, 0x84, 0xA2,
+ 0x28, 0x9A, 0x9E, 0xDF, 0xA6, 0x6A, 0xF4, 0xD6, 0xFC, 0x2E, 0x5B, 0x9D, 0x1A, 0x2A, 0x27, 0x68,
+ 0xFB, 0xC1, 0x83, 0x21, 0x4B, 0x90, 0xE0, 0x36, 0xDD, 0x5B, 0x31, 0x42, 0x55, 0xA0, 0x13, 0xF7,
+ 0xD0, 0x89, 0x53, 0x71, 0x99, 0x57, 0x09, 0x29, 0xC5, 0xF3, 0x21, 0xF8, 0x37, 0x2F, 0x40, 0xF3,
+ 0xD4, 0xAF, 0x16, 0x08, 0x36, 0x02, 0xFC, 0x77, 0xC5, 0x8B, 0x04, 0x90, 0x56, 0xB9, 0xC9, 0x67,
+ 0x9A, 0x99, 0xE8, 0x00, 0xD3, 0x86, 0xFF, 0x97, 0x2D, 0x08, 0xE9, 0xB7, 0xB3, 0x91, 0xBC, 0xDF,
+ 0x45, 0xC6, 0xED, 0x0F, 0x8C, 0x4C, 0x1E, 0xE6, 0x5B, 0x6E, 0x38, 0x30, 0xE4, 0xAA, 0xE3, 0x95,
+ 0xDE, 0xB9, 0xE4, 0x9A, 0xF5, 0xB2, 0x55, 0x9A, 0x87, 0x9B, 0xF6, 0x6A, 0xB2, 0xF2, 0x77, 0x9A,
+ 0x31, 0xF4, 0x7A, 0x31, 0xD1, 0x1D, 0x04, 0xC0, 0x7C, 0x32, 0xA2, 0x9E, 0x9A, 0xF5, 0x62, 0xF8,
+ 0x27, 0x8D, 0xBF, 0x51, 0xFF, 0xD3, 0xDF, 0x64, 0x37, 0x3F, 0x2A, 0x6F, 0x76, 0x3A, 0x7D, 0x77,
+ 0x06, 0x9E, 0x77, 0x7F, 0x5E, 0xEB, 0x32, 0x51, 0xF9, 0x16, 0x66, 0x9A, 0x09, 0xF3, 0xB0, 0x08,
+ 0xA4, 0x70, 0x96, 0x46, 0x30, 0xFF, 0xDA, 0x4F, 0xE9, 0x1B, 0xED, 0x8D, 0xF8, 0x74, 0x1F, 0x31,
+ 0x92, 0xB3, 0x73, 0x17, 0x36, 0xDB, 0x91, 0x30, 0xD6, 0x88, 0x55, 0x6B, 0x34, 0x77, 0x87, 0x7A,
+ 0xE7, 0xEE, 0x06, 0xC6, 0x1C, 0x8C, 0x19, 0x0C, 0x48, 0x46, 0x23, 0x5E, 0x9C, 0x07, 0x5C, 0xBF,
+ 0xB4, 0x7E, 0xD6, 0x4F, 0x74, 0x9C, 0xE2, 0xC5, 0x50, 0x8B, 0xC5, 0x8B, 0x15, 0x90, 0x60, 0x62,
+ 0x57, 0x29, 0xD0, 0x13, 0x43, 0xA1, 0x80, 0x88, 0x91, 0x00, 0x44, 0xC7, 0x4D, 0x19, 0x86, 0xCC,
+ 0x2F, 0x2A, 0x75, 0x5A, 0xFC, 0xEB, 0x97, 0x2A, 0x70, 0xE3, 0x78, 0xD8, 0x91, 0xB0, 0x4F, 0x99,
+ 0x07, 0xA3, 0x95, 0xEA, 0x24, 0x21, 0xD5, 0xDE, 0x51, 0x20, 0x93, 0x27, 0x0A, 0x30, 0x73, 0xA8,
+ 0xFF, 0x8A, 0x97, 0xE9, 0xA7, 0x6A, 0x8E, 0x0D, 0xE8, 0xF0, 0xDF, 0xEC, 0xEA, 0xB4, 0x6C, 0x1D,
+ 0x39, 0x2A, 0x62, 0x2D, 0x3D, 0x5A, 0x8B, 0x65, 0xF8, 0x90, 0x05, 0x2E, 0x7E, 0x91, 0x2C, 0x78,
+ 0xEF, 0x8E, 0x7A, 0xC1, 0x2F, 0xAC, 0x78, 0xEE, 0xAF, 0x28, 0x45, 0x06, 0x4C, 0x26, 0xAF, 0x3B,
+ 0xA2, 0xDB, 0xA3, 0x93, 0x06, 0xB5, 0x3C, 0xA5, 0xD8, 0xEE, 0x8F, 0xAF, 0x25, 0xCC, 0x3F, 0x85,
+ 0x68, 0x48, 0xA9, 0x62, 0xCC, 0x97, 0x8F, 0x7F, 0x2A, 0xEA, 0xE0, 0x15, 0x0A, 0xAD, 0x62, 0x07,
+ 0xBD, 0x45, 0xF8, 0x41, 0xD8, 0x36, 0xCB, 0x4C, 0xDB, 0x6E, 0xE6, 0x3A, 0xE7, 0xDA, 0x15, 0xE9,
+ 0x29, 0x1E, 0x12, 0x10, 0xA0, 0x14, 0x2C, 0x0E, 0x3D, 0xF4, 0xBF, 0x39, 0x41, 0x92, 0x75, 0x0B,
+ 0x25, 0x7B, 0xA3, 0xCE, 0x39, 0x9C, 0x15, 0x64, 0xC8, 0xFA, 0x3D, 0xEF, 0x73, 0x27, 0xFE, 0x26,
+ 0x2E, 0xCE, 0xDA, 0x6E, 0xFD, 0x71, 0x8E, 0xDD, 0xFE, 0x76, 0xEE, 0xDC, 0x12, 0x5C, 0x02, 0xC5,
+ 0x3A, 0x4E, 0x4E, 0x4F, 0xBF, 0xCA, 0x40, 0x15, 0xC7, 0x6E, 0x8D, 0x41, 0xF1, 0x10, 0xE0, 0x4F,
+ 0x7E, 0x97, 0x7F, 0x1C, 0xAE, 0x47, 0x8E, 0x6B, 0xB1, 0x25, 0x31, 0xB0, 0x73, 0xC7, 0x1B, 0x97,
+ 0x79, 0xF9, 0x80, 0xD3, 0x66, 0x22, 0x30, 0x07, 0x74, 0x1E, 0xE4, 0xD0, 0x80, 0x21, 0xD6, 0xEE,
+ 0x6B, 0x6C, 0x4F, 0xBF, 0xF5, 0xB7, 0xD9, 0x09, 0x87, 0x2F, 0xA9, 0x14, 0xBE, 0x27, 0xD9, 0x72,
+ 0x50, 0x01, 0xD4, 0x13, 0x73, 0xA6, 0xA7, 0x51, 0x02, 0x75, 0x25, 0xE1, 0xB3, 0x45, 0x34, 0x7D,
+ 0xA8, 0x8E, 0xEB, 0xF3, 0x16, 0x49, 0xCB, 0x4F, 0x8C, 0xA1, 0xB9, 0x36, 0x85, 0x39, 0x75, 0x5D,
+ 0x08, 0x00, 0xAE, 0xEB, 0xF6, 0xEA, 0xD7, 0x13, 0x3A, 0x21, 0x5A, 0x5F, 0x30, 0x84, 0x52, 0x26,
+ 0x95, 0xC9, 0x14, 0xF2, 0x57, 0x55, 0x6B, 0xB1, 0x10, 0xC2, 0xE1, 0xBD, 0x3B, 0x51, 0xC0, 0xB7,
+ 0x55, 0x4C, 0x71, 0x12, 0x26, 0xC7, 0x0D, 0xF9, 0x51, 0xA4, 0x38, 0x02, 0x05, 0x7F, 0xB8, 0xF1,
+ 0x72, 0x4B, 0xBF, 0x71, 0x89, 0x14, 0xF3, 0x77, 0x38, 0xD9, 0x71, 0x24, 0xF3, 0x00, 0x11, 0xA1,
+ 0xD8, 0xD4, 0x69, 0x27, 0x08, 0x37, 0x35, 0xC9, 0x11, 0x9D, 0x90, 0x1C, 0x0E, 0xE7, 0x1C, 0xFF,
+ 0x2D, 0x1E, 0xE8, 0x92, 0xE1, 0x18, 0x10, 0x95, 0x7C, 0xE0, 0x80, 0xF4, 0x96, 0x43, 0x21, 0xF9,
+ 0x75, 0x21, 0x64, 0x38, 0xDD, 0x9F, 0x1E, 0x95, 0x16, 0xDA, 0x56, 0x1D, 0x4F, 0x9A, 0x53, 0xB2,
+ 0xE2, 0xE4, 0x18, 0xCB, 0x6B, 0x1A, 0x65, 0xEB, 0x56, 0xC6, 0x3B, 0xE5, 0xFE, 0xD8, 0x26, 0x3F,
+ 0x3A, 0x84, 0x59, 0x72, 0x66, 0xA2, 0xF3, 0x75, 0xFF, 0xFB, 0x60, 0xB3, 0x22, 0xAD, 0x3F, 0x2D,
+ 0x6B, 0xF9, 0xEB, 0xEA, 0x05, 0x7C, 0xD8, 0x8F, 0x6D, 0x2C, 0x98, 0x9E, 0x2B, 0x93, 0xF1, 0x5E,
+ 0x46, 0xF0, 0x87, 0x49, 0x29, 0x73, 0x68, 0xD7, 0x7F, 0xF9, 0xF0, 0xE5, 0x7D, 0xDB, 0x1D, 0x75,
+ 0x19, 0xF3, 0xC4, 0x58, 0x9B, 0x17, 0x88, 0xA8, 0x92, 0xE0, 0xBE, 0xBD, 0x8B, 0x1D, 0x8D, 0x9F,
+ 0x56, 0x76, 0xAD, 0xAF, 0x29, 0xE2, 0xD9, 0xD5, 0x52, 0xF6, 0xB5, 0x56, 0x35, 0x57, 0x3A, 0xC8,
+ 0xE1, 0x56, 0x43, 0x19, 0x94, 0xD3, 0x04, 0x9B, 0x6D, 0x35, 0xD8, 0x0B, 0x5F, 0x4D, 0x19, 0x8E,
+ 0xEC, 0xFA, 0x64, 0x91, 0x0A, 0x72, 0x20, 0x2B, 0xBC, 0x1A, 0x4A, 0xFE, 0x8B, 0xFD, 0xBB, 0xED,
+ 0x1B, 0x23, 0xEA, 0xAD, 0x72, 0x82, 0xA1, 0x29, 0x99, 0x71, 0xBD, 0xF0, 0x95, 0xC1, 0x03, 0xDD,
+ 0x7B, 0xC2, 0xB2, 0x3C, 0x28, 0x54, 0xD3, 0x68, 0xA4, 0x72, 0xC8, 0x66, 0x96, 0xE0, 0xD1, 0xD8,
+ 0x7F, 0xF8, 0xD1, 0x26, 0x2B, 0xF7, 0xAD, 0xBA, 0x55, 0xCA, 0x15, 0xB9, 0x32, 0xC3, 0xE5, 0x88,
+ 0x97, 0x8E, 0x5C, 0xFB, 0x92, 0x25, 0x8B, 0xBF, 0xA2, 0x45, 0x55, 0x7A, 0xA7, 0x6F, 0x8B, 0x57,
+ 0x5B, 0xCF, 0x0E, 0xCB, 0x1D, 0xFB, 0x20, 0x82, 0x77, 0xA8, 0x8C, 0xCC, 0x16, 0xCE, 0x1D, 0xFA,
+ 0xDE, 0xCC, 0x0B, 0x62, 0xFE, 0xCC, 0xE1, 0xB7, 0xF0, 0xC3, 0x81, 0x64, 0x73, 0x40, 0xA0, 0xC2,
+ 0x4D, 0x89, 0x11, 0x75, 0x33, 0x55, 0x33, 0x8D, 0xE8, 0x4A, 0xFD, 0xEA, 0x6E, 0x30, 0x0B, 0xD7,
+ 0x31, 0x2C, 0xDE, 0x47, 0xE3, 0xBF, 0xF8, 0x55, 0x42, 0xE2, 0x7F, 0x59, 0xE5, 0x17, 0xEF, 0x99,
+ 0x34, 0x69, 0x91, 0xB1, 0x23, 0x8E, 0x20, 0x87, 0x2D, 0xA8, 0xFE, 0xD5, 0x8A, 0xF3, 0x84, 0x3A,
+ 0xF0, 0x37, 0xE4, 0x09, 0x00, 0x54, 0xEE, 0x67, 0x49, 0x93, 0xE4, 0x81, 0x70, 0xE3, 0x90, 0x4D,
+ 0xEF, 0xFE, 0x41, 0xB7, 0x99, 0x7B, 0xC1, 0x83, 0xBA, 0x62, 0x12, 0x6F, 0x7D, 0xDE, 0x6B, 0xAF,
+ 0xDA, 0x16, 0xF9, 0x55, 0x51, 0xEE, 0xA6, 0x0C, 0x2B, 0x02, 0xA3, 0xFD, 0x8D, 0xFB, 0x30, 0x17,
+ 0xE4, 0x6F, 0xDF, 0x36, 0x71, 0xC4, 0xCA, 0x87, 0x25, 0x48, 0xB0, 0x47, 0xEC, 0xEA, 0xB4, 0xBF,
+ 0xA5, 0x4D, 0x9B, 0x9F, 0x02, 0x93, 0xC4, 0xE3, 0xE4, 0xE8, 0x42, 0x2D, 0x68, 0x81, 0x15, 0x0A,
+ 0xEB, 0x84, 0x5B, 0xD6, 0xA8, 0x74, 0xFB, 0x7D, 0x1D, 0xCB, 0x2C, 0xDA, 0x46, 0x2A, 0x76, 0x62,
+ 0xCE, 0xBC, 0x5C, 0x9E, 0x8B, 0xE7, 0xCF, 0xBE, 0x78, 0xF5, 0x7C, 0xEB, 0xB3, 0x3A, 0x9C, 0xAA,
+ 0x6F, 0xCC, 0x72, 0xD1, 0x59, 0xF2, 0x11, 0x23, 0xD6, 0x3F, 0x48, 0xD1, 0xB7, 0xCE, 0xB0, 0xBF,
+ 0xCB, 0xEA, 0x80, 0xDE, 0x57, 0xD4, 0x5E, 0x97, 0x2F, 0x75, 0xD1, 0x50, 0x8E, 0x80, 0x2C, 0x66,
+ 0x79, 0xBF, 0x72, 0x4B, 0xBD, 0x8A, 0x81, 0x6C, 0xD3, 0xE1, 0x01, 0xDC, 0xD2, 0x15, 0x26, 0xC5,
+ 0x36, 0xDA, 0x2C, 0x1A, 0xC0, 0x27, 0x94, 0xED, 0xB7, 0x9B, 0x85, 0x0B, 0x5E, 0x80, 0x97, 0xC5,
+ 0xEC, 0x4F, 0xEC, 0x88, 0x5D, 0x50, 0x07, 0x35, 0x47, 0xDC, 0x0B, 0x3B, 0x3D, 0xDD, 0x60, 0xAF,
+ 0xA8, 0x5D, 0x81, 0x38, 0x24, 0x25, 0x5D, 0x5C, 0x15, 0xD1, 0xDE, 0xB3, 0xAB, 0xEC, 0x05, 0x69,
+ 0xEF, 0x83, 0xED, 0x57, 0x54, 0xB8, 0x64, 0x64, 0x11, 0x16, 0x32, 0x69, 0xDA, 0x9F, 0x2D, 0x7F,
+ 0x36, 0xBB, 0x44, 0x5A, 0x34, 0xE8, 0x7F, 0xBF, 0x03, 0xEB, 0x00, 0x7F, 0x59, 0x68, 0x22, 0x79,
+ 0xCF, 0x73, 0x6C, 0x2C, 0x29, 0xA7, 0xA1, 0x5F, 0x38, 0xA1, 0x1D, 0xF0, 0x20, 0x53, 0xE0, 0x1A,
+ 0x63, 0x14, 0x58, 0x71, 0x10, 0xAA, 0x08, 0x0C, 0x3E, 0x16, 0x1A, 0x60, 0x22, 0x82, 0x7F, 0xBA,
+ 0xA4, 0x43, 0xA0, 0xD0, 0xAC, 0x1B, 0xD5, 0x6B, 0x64, 0xB5, 0x14, 0x93, 0x31, 0x9E, 0x53, 0x50,
+ 0xD0, 0x57, 0x66, 0xEE, 0x5A, 0x4F, 0xFB, 0x03, 0x2A, 0x69, 0x58, 0x76, 0xF1, 0x83, 0xF7, 0x4E,
+ 0xBA, 0x8C, 0x42, 0x06, 0x60, 0x5D, 0x6D, 0xCE, 0x60, 0x88, 0xAE, 0xA4, 0xC3, 0xF1, 0x03, 0xA5,
+ 0x4B, 0x98, 0xA1, 0xFF, 0x67, 0xE1, 0xAC, 0xA2, 0xB8, 0x62, 0xD7, 0x6F, 0xA0, 0x31, 0xB4, 0xD2,
+ 0x77, 0xAF, 0x21, 0x10, 0x06, 0xC6, 0x9A, 0xFF, 0x1D, 0x09, 0x17, 0x0E, 0x5F, 0xF1, 0xAA, 0x54,
+ 0x34, 0x4B, 0x45, 0x8A, 0x87, 0x63, 0xA6, 0xDC, 0xF9, 0x24, 0x30, 0x67, 0xC6, 0xB2, 0xD6, 0x61,
+ 0x33, 0x69, 0xEE, 0x50, 0x61, 0x57, 0x28, 0xE7, 0x7E, 0xEE, 0xEC, 0x3A, 0x5A, 0x73, 0x4E, 0xA8,
+ 0x8D, 0xE4, 0x18, 0xEA, 0xEC, 0x41, 0x64, 0xC8, 0xE2, 0xE8, 0x66, 0xB6, 0x2D, 0xB6, 0xFB, 0x6A,
+ 0x6C, 0x16, 0xB3, 0xDD, 0x46, 0x43, 0xB9, 0x73, 0x00, 0x6A, 0x71, 0xED, 0x4E, 0x9D, 0x25, 0x1A,
+ 0xC3, 0x3C, 0x4A, 0x95, 0x15, 0x99, 0x35, 0x81, 0x14, 0x02, 0xD6, 0x98, 0x9B, 0xEC, 0xD8, 0x23,
+ 0x3B, 0x84, 0x29, 0xAF, 0x0C, 0x99, 0x83, 0xA6, 0x9A, 0x34, 0x4F, 0xFA, 0xE8, 0xD0, 0x3C, 0x4B,
+ 0xD0, 0xFB, 0xB6, 0x68, 0xB8, 0x9E, 0x8F, 0xCD, 0xF7, 0x60, 0x2D, 0x7A, 0x22, 0xE5, 0x7D, 0xAB,
+ 0x65, 0x1B, 0x95, 0xA7, 0xA8, 0x7F, 0xB6, 0x77, 0x47, 0x7B, 0x5F, 0x8B, 0x12, 0x72, 0xD0, 0xD4,
+ 0x91, 0xEF, 0xDE, 0x19, 0x50, 0x3C, 0xA7, 0x8B, 0xC4, 0xA9, 0xB3, 0x23, 0xCB, 0x76, 0xE6, 0x81,
+ 0xF0, 0xC1, 0x04, 0x8F, 0xA3, 0xB8, 0x54, 0x5B, 0x97, 0xAC, 0x19, 0xFF, 0x3F, 0x55, 0x27, 0x2F,
+ 0xE0, 0x1D, 0x42, 0x9B, 0x57, 0xFC, 0x4B, 0x4E, 0x0F, 0xCE, 0x98, 0xA9, 0x43, 0x57, 0x03, 0xBD,
+ 0xE7, 0xC8, 0x94, 0xDF, 0x6E, 0x36, 0x73, 0x32, 0xB4, 0xEF, 0x2E, 0x85, 0x7A, 0x6E, 0xFC, 0x6C,
+ 0x18, 0x82, 0x75, 0x35, 0x90, 0x07, 0xF3, 0xE4, 0x9F, 0x3E, 0xDC, 0x68, 0xF3, 0xB5, 0xF3, 0x19,
+ 0x80, 0x92, 0x06, 0x99, 0xA2, 0xE8, 0x6F, 0xFF, 0x2E, 0x7F, 0xAE, 0x42, 0xA4, 0x5F, 0xFB, 0xD4,
+ 0x0E, 0x81, 0x2B, 0xC3, 0x04, 0xFF, 0x2B, 0xB3, 0x74, 0x4E, 0x36, 0x5B, 0x9C, 0x15, 0x00, 0xC6,
+ 0x47, 0x2B, 0xE8, 0x8B, 0x3D, 0xF1, 0x9C, 0x03, 0x9A, 0x58, 0x7F, 0x9B, 0x9C, 0xBF, 0x85, 0x49,
+ 0x79, 0x35, 0x2E, 0x56, 0x7B, 0x41, 0x14, 0x39, 0x47, 0x83, 0x26, 0xAA, 0x07, 0x89, 0x98, 0x11,
+ 0x1B, 0x86, 0xE7, 0x73, 0x7A, 0xD8, 0x7D, 0x78, 0x61, 0x53, 0xE9, 0x79, 0xF5, 0x36, 0x8D, 0x44,
+ 0x92, 0x84, 0xF9, 0x13, 0x50, 0x58, 0x3B, 0xA4, 0x6A, 0x36, 0x65, 0x49, 0x8E, 0x3C, 0x0E, 0xF1,
+ 0x6F, 0xD2, 0x84, 0xC4, 0x7E, 0x8E, 0x3F, 0x39, 0xAE, 0x7C, 0x84, 0xF1, 0x63, 0x37, 0x8E, 0x3C,
+ 0xCC, 0x3E, 0x44, 0x81, 0x45, 0xF1, 0x4B, 0xB9, 0xED, 0x6B, 0x36, 0x5D, 0xBB, 0x20, 0x60, 0x1A,
+ 0x0F, 0xA3, 0xAA, 0x55, 0x77, 0x3A, 0xA9, 0xAE, 0x37, 0x4D, 0xBA, 0xB8, 0x86, 0x6B, 0xBC, 0x08,
+ 0x50, 0xF6, 0xCC, 0xA4, 0xBD, 0x1D, 0x40, 0x72, 0xA5, 0x86, 0xFA, 0xE2, 0x10, 0xAE, 0x3D, 0x58,
+ 0x4B, 0x97, 0xF3, 0x43, 0x74, 0xA9, 0x9E, 0xEB, 0x21, 0xB7, 0x01, 0xA4, 0x86, 0x93, 0x97, 0xEE,
+ 0x2F, 0x4F, 0x3B, 0x86, 0xA1, 0x41, 0x6F, 0x41, 0x26, 0x90, 0x78, 0x5C, 0x7F, 0x30, 0x38, 0x4B,
+ 0x3F, 0xAA, 0xEC, 0xED, 0x5C, 0x6F, 0x0E, 0xAD, 0x43, 0x87, 0xFD, 0x93, 0x35, 0xE6, 0x01, 0xEF,
+ 0x41, 0x26, 0x90, 0x99, 0x9E, 0xFB, 0x19, 0x5B, 0xAD, 0xD2, 0x91, 0x8A, 0xE0, 0x46, 0xAF, 0x65,
+ 0xFA, 0x4F, 0x84, 0xC1, 0xA1, 0x2D, 0xCF, 0x45, 0x8B, 0xD3, 0x85, 0x50, 0x55, 0x7C, 0xF9, 0x67,
+ 0x88, 0xD4, 0x4E, 0xE9, 0xD7, 0x6B, 0x61, 0x54, 0xA1, 0xA4, 0xA6, 0xA2, 0xC2, 0xBF, 0x30, 0x9C,
+ 0x40, 0x9F, 0x5F, 0xD7, 0x69, 0x2B, 0x24, 0x82, 0x5E, 0xD9, 0xD6, 0xA7, 0x12, 0x54, 0x1A, 0xF7,
+ 0x55, 0x9F, 0x76, 0x50, 0xA9, 0x95, 0x84, 0xE6, 0x6B, 0x6D, 0xB5, 0x96, 0x54, 0xD6, 0xCD, 0xB3,
+ 0xA1, 0x9B, 0x46, 0xA7, 0x94, 0x4D, 0xC4, 0x94, 0xB4, 0x98, 0xE3, 0xE1, 0xE2, 0x34, 0xD5, 0x33,
+ 0x16, 0x07, 0x54, 0xCD, 0xB7, 0x77, 0x53, 0xDB, 0x4F, 0x4D, 0x46, 0x9D, 0xE9, 0xD4, 0x9C, 0x8A,
+ 0x36, 0xB6, 0xB8, 0x38, 0x26, 0x6C, 0x0E, 0xFF, 0x9C, 0x1B, 0x43, 0x8B, 0x80, 0xCC, 0xB9, 0x3D,
+ 0xDA, 0xC7, 0xF1, 0x8A, 0xF2, 0x6D, 0xB8, 0xD7, 0x74, 0x2F, 0x7E, 0x1E, 0xB7, 0xD3, 0x4A, 0xB4,
+ 0xAC, 0xFC, 0x79, 0x48, 0x6C, 0xBC, 0x96, 0xB6, 0x94, 0x46, 0x57, 0x2D, 0xB0, 0xA3, 0xFC, 0x1E,
+ 0xB9, 0x52, 0x60, 0x85, 0x2D, 0x41, 0xD0, 0x43, 0x01, 0x1E, 0x1C, 0xD5, 0x7D, 0xFC, 0xF3, 0x96,
+ 0x0D, 0xC7, 0xCB, 0x2A, 0x29, 0x9A, 0x93, 0xDD, 0x88, 0x2D, 0x37, 0x5D, 0xAA, 0xFB, 0x49, 0x68,
+ 0xA0, 0x9C, 0x50, 0x86, 0x7F, 0x68, 0x56, 0x57, 0xF9, 0x79, 0x18, 0x39, 0xD4, 0xE0, 0x01, 0x84,
+ 0x33, 0x61, 0xCA, 0xA5, 0xD2, 0xD6, 0xE4, 0xC9, 0x8A, 0x4A, 0x23, 0x44, 0x4E, 0xBC, 0xF0, 0xDC,
+ 0x24, 0xA1, 0xA0, 0xC4, 0xE2, 0x07, 0x3C, 0x10, 0xC4, 0xB5, 0x25, 0x4B, 0x65, 0x63, 0xF4, 0x80,
+ 0xE7, 0xCF, 0x61, 0xB1, 0x71, 0x82, 0x21, 0x87, 0x2C, 0xF5, 0x91, 0x00, 0x32, 0x0C, 0xEC, 0xA9,
+ 0xB5, 0x9A, 0x74, 0x85, 0xE3, 0x36, 0x8F, 0x76, 0x4F, 0x9C, 0x6D, 0xCE, 0xBC, 0xAD, 0x0A, 0x4B,
+ 0xED, 0x76, 0x04, 0xCB, 0xC3, 0xB9, 0x33, 0x9E, 0x01, 0x93, 0x96, 0x69, 0x7D, 0xC5, 0xA2, 0x45,
+ 0x79, 0x9B, 0x04, 0x5C, 0x84, 0x09, 0xED, 0x88, 0x43, 0xC7, 0xAB, 0x93, 0x14, 0x26, 0xA1, 0x40,
+ 0xB5, 0xCE, 0x4E, 0xBF, 0x2A, 0x42, 0x85, 0x3E, 0x2C, 0x3B, 0x54, 0xE8, 0x12, 0x1F, 0x0E, 0x97,
+ 0x59, 0xB2, 0x27, 0x89, 0xFA, 0xF2, 0xDF, 0x8E, 0x68, 0x59, 0xDC, 0x06, 0xBC, 0xB6, 0x85, 0x0D,
+ 0x06, 0x22, 0xEC, 0xB1, 0xCB, 0xE5, 0x04, 0xE6, 0x3D, 0xB3, 0xB0, 0x41, 0x73, 0x08, 0x3F, 0x3C,
+ 0x58, 0x86, 0x63, 0xEB, 0x50, 0xEE, 0x1D, 0x2C, 0x37, 0x74, 0xA9, 0xD3, 0x18, 0xA3, 0x47, 0x6E,
+ 0x93, 0x54, 0xAD, 0x0A, 0x5D, 0xB8, 0x2A, 0x55, 0x5D, 0x78, 0xF6, 0xEE, 0xBE, 0x8E, 0x3C, 0x76,
+ 0x69, 0xB9, 0x40, 0xC2, 0x34, 0xEC, 0x2A, 0xB9, 0xED, 0x7E, 0x20, 0xE4, 0x8D, 0x00, 0x38, 0xC7,
+ 0xE6, 0x8F, 0x44, 0xA8, 0x86, 0xCE, 0xEB, 0x2A, 0xE9, 0x90, 0xF1, 0x4C, 0xDF, 0x32, 0xFB, 0x73,
+ 0x1B, 0x6D, 0x92, 0x1E, 0x95, 0xFE, 0xB4, 0xDB, 0x65, 0xDF, 0x4D, 0x23, 0x54, 0x89, 0x48, 0xBF,
+ 0x4A, 0x2E, 0x70, 0xD6, 0xD7, 0x62, 0xB4, 0x33, 0x29, 0xB1, 0x3A, 0x33, 0x4C, 0x23, 0x6D, 0xA6,
+ 0x76, 0xA5, 0x21, 0x63, 0x48, 0xE6, 0x90, 0x5D, 0xED, 0x90, 0x95, 0x0B, 0x7A, 0x84, 0xBE, 0xB8,
+ 0x0D, 0x5E, 0x63, 0x0C, 0x62, 0x26, 0x4C, 0x14, 0x5A, 0xB3, 0xAC, 0x23, 0xA4, 0x74, 0xA7, 0x6F,
+ 0x33, 0x30, 0x05, 0x60, 0x01, 0x42, 0xA0, 0x28, 0xB7, 0xEE, 0x19, 0x38, 0xF1, 0x64, 0x80, 0x82,
+ 0x43, 0xE1, 0x41, 0x27, 0x1F, 0x1F, 0x90, 0x54, 0x7A, 0xD5, 0x23, 0x2E, 0xD1, 0x3D, 0xCB, 0x28,
+ 0xBA, 0x58, 0x7F, 0xDC, 0x7C, 0x91, 0x24, 0xE9, 0x28, 0x51, 0x83, 0x6E, 0xC5, 0x56, 0x21, 0x42,
+ 0xED, 0xA0, 0x56, 0x22, 0xA1, 0x40, 0x80, 0x6B, 0xA8, 0xF7, 0x94, 0xCA, 0x13, 0x6B, 0x0C, 0x39,
+ 0xD9, 0xFD, 0xE9, 0xF3, 0x6F, 0xA6, 0x9E, 0xFC, 0x70, 0x8A, 0xB3, 0xBC, 0x59, 0x3C, 0x1E, 0x1D,
+ 0x6C, 0xF9, 0x7C, 0xAF, 0xF9, 0x88, 0x71, 0x95, 0xEB, 0x57, 0x00, 0xBD, 0x9F, 0x8C, 0x4F, 0xE1,
+ 0x24, 0x83, 0xC5, 0x22, 0xEA, 0xFD, 0xD3, 0x0C, 0xE2, 0x17, 0x18, 0x7C, 0x6A, 0x4C, 0xDE, 0x77,
+ 0xB4, 0x53, 0x9B, 0x4C, 0x81, 0xCD, 0x23, 0x60, 0xAA, 0x0E, 0x25, 0x73, 0x9C, 0x02, 0x79, 0x32,
+ 0x30, 0xDF, 0x74, 0xDF, 0x75, 0x19, 0xF4, 0xA5, 0x14, 0x5C, 0xF7, 0x7A, 0xA8, 0xA5, 0x91, 0x84,
+ 0x7C, 0x60, 0x03, 0x06, 0x3B, 0xCD, 0x50, 0xB6, 0x27, 0x9C, 0xFE, 0xB1, 0xDD, 0xCC, 0xD3, 0xB0,
+ 0x59, 0x24, 0xB2, 0xCA, 0xE2, 0x1C, 0x81, 0x22, 0x9D, 0x07, 0x8F, 0x8E, 0xB9, 0xBE, 0x4E, 0xFA,
+ 0xFC, 0x39, 0x65, 0xBA, 0xBF, 0x9D, 0x12, 0x37, 0x5E, 0x97, 0x7E, 0xF3, 0x89, 0xF5, 0x5D, 0xF5,
+ 0xE3, 0x09, 0x8C, 0x62, 0xB5, 0x20, 0x9D, 0x0C, 0x53, 0x8A, 0x68, 0x1B, 0xD2, 0x8F, 0x75, 0x17,
+ 0x5D, 0xD4, 0xE5, 0xDA, 0x75, 0x62, 0x19, 0x14, 0x6A, 0x26, 0x2D, 0xEB, 0xF8, 0xAF, 0x37, 0xF0,
+ 0x6C, 0xA4, 0x55, 0xB1, 0xBC, 0xE2, 0x33, 0xC0, 0x9A, 0xCA, 0xB0, 0x11, 0x49, 0x4F, 0x68, 0x9B,
+ 0x3B, 0x6B, 0x3C, 0xCC, 0x13, 0xF6, 0xC7, 0x85, 0x61, 0x68, 0x42, 0xAE, 0xBB, 0xDD, 0xCD, 0x45,
+ 0x16, 0x29, 0x1D, 0xEA, 0xDB, 0xC8, 0x03, 0x94, 0x3C, 0xEE, 0x4F, 0x82, 0x11, 0xC3, 0xEC, 0x28,
+ 0xBD, 0x97, 0x05, 0x99, 0xDE, 0xD7, 0xBB, 0x5E, 0x22, 0x1F, 0xD4, 0xEB, 0x64, 0xD9, 0x92, 0xD9,
+ 0x85, 0xB7, 0x6A, 0x05, 0x6A, 0xE4, 0x24, 0x41, 0xF1, 0xCD, 0xF0, 0xD8, 0x3F, 0xF8, 0x9E, 0x0E,
+ 0xCD, 0x0B, 0x7A, 0x70, 0x6B, 0x5A, 0x75, 0x0A, 0x6A, 0x33, 0x88, 0xEC, 0x17, 0x75, 0x08, 0x70,
+ 0x10, 0x2F, 0x24, 0xCF, 0xC4, 0xE9, 0x42, 0x00, 0x61, 0x94, 0xCA, 0x1F, 0x3A, 0x76, 0x06, 0xFA,
+ 0xD2, 0x48, 0x81, 0xF0, 0x77, 0x60, 0x03, 0x45, 0xD9, 0x61, 0xF4, 0xA4, 0x6F, 0x3D, 0xD9, 0x30,
+ 0xC3, 0x04, 0x6B, 0x54, 0x2A, 0xB7, 0xEC, 0x3B, 0xF4, 0x4B, 0xF5, 0x68, 0x52, 0x26, 0xCE, 0xFF,
+ 0x5D, 0x19, 0x91, 0xA0, 0xA3, 0xA5, 0xA9, 0xB1, 0xE0, 0x23, 0xC4, 0x0A, 0x77, 0x4D, 0xF9, 0x51,
+ 0x20, 0xA3, 0xA5, 0xA9, 0xB1, 0xC1, 0x00, 0x82, 0x86, 0x8E, 0x7F, 0x5D, 0x19, 0x91, 0xA0, 0xA3,
+ 0xC4, 0xEB, 0x54, 0x0B, 0x75, 0x68, 0x52, 0x07, 0x8C, 0x9A, 0x97, 0x8D, 0x79, 0x70, 0x62, 0x46,
+ 0xEF, 0x5C, 0x1B, 0x95, 0x89, 0x71, 0x41, 0xE1, 0x21, 0xA1, 0xA1, 0xA1, 0xC0, 0x02, 0x67, 0x4C,
+ 0x1A, 0xB6, 0xCF, 0xFD, 0x78, 0x53, 0x24, 0xAB, 0xB5, 0xC9, 0xF1, 0x60, 0x23, 0xA5, 0xC8, 0x12,
+ 0x87, 0x6D, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x6D, 0x58, 0x32, 0xC7, 0x0C, 0x9A, 0x97, 0xAC,
+ 0xDA, 0x36, 0xEE, 0x5E, 0x3E, 0xDF, 0x1D, 0xB8, 0xF2, 0x66, 0x2F, 0xBD, 0xF8, 0x72, 0x47, 0xED,
+ 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x8C, 0x7B, 0x55, 0x09, 0x90, 0xA2, 0xC6, 0xEF, 0x3D, 0xF8,
+ 0x53, 0x24, 0xAB, 0xD4, 0x2A, 0xB7, 0xEC, 0x5A, 0x36, 0xEE, 0x5E, 0x3E, 0xDF, 0x3C, 0xFA, 0x76,
+ 0x4F, 0xFD, 0x59, 0x30, 0xE2, 0x46, 0xEF, 0x3D, 0xF8, 0x53, 0x05, 0x69, 0x31, 0xC1, 0x00, 0x82,
+ 0x86, 0x8E, 0x7F, 0x5D, 0x19, 0xB0, 0xE2, 0x27, 0xCC, 0xFB, 0x74, 0x4B, 0x14, 0x8B, 0x94, 0x8B,
+ 0x75, 0x68, 0x33, 0xC5, 0x08, 0x92, 0x87, 0x8C, 0x9A, 0xB6, 0xCF, 0x1C, 0xBA, 0xD7, 0x0D, 0x98,
+ 0xB2, 0xE6, 0x2F, 0xDC, 0x1B, 0x95, 0x89, 0x71, 0x60, 0x23, 0xC4, 0x0A, 0x96, 0x8F, 0x9C, 0xBA,
+ 0xF6, 0x6E, 0x3F, 0xFC, 0x5B, 0x15, 0xA8, 0xD2, 0x26, 0xAF, 0xBD, 0xF8, 0x72, 0x66, 0x2F, 0xDC,
+ 0x1B, 0xB4, 0xCB, 0x14, 0x8B, 0x94, 0xAA, 0xB7, 0xCD, 0xF9, 0x51, 0x01, 0x80, 0x82, 0x86, 0x6F,
+ 0x3D, 0xD9, 0x30, 0xE2, 0x27, 0xCC, 0xFB, 0x74, 0x4B, 0x14, 0xAA, 0xB7, 0xCD, 0xF9, 0x70, 0x43,
+ 0x04, 0x6B, 0x35, 0xC9, 0xF1, 0x60, 0x23, 0xA5, 0xC8, 0xF3, 0x45, 0x08, 0x92, 0x87, 0x6D, 0x58,
+ 0x32, 0xE6, 0x2F, 0xBD, 0xF8, 0x72, 0x66, 0x4E, 0x1E, 0xBE, 0xFE, 0x7E, 0x7E, 0x7E, 0x5F, 0x1D,
+ 0x99, 0x91, 0xA0, 0xA3, 0xC4, 0x0A, 0x77, 0x4D, 0x18, 0x93, 0xA4, 0xAB, 0xD4, 0x0B, 0x75, 0x49,
+ 0x10, 0xA2, 0xC6, 0xEF, 0x3D, 0xF8, 0x53, 0x24, 0xAB, 0xB5, 0xE8, 0x33, 0xE4, 0x4A, 0x16, 0xAE,
+ 0xDE, 0x1F, 0xBC, 0xDB, 0x15, 0xA8, 0xB3, 0xC5, 0x08, 0x73, 0x45, 0xE9, 0x31, 0xC1, 0xE1, 0x21,
+ 0xA1, 0xA1, 0xA1, 0xC0, 0x02, 0x86, 0x6F, 0x5C, 0x3A, 0xD7, 0x0D, 0x98, 0x93, 0xA4, 0xCA, 0x16,
+ 0xAE, 0xDE, 0x1F, 0x9D, 0x99, 0xB0, 0xE2, 0x46, 0xEF, 0x3D, 0xF8, 0x72, 0x47, 0x0C, 0x9A, 0xB6,
+ 0xCF, 0xFD, 0x59, 0x11, 0xA0, 0xA3, 0xA5, 0xC8, 0xF3, 0x45, 0x08, 0x92, 0x87, 0x6D, 0x39, 0xF0,
+ 0x43, 0x04, 0x8A, 0x96, 0xAE, 0xDE, 0x3E, 0xDF, 0x1D, 0x99, 0x91, 0xA0, 0xC2, 0x06, 0x6F, 0x3D,
+ 0xF8, 0x72, 0x47, 0x0C, 0x9A, 0x97, 0x8D, 0x98, 0x93, 0x85, 0x88, 0x73, 0x45, 0xE9, 0x31, 0xE0,
+ 0x23, 0xA5, 0xA9, 0xD0, 0x03, 0x84, 0x8A, 0x96, 0xAE, 0xDE, 0x1F, 0xBC, 0xDB, 0x15, 0xA8, 0xD2,
+ 0x26, 0xCE, 0xFF, 0x5D, 0x19, 0x91, 0x81, 0x80, 0x82, 0x67, 0x2D, 0xD8, 0x13, 0xA4, 0xAB, 0xD4,
+ 0x0B, 0x94, 0xAA, 0xB7, 0xCD, 0xF9, 0x51, 0x20, 0xA3, 0xA5, 0xC8, 0xF3, 0x45, 0xE9, 0x50, 0x22,
+ 0xC6, 0xEF, 0x5C, 0x3A, 0xD7, 0x0D, 0x98, 0x93, 0x85, 0x88, 0x73, 0x64, 0x4A, 0xF7, 0x4D, 0xF9,
+ 0x51, 0x20, 0xA3, 0xC4, 0x0A, 0x96, 0xAE, 0xDE, 0x3E, 0xFE, 0x7E, 0x7E, 0x7E, 0x5F, 0x3C, 0xFA,
+ 0x76, 0x4F, 0xFD, 0x78, 0x72, 0x66, 0x2F, 0xBD, 0xD9, 0x30, 0xC3, 0xE5, 0x48, 0x12, 0x87, 0x8C,
+ 0x7B, 0x55, 0x28, 0xD2, 0x07, 0x8C, 0x9A, 0x97, 0xAC, 0xDA, 0x17, 0x8D, 0x79, 0x51, 0x20, 0xA3,
+ 0xC4, 0xEB, 0x54, 0x0B, 0x94, 0x8B, 0x94, 0xAA, 0xD6, 0x2E, 0xBF, 0xFC, 0x5B, 0x15, 0xA8, 0xD2,
+ 0x26, 0xAF, 0xDC, 0x1B, 0xB4, 0xEA, 0x37, 0xEC, 0x3B, 0xF4, 0x6A, 0x37, 0xCD, 0x18, 0x93, 0x85,
+ 0x69, 0x31, 0xC1, 0xE1, 0x40, 0xE3, 0x25, 0xC8, 0x12, 0x87, 0x8C, 0x9A, 0xB6, 0xCF, 0xFD, 0x59,
+ 0x11, 0xA0, 0xC2, 0x06, 0x8E, 0x7F, 0x5D, 0x38, 0xF2, 0x47, 0x0C, 0x7B, 0x74, 0x6A, 0x37, 0xEC,
+ 0x5A, 0x36, 0xEE, 0x3F, 0xFC, 0x7A, 0x76, 0x4F, 0x1C, 0x9B, 0x95, 0x89, 0x71, 0x41, 0x00, 0x63,
+ 0x44, 0xEB, 0x54, 0x2A, 0xD6, 0x0F, 0x9C, 0xBA, 0xD7, 0x0D, 0x98, 0x93, 0x85, 0x69, 0x31, 0xC1,
+ 0x00, 0x82, 0x86, 0x8E, 0x9E, 0xBE, 0xDF, 0x3C, 0xFA, 0x57, 0x2C, 0xDA, 0x36, 0xEE, 0x3F, 0xFC,
+ 0x5B, 0x15, 0x89, 0x71, 0x41, 0x00, 0x82, 0x86, 0x8E, 0x7F, 0x5D, 0x38, 0xF2, 0x47, 0xED, 0x58,
+ 0x13, 0xA4, 0xCA, 0xF7, 0x4D, 0xF9, 0x51, 0x01, 0x80, 0x63, 0x44, 0xEB, 0x54, 0x2A, 0xD6, 0x2E,
+ 0xBF, 0xDD, 0x19, 0x91, 0xA0, 0xA3, 0xA5, 0xA9, 0xB1, 0xE0, 0x42, 0x06, 0x8E, 0x7F, 0x5D, 0x19,
+ 0x91, 0xA0, 0xA3, 0xC4, 0x0A, 0x96, 0x8F, 0x7D, 0x78, 0x72, 0x47, 0x0C, 0x7B, 0x74, 0x6A, 0x56,
+ 0x2E, 0xDE, 0x1F, 0xBC, 0xFA, 0x57, 0x0D, 0x79, 0x51, 0x01, 0x61, 0x21, 0xA1, 0xC0, 0xE3, 0x25,
+ 0xA9, 0xB1, 0xC1, 0xE1, 0x40, 0x02, 0x67, 0x4C, 0x1A, 0x97, 0x8D, 0x98, 0x93, 0xA4, 0xAB, 0xD4,
+ 0x2A, 0xD6, 0x0F, 0x9C, 0x9B, 0xB4, 0xCB, 0x14, 0xAA, 0xB7, 0xCD, 0xF9, 0x51, 0x20, 0xA3, 0xC4,
+ 0xEB, 0x35, 0xC9, 0xF1, 0x60, 0x42, 0x06, 0x8E, 0x7F, 0x7C, 0x7A, 0x76, 0x6E, 0x3F, 0xFC, 0x7A,
+ 0x76, 0x6E, 0x5E, 0x3E, 0xFE, 0x7E, 0x5F, 0x3C, 0xDB, 0x15, 0x89, 0x71, 0x41, 0xE1, 0x21, 0xC0,
+ 0xE3, 0x44, 0xEB, 0x54, 0x2A, 0xB7, 0xCD, 0xF9, 0x70, 0x62, 0x27, 0xAD, 0xD8, 0x32, 0xC7, 0x0C,
+ 0x7B, 0x74, 0x4B, 0x14, 0xAA, 0xB7, 0xEC, 0x3B, 0xD5, 0x28, 0xD2, 0x07, 0x6D, 0x39, 0xD1, 0x20,
+ 0xC2, 0xE7, 0x4C, 0x1A, 0x97, 0x8D, 0x98, 0xB2, 0xC7, 0x0C, 0x59, 0x28, 0xF3, 0x9B
+};
diff --git a/drivers/sensors/pmw3389_firmware.h b/drivers/sensors/pmw3389_firmware.h
new file mode 100644
index 0000000000..0564dab73a
--- /dev/null
+++ b/drivers/sensors/pmw3389_firmware.h
@@ -0,0 +1,303 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2019 Sunjun Kim
+ * Copyright 2020 Ploopy Corporation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+// PID, Inverse PID, SROM version
+const uint8_t firmware_signature[] PROGMEM = {0x42, 0xBD, 0x04};
+
+// clang-format off
+// Firmware Blob foor PMW3389
+const uint16_t firmware_length = 4094;
+// clang-format off
+const uint8_t firmware_data[] PROGMEM = { // SROM 0x04
+0x01, 0xe8, 0xba, 0x26, 0x0b, 0xb2, 0xbe, 0xfe, 0x7e, 0x5f, 0x3c, 0xdb, 0x15, 0xa8, 0xb3,
+0xe4, 0x2b, 0xb5, 0xe8, 0x53, 0x07, 0x6d, 0x3b, 0xd1, 0x20, 0xc2, 0x06, 0x6f, 0x3d, 0xd9,
+0x11, 0xa0, 0xc2, 0xe7, 0x2d, 0xb9, 0xd1, 0x20, 0xa3, 0xa5, 0xc8, 0xf3, 0x64, 0x4a, 0xf7,
+0x4d, 0x18, 0x93, 0xa4, 0xca, 0xf7, 0x6c, 0x5a, 0x36, 0xee, 0x5e, 0x3e, 0xfe, 0x7e, 0x7e,
+0x5f, 0x1d, 0x99, 0xb0, 0xc3, 0xe5, 0x29, 0xd3, 0x03, 0x65, 0x48, 0x12, 0x87, 0x6d, 0x58,
+0x32, 0xe6, 0x2f, 0xdc, 0x3a, 0xf2, 0x4f, 0xfd, 0x59, 0x11, 0x81, 0x61, 0x21, 0xc0, 0x02,
+0x86, 0x8e, 0x7f, 0x5d, 0x38, 0xf2, 0x47, 0x0c, 0x7b, 0x55, 0x28, 0xb3, 0xe4, 0x4a, 0x16,
+0xab, 0xbf, 0xdd, 0x38, 0xf2, 0x66, 0x4e, 0xff, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xa5, 0xc8,
+0x12, 0xa6, 0xaf, 0xdc, 0x3a, 0xd1, 0x41, 0x60, 0x75, 0x58, 0x24, 0x92, 0xd4, 0x72, 0x6c,
+0xe0, 0x2f, 0xfd, 0x23, 0x8d, 0x1c, 0x5b, 0xb2, 0x97, 0x36, 0x3d, 0x0b, 0xa2, 0x49, 0xb1,
+0x58, 0xf2, 0x1f, 0xc0, 0xcb, 0xf8, 0x41, 0x4f, 0xcd, 0x1e, 0x6b, 0x39, 0xa7, 0x2b, 0xe9,
+0x30, 0x16, 0x83, 0xd2, 0x0e, 0x47, 0x8f, 0xe3, 0xb1, 0xdf, 0xa2, 0x15, 0xdb, 0x5d, 0x30,
+0xc5, 0x1a, 0xab, 0x31, 0x99, 0xf3, 0xfa, 0xb2, 0x86, 0x69, 0xad, 0x7a, 0xe8, 0xa7, 0x18,
+0x6a, 0xcc, 0xc8, 0x65, 0x23, 0x87, 0xa8, 0x5f, 0xf5, 0x21, 0x59, 0x75, 0x09, 0x71, 0x45,
+0x55, 0x25, 0x4b, 0xda, 0xa1, 0xc3, 0xf7, 0x41, 0xab, 0x59, 0xd9, 0x74, 0x12, 0x55, 0x5f,
+0xbc, 0xaf, 0xd9, 0xfd, 0xb0, 0x1e, 0xa3, 0x0f, 0xff, 0xde, 0x11, 0x16, 0x6a, 0xae, 0x0e,
+0xe1, 0x5d, 0x3c, 0x10, 0x43, 0x9a, 0xa1, 0x0b, 0x24, 0x8f, 0x0d, 0x7f, 0x0b, 0x5e, 0x4c,
+0x42, 0xa4, 0x84, 0x2c, 0x40, 0xd0, 0x55, 0x39, 0xe6, 0x4b, 0xf8, 0x9b, 0x2f, 0xdc, 0x28,
+0xff, 0xfa, 0xb5, 0x85, 0x19, 0xe5, 0x28, 0xa1, 0x77, 0xaa, 0x73, 0xf3, 0x03, 0xc7, 0x62,
+0xa6, 0x91, 0x18, 0xc9, 0xb0, 0xcd, 0x05, 0xdc, 0xca, 0x81, 0x26, 0x1a, 0x47, 0x40, 0xda,
+0x36, 0x7d, 0x6a, 0x53, 0xc8, 0x5a, 0x77, 0x5d, 0x19, 0xa4, 0x1b, 0x23, 0x83, 0xd0, 0xb2,
+0xaa, 0x0e, 0xbf, 0x77, 0x4e, 0x3a, 0x3b, 0x59, 0x00, 0x31, 0x0d, 0x02, 0x1b, 0x88, 0x7a,
+0xd4, 0xbd, 0x9d, 0xcc, 0x58, 0x04, 0x69, 0xf6, 0x3b, 0xca, 0x42, 0xe2, 0xfd, 0xc3, 0x3d,
+0x39, 0xc5, 0xd0, 0x71, 0xe4, 0xc8, 0xb7, 0x3e, 0x3f, 0xc8, 0xe9, 0xca, 0xc9, 0x3f, 0x04,
+0x4e, 0x1b, 0x79, 0xca, 0xa5, 0x61, 0xc2, 0xed, 0x1d, 0xa6, 0xda, 0x5a, 0xe9, 0x7f, 0x65,
+0x8c, 0xbe, 0x12, 0x6e, 0xa4, 0x5b, 0x33, 0x2f, 0x84, 0x28, 0x9c, 0x1c, 0x88, 0x2d, 0xff,
+0x07, 0xbf, 0xa6, 0xd7, 0x5a, 0x88, 0x86, 0xb0, 0x3f, 0xf6, 0x31, 0x5b, 0x11, 0x6d, 0xf5,
+0x58, 0xeb, 0x58, 0x02, 0x9e, 0xb5, 0x9a, 0xb1, 0xff, 0x25, 0x9d, 0x8b, 0x4f, 0xb6, 0x0a,
+0xf9, 0xea, 0x3e, 0x3f, 0x21, 0x09, 0x65, 0x21, 0x22, 0xfe, 0x3d, 0x4e, 0x11, 0x5b, 0x9e,
+0x5a, 0x59, 0x8b, 0xdd, 0xd8, 0xce, 0xd6, 0xd9, 0x59, 0xd2, 0x1e, 0xfd, 0xef, 0x0d, 0x1b,
+0xd9, 0x61, 0x7f, 0xd7, 0x2d, 0xad, 0x62, 0x09, 0xe5, 0x22, 0x63, 0xea, 0xc7, 0x31, 0xd9,
+0xa1, 0x38, 0x80, 0x5c, 0xa7, 0x32, 0x82, 0xec, 0x1b, 0xa2, 0x49, 0x5a, 0x06, 0xd2, 0x7c,
+0xc9, 0x96, 0x57, 0xbb, 0x17, 0x75, 0xfc, 0x7a, 0x8f, 0x0d, 0x77, 0xb5, 0x7a, 0x8e, 0x3e,
+0xf4, 0xba, 0x2f, 0x69, 0x13, 0x26, 0xd6, 0xd9, 0x21, 0x60, 0x2f, 0x21, 0x3e, 0x87, 0xee,
+0xfd, 0x87, 0x16, 0x0d, 0xc8, 0x08, 0x00, 0x25, 0x71, 0xac, 0x2c, 0x03, 0x2a, 0x37, 0x2d,
+0xb3, 0x34, 0x09, 0x91, 0xe3, 0x06, 0x2c, 0x38, 0x37, 0x95, 0x3b, 0x17, 0x7a, 0xaf, 0xac,
+0x99, 0x55, 0xab, 0x41, 0x39, 0x5f, 0x8e, 0xa6, 0x43, 0x80, 0x03, 0x88, 0x6f, 0x7d, 0xbd,
+0x5a, 0xb4, 0x2b, 0x32, 0x23, 0x5a, 0xa9, 0x31, 0x32, 0x39, 0x4c, 0x5b, 0xf4, 0x6b, 0xaf,
+0x66, 0x6f, 0x3c, 0x8e, 0x2d, 0x82, 0x97, 0x9f, 0x4a, 0x01, 0xdc, 0x99, 0x98, 0x00, 0xec,
+0x38, 0x7a, 0x79, 0x70, 0xa6, 0x85, 0xd6, 0x21, 0x63, 0x0d, 0x45, 0x9a, 0x2e, 0x5e, 0xa7,
+0xb1, 0xea, 0x66, 0x6a, 0xbc, 0x62, 0x2d, 0x7b, 0x7d, 0x85, 0xea, 0x95, 0x2f, 0xc0, 0xe8,
+0x6f, 0x35, 0xa0, 0x3a, 0x02, 0x25, 0xbc, 0xb2, 0x5f, 0x5c, 0x43, 0x96, 0xcc, 0x26, 0xd2,
+0x16, 0xb4, 0x96, 0x73, 0xd7, 0x13, 0xc7, 0xae, 0x53, 0x15, 0x31, 0x89, 0x68, 0x66, 0x6d,
+0x2c, 0x92, 0x1f, 0xcc, 0x5b, 0xa7, 0x8f, 0x5d, 0xbb, 0xc9, 0xdb, 0xe8, 0x3b, 0x9d, 0x61,
+0x74, 0x8b, 0x05, 0xa1, 0x58, 0x52, 0x68, 0xee, 0x3d, 0x39, 0x79, 0xa0, 0x9b, 0xdd, 0xe1,
+0x55, 0xc9, 0x60, 0xeb, 0xad, 0xb8, 0x5b, 0xc2, 0x5a, 0xb5, 0x2c, 0x18, 0x55, 0xa9, 0x50,
+0xc3, 0xf6, 0x72, 0x5f, 0xcc, 0xe2, 0xf4, 0x55, 0xb5, 0xd6, 0xb5, 0x4a, 0x99, 0xa5, 0x28,
+0x74, 0x97, 0x18, 0xe8, 0xc0, 0x84, 0x89, 0x50, 0x03, 0x86, 0x4d, 0x1a, 0xb7, 0x09, 0x90,
+0xa2, 0x01, 0x04, 0xbb, 0x73, 0x62, 0xcb, 0x97, 0x22, 0x70, 0x5d, 0x52, 0x41, 0x8e, 0xd9,
+0x90, 0x15, 0xaa, 0xab, 0x0a, 0x31, 0x65, 0xb4, 0xda, 0xd0, 0xee, 0x24, 0xc9, 0x41, 0x91,
+0x1e, 0xbc, 0x46, 0x70, 0x40, 0x9d, 0xda, 0x0e, 0x2a, 0xe4, 0xb2, 0x4c, 0x9f, 0xf2, 0xfc,
+0xf3, 0x84, 0x17, 0x44, 0x1e, 0xd7, 0xca, 0x23, 0x1f, 0x3f, 0x5a, 0x22, 0x3d, 0xaf, 0x9b,
+0x2d, 0xfc, 0x41, 0xad, 0x26, 0xb4, 0x45, 0x67, 0x0b, 0x80, 0x0e, 0xf9, 0x61, 0x37, 0xec,
+0x3b, 0xf4, 0x4b, 0x14, 0xdf, 0x5a, 0x0c, 0x3a, 0x50, 0x0b, 0x14, 0x0c, 0x72, 0xae, 0xc6,
+0xc5, 0xec, 0x35, 0x53, 0x2d, 0x59, 0xed, 0x91, 0x74, 0xe2, 0xc4, 0xc8, 0xf2, 0x25, 0x6b,
+0x97, 0x6f, 0xc9, 0x76, 0xce, 0xa9, 0xb1, 0x99, 0x8f, 0x5a, 0x92, 0x3b, 0xc4, 0x8d, 0x54,
+0x50, 0x40, 0x72, 0xd6, 0x90, 0x83, 0xfc, 0xe5, 0x49, 0x8b, 0x17, 0xf5, 0xfd, 0x6b, 0x8d,
+0x32, 0x02, 0xe9, 0x0a, 0xfe, 0xbf, 0x00, 0x6b, 0xa3, 0xad, 0x5f, 0x09, 0x4b, 0x97, 0x2b,
+0x00, 0x58, 0x65, 0x2e, 0x07, 0x49, 0x0a, 0x3b, 0x6b, 0x2e, 0x50, 0x6c, 0x1d, 0xac, 0xb7,
+0x6a, 0x26, 0xd8, 0x13, 0xa4, 0xca, 0x16, 0xae, 0xab, 0x93, 0xb9, 0x1c, 0x1c, 0xb4, 0x47,
+0x6a, 0x38, 0x36, 0x17, 0x27, 0xc9, 0x7f, 0xc7, 0x64, 0xcb, 0x89, 0x58, 0xc5, 0x61, 0xc2,
+0xc6, 0xea, 0x15, 0x0b, 0x34, 0x0c, 0x5d, 0x61, 0x76, 0x6e, 0x2b, 0x62, 0x40, 0x92, 0xa3,
+0x6c, 0xef, 0xf4, 0xe4, 0xc3, 0xa1, 0xa8, 0xf5, 0x94, 0x79, 0x0d, 0xd1, 0x3d, 0xcb, 0x3d,
+0x40, 0xb6, 0xd0, 0xf0, 0x10, 0x54, 0xd8, 0x47, 0x25, 0x51, 0xc5, 0x41, 0x79, 0x00, 0xe5,
+0xa0, 0x72, 0xde, 0xbb, 0x3b, 0x62, 0x17, 0xf6, 0xbc, 0x5d, 0x00, 0x76, 0x2e, 0xa7, 0x3b,
+0xb6, 0xf1, 0x98, 0x72, 0x59, 0x2a, 0x73, 0xb0, 0x21, 0xd6, 0x49, 0xe0, 0xc0, 0xd5, 0xeb,
+0x02, 0x7d, 0x4b, 0x41, 0x28, 0x70, 0x2d, 0xec, 0x2b, 0x71, 0x1f, 0x0b, 0xb9, 0x71, 0x63,
+0x06, 0xe6, 0xbc, 0x60, 0xbb, 0xf4, 0x9a, 0x62, 0x43, 0x09, 0x18, 0x4e, 0x93, 0x06, 0x4d,
+0x76, 0xfa, 0x7f, 0xbd, 0x02, 0xe4, 0x50, 0x91, 0x12, 0xe5, 0x86, 0xff, 0x64, 0x1e, 0xaf,
+0x7e, 0xb3, 0xb2, 0xde, 0x89, 0xc1, 0xa2, 0x6f, 0x40, 0x7b, 0x41, 0x51, 0x63, 0xea, 0x25,
+0xd1, 0x97, 0x57, 0x92, 0xa8, 0x45, 0xa1, 0xa5, 0x45, 0x21, 0x43, 0x7f, 0x83, 0x15, 0x29,
+0xd0, 0x30, 0x53, 0x32, 0xb4, 0x5a, 0x17, 0x96, 0xbc, 0xc2, 0x68, 0xa9, 0xb7, 0xaf, 0xac,
+0xdf, 0xf1, 0xe3, 0x89, 0xba, 0x24, 0x79, 0x54, 0xc6, 0x14, 0x07, 0x1c, 0x1e, 0x0d, 0x3a,
+0x6b, 0xe5, 0x3d, 0x4e, 0x10, 0x60, 0x96, 0xec, 0x6c, 0xda, 0x47, 0xae, 0x03, 0x25, 0x39,
+0x1d, 0x74, 0xc8, 0xac, 0x6a, 0xf2, 0x6b, 0x05, 0x2a, 0x9a, 0xe7, 0xe8, 0x92, 0xd6, 0xc2,
+0x6d, 0xfa, 0xe8, 0xa7, 0x9d, 0x5f, 0x48, 0xc9, 0x75, 0xf1, 0x66, 0x6a, 0xdb, 0x5d, 0x9a,
+0xcd, 0x27, 0xdd, 0xb9, 0x24, 0x04, 0x9c, 0x18, 0xc2, 0x6d, 0x0c, 0x91, 0x34, 0x48, 0x42,
+0x6f, 0xe9, 0x59, 0x70, 0xc4, 0x7e, 0x81, 0x0e, 0x32, 0x0a, 0x93, 0x48, 0xb0, 0xc0, 0x15,
+0x9e, 0x05, 0xac, 0x36, 0x16, 0xcb, 0x59, 0x65, 0xa0, 0x83, 0xdf, 0x3e, 0xda, 0xfb, 0x1d,
+0x1a, 0xdb, 0x65, 0xec, 0x9a, 0xc6, 0xc3, 0x8e, 0x3c, 0x45, 0xfd, 0xc8, 0xf5, 0x1c, 0x6a,
+0x67, 0x0d, 0x8f, 0x99, 0x7d, 0x30, 0x21, 0x8c, 0xea, 0x22, 0x87, 0x65, 0xc9, 0xb2, 0x4c,
+0xe4, 0x1b, 0x46, 0xba, 0x54, 0xbd, 0x7c, 0xca, 0xd5, 0x8f, 0x5b, 0xa5, 0x01, 0x04, 0xd8,
+0x0a, 0x16, 0xbf, 0xb9, 0x50, 0x2e, 0x37, 0x2f, 0x64, 0xf3, 0x70, 0x11, 0x02, 0x05, 0x31,
+0x9b, 0xa0, 0xb2, 0x01, 0x5e, 0x4f, 0x19, 0xc9, 0xd4, 0xea, 0xa1, 0x79, 0x54, 0x53, 0xa7,
+0xde, 0x2f, 0x49, 0xd3, 0xd1, 0x63, 0xb5, 0x03, 0x15, 0x4e, 0xbf, 0x04, 0xb3, 0x26, 0x8b,
+0x20, 0xb2, 0x45, 0xcf, 0xcd, 0x5b, 0x82, 0x32, 0x88, 0x61, 0xa7, 0xa8, 0xb2, 0xa0, 0x72,
+0x96, 0xc0, 0xdb, 0x2b, 0xe2, 0x5f, 0xba, 0xe3, 0xf5, 0x8a, 0xde, 0xf1, 0x18, 0x01, 0x16,
+0x40, 0xd9, 0x86, 0x12, 0x09, 0x18, 0x1b, 0x05, 0x0c, 0xb1, 0xb5, 0x47, 0xe2, 0x43, 0xab,
+0xfe, 0x92, 0x63, 0x7e, 0x95, 0x2b, 0xf0, 0xaf, 0xe1, 0xf1, 0xc3, 0x4a, 0xff, 0x2b, 0x09,
+0xbb, 0x4a, 0x0e, 0x9a, 0xc4, 0xd8, 0x64, 0x7d, 0x83, 0xa0, 0x4f, 0x44, 0xdb, 0xc4, 0xa8,
+0x58, 0xef, 0xfc, 0x9e, 0x77, 0xf9, 0xa6, 0x8f, 0x58, 0x8b, 0x12, 0xf4, 0xe9, 0x81, 0x12,
+0x47, 0x51, 0x41, 0x83, 0xef, 0xf6, 0x73, 0xbc, 0x8e, 0x0f, 0x4c, 0x8f, 0x4e, 0x69, 0x90,
+0x77, 0x29, 0x5d, 0x92, 0xb0, 0x6d, 0x06, 0x67, 0x29, 0x60, 0xbd, 0x4b, 0x17, 0xc8, 0x89,
+0x69, 0x28, 0x29, 0xd6, 0x78, 0xcb, 0x11, 0x4c, 0xba, 0x8b, 0x68, 0xae, 0x7e, 0x9f, 0xef,
+0x95, 0xda, 0xe2, 0x9e, 0x7f, 0xe9, 0x55, 0xe5, 0xe1, 0xe2, 0xb7, 0xe6, 0x5f, 0xbb, 0x2c,
+0xa2, 0xe6, 0xee, 0xc7, 0x0a, 0x60, 0xa9, 0xd1, 0x80, 0xdf, 0x7f, 0xd6, 0x97, 0xab, 0x1d,
+0x22, 0x25, 0xfc, 0x79, 0x23, 0xe0, 0xae, 0xc5, 0xef, 0x16, 0xa4, 0xa1, 0x0f, 0x92, 0xa9,
+0xc7, 0xe3, 0x3a, 0x55, 0xdf, 0x62, 0x49, 0xd9, 0xf5, 0x84, 0x49, 0xc5, 0x90, 0x34, 0xd3,
+0xe1, 0xac, 0x99, 0x21, 0xb1, 0x02, 0x76, 0x4a, 0xfa, 0xd4, 0xbb, 0xa4, 0x9c, 0xa2, 0xe2,
+0xcb, 0x3d, 0x3b, 0x14, 0x75, 0x60, 0xd1, 0x02, 0xb4, 0xa3, 0xb4, 0x72, 0x06, 0xf9, 0x19,
+0x9c, 0xe2, 0xe4, 0xa7, 0x0f, 0x25, 0x88, 0xc6, 0x86, 0xd6, 0x8c, 0x74, 0x4e, 0x6e, 0xfc,
+0xa8, 0x48, 0x9e, 0xa7, 0x9d, 0x1a, 0x4b, 0x37, 0x09, 0xc8, 0xb0, 0x10, 0xbe, 0x6f, 0xfe,
+0xa3, 0xc4, 0x7a, 0xb5, 0x3d, 0xe8, 0x30, 0xf1, 0x0d, 0xa0, 0xb2, 0x44, 0xfc, 0x9b, 0x8c,
+0xf8, 0x61, 0xed, 0x81, 0xd1, 0x62, 0x11, 0xb4, 0xe1, 0xd5, 0x39, 0x52, 0x89, 0xd3, 0xa8,
+0x49, 0x31, 0xdf, 0xb6, 0xf9, 0x91, 0xf4, 0x1c, 0x9d, 0x09, 0x95, 0x40, 0x56, 0xe7, 0xe3,
+0xcd, 0x5c, 0x92, 0xc1, 0x1d, 0x6b, 0xe9, 0x78, 0x6f, 0x8e, 0x94, 0x42, 0x66, 0xa2, 0xaa,
+0xd3, 0xc8, 0x2e, 0xe3, 0xf6, 0x07, 0x72, 0x0b, 0x6b, 0x1e, 0x7b, 0xb9, 0x7c, 0xe0, 0xa0,
+0xbc, 0xd9, 0x25, 0xdf, 0x87, 0xa8, 0x5f, 0x9c, 0xcc, 0xf0, 0xdb, 0x42, 0x8e, 0x07, 0x31,
+0x13, 0x01, 0x66, 0x32, 0xd1, 0xb8, 0xd6, 0xe3, 0x5e, 0x12, 0x76, 0x61, 0xd3, 0x38, 0x89,
+0xe6, 0x17, 0x6f, 0xa5, 0xf2, 0x71, 0x0e, 0xa5, 0xe2, 0x88, 0x30, 0xbb, 0xbe, 0x8a, 0xea,
+0xc7, 0x62, 0xc4, 0xcf, 0xb8, 0xcd, 0x33, 0x8d, 0x3d, 0x3e, 0xb5, 0x60, 0x3a, 0x03, 0x92,
+0xe4, 0x6d, 0x1b, 0xe0, 0xb4, 0x84, 0x08, 0x55, 0x88, 0xa7, 0x3a, 0xb9, 0x3d, 0x43, 0xc3,
+0xc0, 0xfa, 0x07, 0x6a, 0xca, 0x94, 0xad, 0x99, 0x55, 0xf1, 0xf1, 0xc0, 0x23, 0x87, 0x1d,
+0x3d, 0x1c, 0xd1, 0x66, 0xa0, 0x57, 0x10, 0x52, 0xa2, 0x7f, 0xbe, 0xf9, 0x88, 0xb6, 0x02,
+0xbf, 0x08, 0x23, 0xa9, 0x0c, 0x63, 0x17, 0x2a, 0xae, 0xf5, 0xf7, 0xb7, 0x21, 0x83, 0x92,
+0x31, 0x23, 0x0d, 0x20, 0xc3, 0xc2, 0x05, 0x21, 0x62, 0x8e, 0x45, 0xe8, 0x14, 0xc1, 0xda,
+0x75, 0xb8, 0xf8, 0x92, 0x01, 0xd0, 0x5d, 0x18, 0x9f, 0x99, 0x11, 0x19, 0xf5, 0x35, 0xe8,
+0x7f, 0x20, 0x88, 0x8c, 0x05, 0x75, 0xf5, 0xd7, 0x40, 0x17, 0xbb, 0x1e, 0x36, 0x52, 0xd9,
+0xa4, 0x9c, 0xc2, 0x9d, 0x42, 0x81, 0xd8, 0xc7, 0x8a, 0xe7, 0x4c, 0x81, 0xe0, 0xb7, 0x57,
+0xed, 0x48, 0x8b, 0xf0, 0x97, 0x15, 0x61, 0xd9, 0x2c, 0x7c, 0x45, 0xaf, 0xc2, 0xcd, 0xfc,
+0xaa, 0x13, 0xad, 0x59, 0xcc, 0xb2, 0xb2, 0x6e, 0xdd, 0x63, 0x9c, 0x32, 0x0f, 0xec, 0x83,
+0xbe, 0x78, 0xac, 0x91, 0x44, 0x1a, 0x1f, 0xea, 0xfd, 0x5d, 0x8e, 0xb4, 0xc0, 0x84, 0xd4,
+0xac, 0xb4, 0x87, 0x5f, 0xac, 0xef, 0xdf, 0xcd, 0x12, 0x56, 0xc8, 0xcd, 0xfe, 0xc5, 0xda,
+0xd3, 0xc1, 0x69, 0xf3, 0x61, 0x05, 0xea, 0x25, 0xe2, 0x12, 0x05, 0x8f, 0x39, 0x08, 0x08,
+0x7c, 0x37, 0xb6, 0x7e, 0x5b, 0xd8, 0xb1, 0x0e, 0xf2, 0xdb, 0x4b, 0xf1, 0xad, 0x90, 0x01,
+0x57, 0xcd, 0xa0, 0xb4, 0x52, 0xe8, 0xf3, 0xd7, 0x8a, 0xbd, 0x4f, 0x9f, 0x21, 0x40, 0x72,
+0xa4, 0xfc, 0x0b, 0x01, 0x2b, 0x2f, 0xb6, 0x4c, 0x95, 0x2d, 0x35, 0x33, 0x41, 0x6b, 0xa0,
+0x93, 0xe7, 0x2c, 0xf2, 0xd3, 0x72, 0x8b, 0xf4, 0x4f, 0x15, 0x3c, 0xaf, 0xd6, 0x12, 0xde,
+0x3f, 0x83, 0x3f, 0xff, 0xf8, 0x7f, 0xf6, 0xcc, 0xa6, 0x7f, 0xc9, 0x9a, 0x6e, 0x1f, 0xc1,
+0x0c, 0xfb, 0xee, 0x9c, 0xe7, 0xaf, 0xc9, 0x26, 0x54, 0xef, 0xb0, 0x39, 0xef, 0xb2, 0xe9,
+0x23, 0xc4, 0xef, 0xd1, 0xa1, 0xa4, 0x25, 0x24, 0x6f, 0x8d, 0x6a, 0xe5, 0x8a, 0x32, 0x3a,
+0xaf, 0xfc, 0xda, 0xce, 0x18, 0x25, 0x42, 0x07, 0x4d, 0x45, 0x8b, 0xdf, 0x85, 0xcf, 0x55,
+0xb2, 0x24, 0xfe, 0x9c, 0x69, 0x74, 0xa7, 0x6e, 0xa0, 0xce, 0xc0, 0x39, 0xf4, 0x86, 0xc6,
+0x8d, 0xae, 0xb9, 0x48, 0x64, 0x13, 0x0b, 0x40, 0x81, 0xa2, 0xc9, 0xa8, 0x85, 0x51, 0xee,
+0x9f, 0xcf, 0xa2, 0x8c, 0x19, 0x52, 0x48, 0xe2, 0xc1, 0xa8, 0x58, 0xb4, 0x10, 0x24, 0x06,
+0x58, 0x51, 0xfc, 0xb9, 0x12, 0xec, 0xfd, 0x73, 0xb4, 0x6d, 0x84, 0xfa, 0x06, 0x8b, 0x05,
+0x0b, 0x2d, 0xd6, 0xd6, 0x1f, 0x29, 0x82, 0x9f, 0x19, 0x12, 0x1e, 0xb2, 0x04, 0x8f, 0x7f,
+0x4d, 0xbd, 0x30, 0x2e, 0xe3, 0xe0, 0x88, 0x29, 0xc5, 0x93, 0xd6, 0x6c, 0x1f, 0x29, 0x45,
+0x91, 0xa7, 0x58, 0xcd, 0x05, 0x17, 0xd6, 0x6d, 0xb3, 0xca, 0x66, 0xcc, 0x3c, 0x4a, 0x74,
+0xfd, 0x08, 0x10, 0xa6, 0x99, 0x92, 0x10, 0xd2, 0x85, 0xab, 0x6e, 0x1d, 0x0e, 0x8b, 0x26,
+0x46, 0xd1, 0x6c, 0x84, 0xc0, 0x26, 0x43, 0x59, 0x68, 0xf0, 0x13, 0x1d, 0xfb, 0xe3, 0xd1,
+0xd2, 0xb4, 0x71, 0x9e, 0xf2, 0x59, 0x6a, 0x33, 0x29, 0x79, 0xd2, 0xd7, 0x26, 0xf1, 0xae,
+0x78, 0x9e, 0x1f, 0x0f, 0x3f, 0xe3, 0xe8, 0xd0, 0x27, 0x78, 0x77, 0xf6, 0xac, 0x9c, 0x56,
+0x39, 0x73, 0x8a, 0x6b, 0x2f, 0x34, 0x78, 0xb1, 0x11, 0xdb, 0xa4, 0x5c, 0x80, 0x01, 0x71,
+0x6a, 0xc2, 0xd1, 0x2e, 0x5e, 0x76, 0x28, 0x70, 0x93, 0xae, 0x3e, 0x78, 0xb0, 0x1f, 0x0f,
+0xda, 0xbf, 0xfb, 0x8a, 0x67, 0x65, 0x4f, 0x91, 0xed, 0x49, 0x75, 0x78, 0x62, 0xa2, 0x93,
+0xb5, 0x70, 0x7f, 0x4d, 0x08, 0x4e, 0x79, 0x61, 0xa8, 0x5f, 0x7f, 0xb4, 0x65, 0x9f, 0x91,
+0x54, 0x3a, 0xe8, 0x50, 0x33, 0xd3, 0xd5, 0x8a, 0x7c, 0xf3, 0x9e, 0x8b, 0x77, 0x7b, 0xc6,
+0xc6, 0x0c, 0x45, 0x95, 0x1f, 0xb0, 0xd0, 0x0b, 0x27, 0x4a, 0xfd, 0xc7, 0xf7, 0x0d, 0x5a,
+0x43, 0xc9, 0x7d, 0x35, 0xb0, 0x7d, 0xc4, 0x9c, 0x57, 0x1e, 0x76, 0x0d, 0xf1, 0x95, 0x30,
+0x71, 0xcc, 0xb3, 0x66, 0x3b, 0x63, 0xa8, 0x6c, 0xa3, 0x43, 0xa0, 0x24, 0xcc, 0xb7, 0x53,
+0xfe, 0xfe, 0xbc, 0x6e, 0x60, 0x89, 0xaf, 0x16, 0x21, 0xc8, 0x91, 0x6a, 0x89, 0xce, 0x80,
+0x2c, 0xf1, 0x59, 0xce, 0xc3, 0x60, 0x61, 0x3b, 0x0b, 0x19, 0xfe, 0x99, 0xac, 0x65, 0x90,
+0x15, 0x12, 0x05, 0xac, 0x7e, 0xff, 0x98, 0x7b, 0x66, 0x64, 0x0e, 0x4b, 0x5b, 0xaa, 0x8d,
+0x3b, 0xd2, 0x56, 0xcf, 0x99, 0x39, 0xee, 0x22, 0x81, 0xd0, 0x60, 0x06, 0x66, 0x20, 0x81,
+0x48, 0x3c, 0x6f, 0x3a, 0x77, 0xba, 0xcb, 0x52, 0xac, 0x79, 0x56, 0xaf, 0xe9, 0x16, 0x17,
+0x0a, 0xa3, 0x82, 0x08, 0xd5, 0x3c, 0x97, 0xcb, 0x09, 0xff, 0x7f, 0xf9, 0x4f, 0x60, 0x05,
+0xb9, 0x53, 0x26, 0xaa, 0xb8, 0x50, 0xaa, 0x19, 0x25, 0xae, 0x5f, 0xea, 0x8a, 0xd0, 0x89,
+0x12, 0x80, 0x43, 0x50, 0x24, 0x12, 0x21, 0x14, 0xcd, 0x77, 0xeb, 0x21, 0xcc, 0x5c, 0x09,
+0x64, 0xf3, 0xc7, 0xcb, 0xc5, 0x4b, 0xc3, 0xe7, 0xed, 0xe7, 0x86, 0x2c, 0x1d, 0x8e, 0x19,
+0x52, 0x9b, 0x2a, 0x0c, 0x18, 0x72, 0x0b, 0x1e, 0x1b, 0xb0, 0x0f, 0x42, 0x99, 0x04, 0xae,
+0xd5, 0xb7, 0x89, 0x1a, 0xb9, 0x4f, 0xd6, 0xaf, 0xf3, 0xc9, 0x93, 0x6f, 0xb0, 0x60, 0x83,
+0x6e, 0x6b, 0xd1, 0x5f, 0x3f, 0x1a, 0x83, 0x1e, 0x24, 0x00, 0x87, 0xb5, 0x3e, 0xdb, 0xf9,
+0x4d, 0xa7, 0x16, 0x2e, 0x19, 0x5b, 0x8f, 0x1b, 0x0d, 0x47, 0x72, 0x42, 0xe9, 0x0a, 0x11,
+0x08, 0x2d, 0x88, 0x1c, 0xbc, 0xc7, 0xb4, 0xbe, 0x29, 0x4d, 0x03, 0x5e, 0xec, 0xdf, 0xf3,
+0x3d, 0x2f, 0xe8, 0x1d, 0x9a, 0xd2, 0xd1, 0xab, 0x41, 0x3d, 0x87, 0x11, 0x45, 0xb0, 0x0d,
+0x46, 0xf5, 0xe8, 0x95, 0x62, 0x1c, 0x68, 0xf7, 0xa6, 0x5b, 0x39, 0x4e, 0xbf, 0x47, 0xba,
+0x5d, 0x7f, 0xb7, 0x6a, 0xf4, 0xba, 0x1d, 0x69, 0xf6, 0xa4, 0xe7, 0xe4, 0x6b, 0x3b, 0x0d,
+0x23, 0x16, 0x4a, 0xb2, 0x68, 0xf0, 0xb2, 0x0d, 0x09, 0x17, 0x6a, 0x63, 0x8c, 0x83, 0xd3,
+0xbd, 0x05, 0xc9, 0xf6, 0xf0, 0xa1, 0x31, 0x0b, 0x2c, 0xac, 0x83, 0xac, 0x80, 0x34, 0x32,
+0xb4, 0xec, 0xd0, 0xbc, 0x54, 0x82, 0x9a, 0xc8, 0xf6, 0xa0, 0x7d, 0xc6, 0x79, 0x73, 0xf4,
+0x20, 0x99, 0xf3, 0xb4, 0x01, 0xde, 0x91, 0x27, 0xf2, 0xc0, 0xdc, 0x81, 0x00, 0x4e, 0x7e,
+0x07, 0x99, 0xc8, 0x3a, 0x51, 0xbc, 0x38, 0xd6, 0x8a, 0xa2, 0xde, 0x3b, 0x6a, 0x8c, 0x1a,
+0x7c, 0x81, 0x0f, 0x3a, 0x1f, 0xe4, 0x05, 0x7b, 0x20, 0x35, 0x6b, 0xa5, 0x6a, 0xa7, 0xe7,
+0xbc, 0x9c, 0x20, 0xec, 0x00, 0x15, 0xe2, 0x51, 0xaf, 0x77, 0xeb, 0x29, 0x3c, 0x7d, 0x2e,
+0x00, 0x5c, 0x81, 0x21, 0xfa, 0x35, 0x6f, 0x40, 0xef, 0xfb, 0xd1, 0x3f, 0xcc, 0x9d, 0x55,
+0x53, 0xfb, 0x5a, 0xa5, 0x56, 0x89, 0x0b, 0x52, 0xeb, 0x57, 0x73, 0x4f, 0x1b, 0x67, 0x24,
+0xcb, 0xb8, 0x6a, 0x10, 0x69, 0xd6, 0xfb, 0x52, 0x40, 0xff, 0x20, 0xa5, 0xf3, 0x72, 0xe1,
+0x3d, 0xa4, 0x8c, 0x81, 0x66, 0x16, 0x0d, 0x5d, 0xad, 0xa8, 0x50, 0x25, 0x78, 0x31, 0x77,
+0x0c, 0x57, 0xe4, 0xe9, 0x15, 0x2d, 0xdb, 0x07, 0x87, 0xc8, 0xb0, 0x43, 0xde, 0xfc, 0xfe,
+0xa9, 0xeb, 0xf5, 0xb0, 0xd3, 0x7b, 0xe9, 0x1f, 0x6e, 0xca, 0xe4, 0x03, 0x95, 0xc5, 0xd1,
+0x59, 0x72, 0x63, 0xf0, 0x86, 0x54, 0xe8, 0x16, 0x62, 0x0b, 0x35, 0x29, 0xc2, 0x68, 0xd0,
+0xd6, 0x3e, 0x90, 0x60, 0x57, 0x1d, 0xc9, 0xed, 0x3f, 0xed, 0xb0, 0x2f, 0x7e, 0x97, 0x02,
+0x51, 0xec, 0xee, 0x6f, 0x82, 0x74, 0x76, 0x7f, 0xfb, 0xd6, 0xc4, 0xc3, 0xdd, 0xe8, 0xb1,
+0x60, 0xfc, 0xc6, 0xb9, 0x0d, 0x6a, 0x33, 0x78, 0xc6, 0xc1, 0xbf, 0x86, 0x2c, 0x50, 0xcc,
+0x9a, 0x70, 0x8e, 0x7b, 0xec, 0xab, 0x95, 0xac, 0x53, 0xa0, 0x4b, 0x07, 0x88, 0xaf, 0x42,
+0xed, 0x19, 0x8d, 0xf6, 0x32, 0x17, 0x48, 0x47, 0x1d, 0x41, 0x6f, 0xfe, 0x2e, 0xa7, 0x8f,
+0x4b, 0xa0, 0x51, 0xf3, 0xbf, 0x02, 0x0a, 0x48, 0x58, 0xf7, 0xa1, 0x6d, 0xea, 0xa5, 0x13,
+0x5a, 0x5b, 0xea, 0x0c, 0x9e, 0x52, 0x4f, 0x9e, 0xb9, 0x71, 0x7f, 0x23, 0x83, 0xda, 0x1b,
+0x86, 0x9a, 0x41, 0x29, 0xda, 0x70, 0xe7, 0x64, 0xa1, 0x7b, 0xd5, 0x0a, 0x22, 0x0d, 0x5c,
+0x40, 0xc4, 0x81, 0x07, 0x25, 0x35, 0x4a, 0x1c, 0x10, 0xdb, 0x45, 0x0a, 0xff, 0x36, 0xd4,
+0xe0, 0xeb, 0x5f, 0x68, 0xd6, 0x67, 0xc6, 0xd0, 0x8b, 0x76, 0x1a, 0x7d, 0x59, 0x42, 0xa1,
+0xcb, 0x96, 0x4d, 0x84, 0x09, 0x9a, 0x3d, 0xe0, 0x52, 0x85, 0x6e, 0x48, 0x90, 0x85, 0x2a,
+0x63, 0xb2, 0x69, 0xd2, 0x00, 0x43, 0x31, 0x37, 0xb3, 0x52, 0xaf, 0x62, 0xfa, 0xc1, 0xe0,
+0x03, 0xfb, 0x62, 0xaa, 0x88, 0xc9, 0xb2, 0x2c, 0xd5, 0xa8, 0xf5, 0xa5, 0x4c, 0x12, 0x59,
+0x4e, 0x06, 0x5e, 0x9b, 0x15, 0x66, 0x11, 0xb2, 0x27, 0x92, 0xdc, 0x98, 0x59, 0xde, 0xdf,
+0xfa, 0x9a, 0x32, 0x2e, 0xc0, 0x5d, 0x3c, 0x33, 0x41, 0x6d, 0xaf, 0xb2, 0x25, 0x23, 0x14,
+0xa5, 0x7b, 0xc7, 0x9b, 0x68, 0xf3, 0xda, 0xeb, 0xe3, 0xa9, 0xe2, 0x6f, 0x0e, 0x1d, 0x1c,
+0xba, 0x55, 0xb6, 0x34, 0x6a, 0x93, 0x1f, 0x1f, 0xb8, 0x34, 0xc8, 0x84, 0x08, 0xb1, 0x6b,
+0x6a, 0x28, 0x74, 0x74, 0xe5, 0xeb, 0x75, 0xe9, 0x7c, 0xd8, 0xba, 0xd8, 0x42, 0xa5, 0xee,
+0x1f, 0x80, 0xd9, 0x96, 0xb2, 0x2e, 0xe7, 0xbf, 0xba, 0xeb, 0xd1, 0x69, 0xbb, 0x8f, 0xfd,
+0x5a, 0x63, 0x8f, 0x39, 0x7f, 0xdf, 0x1d, 0x37, 0xd2, 0x18, 0x35, 0x9d, 0xb6, 0xcc, 0xe4,
+0x27, 0x81, 0x89, 0x38, 0x38, 0x68, 0x33, 0xe7, 0x78, 0xd8, 0x76, 0xf5, 0xee, 0xd0, 0x4a,
+0x07, 0x69, 0x19, 0x7a, 0xad, 0x18, 0xb1, 0x94, 0x61, 0x45, 0x53, 0xa2, 0x48, 0xda, 0x96,
+0x4a, 0xf9, 0xee, 0x94, 0x2a, 0x1f, 0x6e, 0x18, 0x3c, 0x92, 0x46, 0xd1, 0x1a, 0x28, 0x18,
+0x32, 0x1f, 0x3a, 0x45, 0xbe, 0x04, 0x35, 0x92, 0xe5, 0xa3, 0xcb, 0xb5, 0x2e, 0x32, 0x43,
+0xac, 0x65, 0x17, 0x89, 0x99, 0x15, 0x03, 0x9e, 0xb1, 0x23, 0x2f, 0xed, 0x76, 0x4d, 0xd8,
+0xac, 0x21, 0x40, 0xc4, 0x99, 0x4e, 0x65, 0x71, 0x2c, 0xb3, 0x45, 0xab, 0xfb, 0xe7, 0x72,
+0x39, 0x56, 0x30, 0x6d, 0xfb, 0x74, 0xeb, 0x99, 0xf3, 0xcd, 0x57, 0x5c, 0x78, 0x75, 0xe9,
+0x8d, 0xc3, 0xa2, 0xfb, 0x5d, 0xe0, 0x90, 0xc5, 0x55, 0xad, 0x91, 0x53, 0x4e, 0x9e, 0xbd,
+0x8c, 0x49, 0xa4, 0xa4, 0x69, 0x10, 0x0c, 0xc5, 0x76, 0xe9, 0x25, 0x86, 0x8d, 0x66, 0x23,
+0xa8, 0xdb, 0x5c, 0xe8, 0xd9, 0x30, 0xe1, 0x15, 0x7b, 0xc0, 0x99, 0x0f, 0x03, 0xec, 0xaa,
+0x12, 0xef, 0xce, 0xd4, 0xea, 0x55, 0x5c, 0x08, 0x86, 0xf4, 0xf4, 0xb0, 0x83, 0x42, 0x95,
+0x37, 0xb6, 0x38, 0xe0, 0x2b, 0x54, 0x89, 0xbd, 0x4e, 0x20, 0x9d, 0x3f, 0xc3, 0x4b, 0xb7,
+0xec, 0xfa, 0x5a, 0x14, 0x03, 0xcb, 0x64, 0xc8, 0x34, 0x4a, 0x4b, 0x6e, 0xf8, 0x6e, 0x56,
+0xf6, 0xdd, 0x5f, 0xa1, 0x24, 0xe2, 0xd4, 0xd0, 0x82, 0x64, 0x1f, 0x8e, 0x9b, 0xfa, 0xb4,
+0xcb, 0xdb, 0x0a, 0xe8, 0x15, 0xfc, 0x15, 0xab, 0x4b, 0x18, 0xbf, 0xd4, 0x42, 0x14, 0x48,
+0x82, 0x85, 0xdd, 0xeb, 0x49, 0x1b, 0x0b, 0x0b, 0x05, 0xe9, 0xb4, 0xa1, 0x33, 0x0a, 0x5d,
+0x0e, 0x6c, 0x4b, 0xc0, 0xd6, 0x6c, 0x7c, 0xfb, 0x69, 0x0b, 0x53, 0x19, 0xe4, 0xf3, 0x35,
+0xfc, 0xbe, 0xa1, 0x34, 0x02, 0x09, 0x4f, 0x74, 0x86, 0x92, 0xcd, 0x5d, 0x1a, 0xc1, 0x27,
+0x0c, 0xf2, 0xc5, 0xcf, 0xdd, 0x23, 0x93, 0x02, 0xbd, 0x41, 0x5e, 0x42, 0xf0, 0xa0, 0x9d,
+0x0c, 0x72, 0xc8, 0xec, 0x32, 0x0a, 0x8a, 0xfd, 0x3d, 0x5a, 0x41, 0x27, 0x0c, 0x88, 0x59,
+0xad, 0x94, 0x2e, 0xef, 0x5d, 0x8f, 0xc7, 0xdf, 0x66, 0xe4, 0xdd, 0x56, 0x6c, 0x7b, 0xca,
+0x55, 0x81, 0xae, 0xae, 0x5c, 0x1b, 0x1a, 0xab, 0xae, 0x99, 0x8d, 0xcc, 0x42, 0x97, 0x59,
+0xf4, 0x14, 0x3f, 0x75, 0xc6, 0xd1, 0x88, 0xba, 0xaa, 0x84, 0x4a, 0xd0, 0x34, 0x08, 0x3b,
+0x7d, 0xdb, 0x15, 0x06, 0xb0, 0x5c, 0xbd, 0x40, 0xf5, 0xa8, 0xec, 0xae, 0x36, 0x40, 0xdd,
+0x90, 0x1c, 0x3e, 0x0d, 0x7e, 0x73, 0xc7, 0xc2, 0xc5, 0x6a, 0xff, 0x52, 0x05, 0x7f, 0xbe,
+0xd0, 0x92, 0xfd, 0xb3, 0x6f, 0xff, 0x5d, 0xb7, 0x97, 0x64, 0x73, 0x7b, 0xca, 0xd1, 0x98,
+0x24, 0x6b, 0x0b, 0x01, 0x68, 0xdd, 0x27, 0x85, 0x85, 0xb5, 0x83, 0xc1, 0xe0, 0x50, 0x64,
+0xc7, 0xaf, 0xf1, 0xc6, 0x4d, 0xb1, 0xef, 0xc9, 0xb4, 0x0a, 0x6d, 0x65, 0xf3, 0x47, 0xcc,
+0xa3, 0x02, 0x21, 0x0c, 0xbe, 0x22, 0x29, 0x05, 0xcf, 0x5f, 0xe8, 0x94, 0x6c, 0xe5, 0xdc,
+0xc4, 0xdf, 0xbe, 0x3e, 0xa8, 0xb4, 0x18, 0xb0, 0x99, 0xb8, 0x6f, 0xff, 0x5d, 0xb9, 0xfd,
+0x3b, 0x5d, 0x16, 0xbf, 0x3e, 0xd8, 0xb3, 0xd8, 0x08, 0x34, 0xf6, 0x47, 0x35, 0x5b, 0x72,
+0x1a, 0x33, 0xad, 0x52, 0x5d, 0xb8, 0xd0, 0x77, 0xc6, 0xab, 0xba, 0x55, 0x09, 0x5f, 0x02,
+0xf8, 0xd4, 0x5f, 0x53, 0x06, 0x91, 0xcd, 0x74, 0x42, 0xae, 0x54, 0x91, 0x81, 0x62, 0x13,
+0x6f, 0xd8, 0xa9, 0x77, 0xc3, 0x6c, 0xcb, 0xf1, 0x29, 0x5a, 0xcc, 0xda, 0x35, 0xbd, 0x52,
+0x23, 0xbe, 0x59, 0xeb, 0x12, 0x6d, 0xb7, 0x53, 0xee, 0xfc, 0xb4, 0x1b, 0x13, 0x5e, 0xba,
+0x16, 0x7c, 0xc5, 0xf3, 0xe3, 0x6d, 0x07, 0x78, 0xf5, 0x2b, 0x21, 0x05, 0x88, 0x4c, 0xc0,
+0xa1, 0xe3, 0x36, 0x10, 0xf8, 0x1b, 0xd8, 0x17, 0xfb, 0x6a, 0x4e, 0xd8, 0xb3, 0x47, 0x2d,
+0x99, 0xbd, 0xbb, 0x5d, 0x37, 0x7d, 0xba, 0xf1, 0xe1, 0x7c, 0xc0, 0xc5, 0x54, 0x62, 0x7f,
+0xcf, 0x5a, 0x4a, 0x93, 0xcc, 0xf1, 0x1b, 0x34, 0xc8, 0xa6, 0x05, 0x4c, 0x55, 0x8b, 0x54,
+0x84, 0xd5, 0x77, 0xeb, 0xc0, 0x6d, 0x3a, 0x29, 0xbd, 0x75, 0x61, 0x09, 0x9a, 0x2c, 0xbb,
+0xf7, 0x18, 0x79, 0x34, 0x90, 0x24, 0xa5, 0x81, 0x70, 0x87, 0xc5, 0x02, 0x7c, 0xba, 0xd4,
+0x5e, 0x14, 0x8e, 0xe4, 0xed, 0xa2, 0x61, 0x6a, 0xb9, 0x6e, 0xb5, 0x4a, 0xb9, 0x01, 0x46,
+0xf4, 0xcf, 0xbc, 0x09, 0x2f, 0x27, 0x4b, 0xbd, 0x86, 0x7a, 0x10, 0xe1, 0xd4, 0xc8, 0xd9,
+0x20, 0x8d, 0x8a, 0x63, 0x00, 0x63, 0x44, 0xeb, 0x54, 0x0b, 0x75, 0x49, 0x10, 0xa2, 0xa7,
+0xad, 0xb9, 0xd1, 0x01, 0x80, 0x63, 0x25, 0xc8, 0x12, 0xa6, 0xce, 0x1e, 0xbe, 0xfe, 0x7e,
+0x5f, 0x3c, 0xdb, 0x34, 0xea, 0x37, 0xec, 0x3b, 0xd5, 0x28, 0xd2, 0x07, 0x8c, 0x9a, 0xb6,
+0xee, 0x5e, 0x3e, 0xdf, 0x1d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x5c, 0x1b, 0xb4, 0xea, 0x56,
+0x2e, 0xde, 0x1f, 0x9d, 0xb8, 0xd3, 0x24, 0xab, 0xd4, 0x2a, 0xd6, 0x2e, 0xde, 0x1f, 0x9d,
+0xb8, 0xf2, 0x66, 0x2f, 0xbd, 0xf8, 0x72, 0x66, 0x4e, 0x1e, 0x9f, 0x9d, 0xb8, 0xf2, 0x47,
+0x0c, 0x9a, 0xb6, 0xee, 0x3f, 0xfc, 0x7a, 0x57, 0x0d, 0x79, 0x70, 0x62, 0x27, 0xad, 0xb9,
+0xd1, 0x01, 0x61, 0x40, 0x02, 0x67, 0x2d, 0xd8, 0x32, 0xe6, 0x2f, 0xdc, 0x3a, 0xd7, 0x2c,
+0xbb, 0xf4, 0x4b, 0xf5, 0x49, 0xf1, 0x60, 0x23, 0xc4, 0x0a, 0x77, 0x4d, 0xf9, 0x51, 0x01,
+0x80, 0x63, 0x25, 0xa9, 0xb1, 0xe0, 0x42, 0xe7, 0x4c, 0x1a, 0x97, 0xac, 0xbb, 0xf4, 0x6a,
+0x37, 0xcd, 0x18, 0xb2, 0xe6, 0x2f, 0xdc, 0x1b, 0x95, 0xa8, 0xd2, 0x07, 0x6d, 0x58, 0x32,
+0xe6, 0x4e, 0x1e, 0x9f, 0xbc, 0xfa, 0x57, 0x0d, 0x79, 0x51, 0x20, 0xc2, 0x06, 0x6f, 0x5c,
+0x1b, 0x95, 0xa8, 0xb3, 0xc5, 0xe9, 0x31, 0xe0, 0x23, 0xc4, 0x0a, 0x77, 0x4d, 0x18, 0x93,
+0x85, 0x69, 0x31, 0xc1, 0xe1, 0x21, 0xc0, 0xe3, 0x44, 0x0a, 0x77, 0x6c, 0x5a, 0x17, 0x8d,
+0x98, 0x93, 0xa4, 0xab, 0xd4, 0x2a, 0xb7, 0xec, 0x5a, 0x17, 0xac, 0xbb, 0xf4, 0x4b, 0x14,
+0xaa, 0xb7, 0xec, 0x3b, 0xd5, 0x28, 0xb3, 0xc5, 0xe9, 0x31, 0xc1, 0x00, 0x82, 0x67, 0x4c,
+0xfb, 0x55, 0x28, 0xd2, 0x26, 0xaf, 0xbd, 0xd9, 0x11, 0x81, 0x61, 0x21, 0xa1, 0xa1, 0xc0,
+0x02, 0x86, 0x6f, 0x5c, 0x1b, 0xb4, 0xcb, 0x14, 0x8b, 0x94, 0xaa, 0xd6, 0x2e, 0xbf, 0xdd,
+0x19, 0xb0, 0xe2, 0x46, 0x0e, 0x7f, 0x7c, 0x5b, 0x15, 0x89, 0x90, 0x83, 0x84, 0x6b, 0x54,
+0x0b, 0x75, 0x68, 0x52, 0x07, 0x6d, 0x58, 0x32, 0xc7, 0xed, 0x58, 0x32, 0xc7, 0xed, 0x58,
+0x32, 0xe6, 0x4e, 0xff, 0x7c, 0x7a, 0x76, 0x6e, 0x3f, 0xdd, 0x38, 0xd3, 0x05, 0x88, 0x92,
+0xa6, 0xaf, 0xdc, 0x1b, 0xb4, 0xcb, 0xf5, 0x68, 0x52, 0x07, 0x8c, 0x7b, 0x55, 0x09, 0x90,
+0x83, 0x84, 0x6b, 0x54, 0x2a, 0xb7, 0xec, 0x3b, 0xd5, 0x09, 0x90, 0xa2, 0xc6, 0x0e, 0x7f,
+0x7c, 0x7a, 0x57, 0x0d, 0x98, 0xb2, 0xc7, 0xed, 0x58, 0x32, 0xc7, 0x0c, 0x7b, 0x74, 0x4b,
+0x14, 0x8b, 0x94, 0xaa, 0xb7, 0xcd, 0x18, 0x93, 0xa4, 0xca, 0x16, 0xae, 0xbf, 0xdd, 0x19,
+0xb0, 0xe2, 0x46, 0x0e, 0x7f, 0x5d, 0x19, 0x91, 0x81, 0x80, 0x63, 0x44, 0xeb, 0x35, 0xc9,
+0x10, 0x83, 0x65, 0x48, 0x12, 0xa6, 0xce, 0x1e, 0x9f, 0xbc, 0xdb, 0x15, 0x89, 0x71, 0x60,
+0x23, 0xc4, 0xeb, 0x54, 0x2a, 0xb7, 0xec, 0x5a, 0x36, 0xcf, 0x81, 0x10, 0xac, 0x74 };
+
+// clang-format off
diff --git a/drivers/ugfx/gdisp/is31fl3731c/board_is31fl3731c_template.h b/drivers/ugfx/gdisp/is31fl3731c/board_is31fl3731c_template.h
deleted file mode 100644
index 0755ddf6c4..0000000000
--- a/drivers/ugfx/gdisp/is31fl3731c/board_is31fl3731c_template.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-Copyright 2016 Fred Sundvik <fsundvik@gmail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-static const I2CConfig i2ccfg = {
- 400000 // clock speed (Hz); 400kHz max for IS31
-};
-
-static const uint8_t led_mask[] = {
- 0xFF, 0x00, /* C1-1 -> C1-16 */
- 0xFF, 0x00, /* C2-1 -> C2-16 */
- 0xFF, 0x00, /* C3-1 -> C3-16 */
- 0xFF, 0x00, /* C4-1 -> C4-16 */
- 0x3F, 0x00, /* C5-1 -> C5-16 */
- 0x00, 0x00, /* C6-1 -> C6-16 */
- 0x00, 0x00, /* C7-1 -> C7-16 */
- 0x00, 0x00, /* C8-1 -> C8-16 */
- 0x00, 0x00, /* C9-1 -> C9-16 */
-};
-
-// The address of the LED
-#define LA(c, r) (c + r * 16)
-// Need to be an address that is not mapped, but inside the range of the controller matrix
-#define NA LA(8, 8)
-
-// The numbers in the comments are the led numbers DXX on the PCB
-// The mapping is taken from the schematic of left hand side
-static const uint8_t led_mapping[GDISP_SCREEN_HEIGHT][GDISP_SCREEN_WIDTH] = {
- // 45 44 43 42 41 40 39
- {LA(1, 1), LA(1, 0), LA(0, 4), LA(0, 3), LA(0, 2), LA(0, 1), LA(0, 0)},
- // 52 51 50 49 48 47 46
- {LA(2, 3), LA(2, 2), LA(2, 1), LA(2, 0), LA(1, 4), LA(1, 3), LA(1, 2)},
- // 58 57 56 55 54 53 N/A
- {LA(3, 4), LA(3, 3), LA(3, 2), LA(3, 1), LA(3, 0), LA(2, 4), NA},
- // 67 66 65 64 63 62 61
- {LA(5, 3), LA(5, 2), LA(5, 1), LA(5, 0), LA(4, 4), LA(4, 3), LA(4, 2)},
- // 76 75 74 73 72 60 59
- {LA(7, 3), LA(7, 2), LA(7, 1), LA(7, 0), LA(6, 3), LA(4, 1), LA(4, 0)},
- // N/A N/A N/A N/A N/A N/A 68
- {NA, NA, NA, NA, NA, NA, LA(5, 4)},
- // N/A N/A N/A N/A 71 70 69
- {NA, NA, NA, NA, LA(6, 2), LA(6, 1), LA(6, 0)},
-};
-
-#define IS31_ADDR_DEFAULT 0x74 // AD connected to GND
-#define IS31_TIMEOUT 5000
-
-static GFXINLINE void init_board(GDisplay* g) {
- (void)g;
- /* I2C pins */
- palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATIVE_2); // PTB0/I2C0/SCL
- palSetPadMode(GPIOB, 1, PAL_MODE_ALTERNATIVE_2); // PTB1/I2C0/SDA
- palSetPadMode(GPIOB, 16, PAL_MODE_OUTPUT_PUSHPULL);
- palClearPad(GPIOB, 16);
- /* start I2C */
- i2cStart(&I2CD1, &i2ccfg);
- // try high drive (from kiibohd)
- I2CD1.i2c->C2 |= I2Cx_C2_HDRS;
- // try glitch fixing (from kiibohd)
- I2CD1.i2c->FLT = 4;
-}
-
-static GFXINLINE void post_init_board(GDisplay* g) { (void)g; }
-
-static GFXINLINE const uint8_t* get_led_mask(GDisplay* g) {
- (void)g;
- return led_mask;
-}
-
-static GFXINLINE uint8_t get_led_address(GDisplay* g, uint16_t x, uint16_t y) {
- (void)g;
- return led_mapping[y][x];
-}
-
-static GFXINLINE void set_hardware_shutdown(GDisplay* g, bool shutdown) {
- (void)g;
- if (!shutdown) {
- palSetPad(GPIOB, 16);
- } else {
- palClearPad(GPIOB, 16);
- }
-}
-
-static GFXINLINE void write_data(GDisplay* g, uint8_t* data, uint16_t length) {
- (void)g;
- i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, data, length, 0, 0, US2ST(IS31_TIMEOUT));
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/ugfx/gdisp/is31fl3731c/driver.mk b/drivers/ugfx/gdisp/is31fl3731c/driver.mk
deleted file mode 100644
index a53131bf33..0000000000
--- a/drivers/ugfx/gdisp/is31fl3731c/driver.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-GFXINC += drivers/ugfx/gdisp/is31fl3731c
-GFXSRC += drivers/ugfx/gdisp/is31fl3731c/gdisp_is31fl3731c.c
-GDISP_DRIVER_LIST += GDISPVMT_IS31FL3731C_QMK
diff --git a/drivers/ugfx/gdisp/is31fl3731c/gdisp_is31fl3731c.c b/drivers/ugfx/gdisp/is31fl3731c/gdisp_is31fl3731c.c
deleted file mode 100644
index 7188244022..0000000000
--- a/drivers/ugfx/gdisp/is31fl3731c/gdisp_is31fl3731c.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
-Copyright 2016 Fred Sundvik <fsundvik@gmail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-# define GDISP_DRIVER_VMT GDISPVMT_IS31FL3731C_QMK
-# define GDISP_SCREEN_HEIGHT LED_HEIGHT
-# define GDISP_SCREEN_WIDTH LED_WIDTH
-
-# include "gdisp_lld_config.h"
-# include "src/gdisp/gdisp_driver.h"
-
-# include "board_is31fl3731c.h"
-
-// Can't include led_tables from here
-extern const uint8_t CIE1931_CURVE[];
-
-/*===========================================================================*/
-/* Driver local definitions. */
-/*===========================================================================*/
-
-# ifndef GDISP_INITIAL_CONTRAST
-# define GDISP_INITIAL_CONTRAST 0
-# endif
-# ifndef GDISP_INITIAL_BACKLIGHT
-# define GDISP_INITIAL_BACKLIGHT 0
-# endif
-
-# define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER << 0)
-
-# define IS31_ADDR_DEFAULT 0x74
-
-# define IS31_REG_CONFIG 0x00
-// bits in reg
-# define IS31_REG_CONFIG_PICTUREMODE 0x00
-# define IS31_REG_CONFIG_AUTOPLAYMODE 0x08
-# define IS31_REG_CONFIG_AUDIOPLAYMODE 0x18
-// D2:D0 bits are starting frame for autoplay mode
-
-# define IS31_REG_PICTDISP 0x01 // D2:D0 frame select for picture mode
-
-# define IS31_REG_AUTOPLAYCTRL1 0x02
-// D6:D4 number of loops (000=infty)
-// D2:D0 number of frames to be used
-
-# define IS31_REG_AUTOPLAYCTRL2 0x03 // D5:D0 delay time (*11ms)
-
-# define IS31_REG_DISPLAYOPT 0x05
-# define IS31_REG_DISPLAYOPT_INTENSITY_SAME 0x20 // same intensity for all frames
-# define IS31_REG_DISPLAYOPT_BLINK_ENABLE 0x8
-// D2:D0 bits blink period time (*0.27s)
-
-# define IS31_REG_AUDIOSYNC 0x06
-# define IS31_REG_AUDIOSYNC_ENABLE 0x1
-
-# define IS31_REG_FRAMESTATE 0x07
-
-# define IS31_REG_BREATHCTRL1 0x08
-// D6:D4 fade out time (26ms*2^i)
-// D2:D0 fade in time (26ms*2^i)
-
-# define IS31_REG_BREATHCTRL2 0x09
-# define IS31_REG_BREATHCTRL2_ENABLE 0x10
-// D2:D0 extinguish time (3.5ms*2^i)
-
-# define IS31_REG_SHUTDOWN 0x0A
-# define IS31_REG_SHUTDOWN_OFF 0x0
-# define IS31_REG_SHUTDOWN_ON 0x1
-
-# define IS31_REG_AGCCTRL 0x0B
-# define IS31_REG_ADCRATE 0x0C
-
-# define IS31_COMMANDREGISTER 0xFD
-# define IS31_FUNCTIONREG 0x0B // helpfully called 'page nine'
-# define IS31_FUNCTIONREG_SIZE 0xD
-
-# define IS31_FRAME_SIZE 0xB4
-
-# define IS31_PWM_REG 0x24
-# define IS31_PWM_SIZE 0x90
-
-# define IS31_LED_MASK_SIZE 0x12
-
-# define IS31
-
-/*===========================================================================*/
-/* Driver local functions. */
-/*===========================================================================*/
-
-typedef struct {
- uint8_t write_buffer_offset;
- uint8_t write_buffer[IS31_FRAME_SIZE];
- uint8_t frame_buffer[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH];
- uint8_t page;
-} __attribute__((__packed__)) PrivData;
-
-// Some common routines and macros
-# define PRIV(g) ((PrivData *)g->priv)
-
-/*===========================================================================*/
-/* Driver exported functions. */
-/*===========================================================================*/
-
-static GFXINLINE void write_page(GDisplay *g, uint8_t page) {
- uint8_t tx[2] __attribute__((aligned(2)));
- tx[0] = IS31_COMMANDREGISTER;
- tx[1] = page;
- write_data(g, tx, 2);
-}
-
-static GFXINLINE void write_register(GDisplay *g, uint8_t page, uint8_t reg, uint8_t data) {
- uint8_t tx[2] __attribute__((aligned(2)));
- tx[0] = reg;
- tx[1] = data;
- write_page(g, page);
- write_data(g, tx, 2);
-}
-
-static GFXINLINE void write_ram(GDisplay *g, uint8_t page, uint16_t offset, uint16_t length) {
- PRIV(g)->write_buffer_offset = offset;
- write_page(g, page);
- write_data(g, (uint8_t *)PRIV(g), length + 1);
-}
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
- // The private area is the display surface.
- g->priv = gfxAlloc(sizeof(PrivData));
- __builtin_memset(PRIV(g), 0, sizeof(PrivData));
- PRIV(g)->page = 0;
-
- // Initialise the board interface
- init_board(g);
- gfxSleepMilliseconds(10);
-
- // zero function page, all registers (assuming full_page is all zeroes)
- write_ram(g, IS31_FUNCTIONREG, 0, IS31_FUNCTIONREG_SIZE);
- set_hardware_shutdown(g, false);
- gfxSleepMilliseconds(10);
- // software shutdown
- write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF);
- gfxSleepMilliseconds(10);
- // zero function page, all registers
- write_ram(g, IS31_FUNCTIONREG, 0, IS31_FUNCTIONREG_SIZE);
- gfxSleepMilliseconds(10);
-
- // zero all LED registers on all 8 pages, and enable the mask
- __builtin_memcpy(PRIV(g)->write_buffer, get_led_mask(g), IS31_LED_MASK_SIZE);
- for (uint8_t i = 0; i < 8; i++) {
- write_ram(g, i, 0, IS31_FRAME_SIZE);
- gfxSleepMilliseconds(1);
- }
-
- // software shutdown disable (i.e. turn stuff on)
- write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF);
- gfxSleepMilliseconds(10);
-
- // Finish Init
- post_init_board(g);
-
- /* Initialise the GDISP structure */
- g->g.Width = GDISP_SCREEN_WIDTH;
- g->g.Height = GDISP_SCREEN_HEIGHT;
- g->g.Orientation = GDISP_ROTATE_0;
- g->g.Powermode = powerOff;
- g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
- g->g.Contrast = GDISP_INITIAL_CONTRAST;
- return TRUE;
-}
-
-# if GDISP_HARDWARE_FLUSH
-LLDSPEC void gdisp_lld_flush(GDisplay *g) {
- // Don't flush if we don't need it.
- if (!(g->flags & GDISP_FLG_NEEDFLUSH)) return;
-
- PRIV(g)->page++;
- PRIV(g)->page %= 2;
- // TODO: some smarter algorithm for this
- // We should run only one physical page at a time
- // This way we don't need to send so much data, and
- // we could use slightly less memory
- uint8_t *src = PRIV(g)->frame_buffer;
- for (int y = 0; y < GDISP_SCREEN_HEIGHT; y++) {
- for (int x = 0; x < GDISP_SCREEN_WIDTH; x++) {
- uint8_t val = (uint16_t)*src * g->g.Backlight / 100;
- PRIV(g)->write_buffer[get_led_address(g, x, y)] = CIE1931_CURVE[val];
- ++src;
- }
- }
- write_ram(g, PRIV(g)->page, IS31_PWM_REG, IS31_PWM_SIZE);
- gfxSleepMilliseconds(1);
- write_register(g, IS31_FUNCTIONREG, IS31_REG_PICTDISP, PRIV(g)->page);
-
- g->flags &= ~GDISP_FLG_NEEDFLUSH;
-}
-# endif
-
-# if GDISP_HARDWARE_DRAWPIXEL
-LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
- coord_t x, y;
-
- switch (g->g.Orientation) {
- default:
- case GDISP_ROTATE_0:
- x = g->p.x;
- y = g->p.y;
- break;
- case GDISP_ROTATE_180:
- x = GDISP_SCREEN_WIDTH - 1 - g->p.x;
- y = g->p.y;
- break;
- }
- PRIV(g)->frame_buffer[y * GDISP_SCREEN_WIDTH + x] = gdispColor2Native(g->p.color);
- g->flags |= GDISP_FLG_NEEDFLUSH;
-}
-# endif
-
-# if GDISP_HARDWARE_PIXELREAD
-LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
- coord_t x, y;
-
- switch (g->g.Orientation) {
- default:
- case GDISP_ROTATE_0:
- x = g->p.x;
- y = g->p.y;
- break;
- case GDISP_ROTATE_180:
- x = GDISP_SCREEN_WIDTH - 1 - g->p.x;
- y = g->p.y;
- break;
- }
- return gdispNative2Color(PRIV(g)->frame_buffer[y * GDISP_SCREEN_WIDTH + x]);
-}
-# endif
-
-# if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-LLDSPEC void gdisp_lld_control(GDisplay *g) {
- switch (g->p.x) {
- case GDISP_CONTROL_POWER:
- if (g->g.Powermode == (powermode_t)g->p.ptr) return;
- switch ((powermode_t)g->p.ptr) {
- case powerOff:
- case powerSleep:
- case powerDeepSleep:
- write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF);
- break;
- case powerOn:
- write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON);
- break;
- default:
- return;
- }
- g->g.Powermode = (powermode_t)g->p.ptr;
- return;
-
- case GDISP_CONTROL_ORIENTATION:
- if (g->g.Orientation == (orientation_t)g->p.ptr) return;
- switch ((orientation_t)g->p.ptr) {
- /* Rotation is handled by the drawing routines */
- case GDISP_ROTATE_0:
- case GDISP_ROTATE_180:
- g->g.Height = GDISP_SCREEN_HEIGHT;
- g->g.Width = GDISP_SCREEN_WIDTH;
- break;
- case GDISP_ROTATE_90:
- case GDISP_ROTATE_270:
- g->g.Height = GDISP_SCREEN_WIDTH;
- g->g.Width = GDISP_SCREEN_HEIGHT;
- break;
- default:
- return;
- }
- g->g.Orientation = (orientation_t)g->p.ptr;
- return;
-
- case GDISP_CONTROL_BACKLIGHT:
- if (g->g.Backlight == (unsigned)g->p.ptr) return;
- unsigned val = (unsigned)g->p.ptr;
- g->g.Backlight = val > 100 ? 100 : val;
- g->flags |= GDISP_FLG_NEEDFLUSH;
- return;
- }
-}
-# endif // GDISP_NEED_CONTROL
-
-#endif // GFX_USE_GDISP
diff --git a/drivers/ugfx/gdisp/is31fl3731c/gdisp_lld_config.h b/drivers/ugfx/gdisp/is31fl3731c/gdisp_lld_config.h
deleted file mode 100644
index 403c6b0409..0000000000
--- a/drivers/ugfx/gdisp/is31fl3731c/gdisp_lld_config.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Copyright 2016 Fred Sundvik <fsundvik@gmail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _GDISP_LLD_CONFIG_H
-#define _GDISP_LLD_CONFIG_H
-
-#if GFX_USE_GDISP
-
-/*===========================================================================*/
-/* Driver hardware support. */
-/*===========================================================================*/
-
-# define GDISP_HARDWARE_FLUSH GFXON // This controller requires flushing
-# define GDISP_HARDWARE_DRAWPIXEL GFXON
-# define GDISP_HARDWARE_PIXELREAD GFXON
-# define GDISP_HARDWARE_CONTROL GFXON
-
-# define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_GRAY256
-
-#endif /* GFX_USE_GDISP */
-
-#endif /* _GDISP_LLD_CONFIG_H */
diff --git a/drivers/ugfx/gdisp/st7565/board_st7565_template.h b/drivers/ugfx/gdisp/st7565/board_st7565_template.h
deleted file mode 100644
index 875ed9e65c..0000000000
--- a/drivers/ugfx/gdisp/st7565/board_st7565_template.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-#include "quantum.h"
-
-#define ST7565_LCD_BIAS ST7565_LCD_BIAS_7
-#define ST7565_COM_SCAN ST7565_COM_SCAN_DEC
-#define ST7565_PAGE_ORDER 0, 1, 2, 3
-/*
- * Custom page order for several LCD boards, e.g. HEM12864-99
- * #define ST7565_PAGE_ORDER 4,5,6,7,0,1,2,3
- */
-
-#define ST7565_A0_PIN C7
-#define ST7565_RST_PIN C8
-#define ST7565_MOSI_PIN C6
-#define ST7565_SCLK_PIN C5
-#define ST7565_SS_PIN C4
-
-// DSPI Clock and Transfer Attributes
-// Frame Size: 8 bits
-// MSB First
-// CLK Low by default
-static const SPIConfig spi1config = {
- // Operation complete callback or @p NULL.
- .end_cb = NULL,
- // The chip select line port - when not using pcs.
- .ssport = PAL_PORT(ST7565_SS_PIN),
- // brief The chip select line pad number - when not using pcs.
- .sspad = PAL_PAD(ST7565_SS_PIN),
- // SPI initialization data.
- .tar0 = SPIx_CTARn_FMSZ(7) // Frame size = 8 bytes
- | SPIx_CTARn_ASC(1) // After SCK Delay Scaler (min 50 ns) = 55.56ns
- | SPIx_CTARn_DT(0) // Delay After Transfer Scaler (no minimum)= 27.78ns
- | SPIx_CTARn_CSSCK(0) // PCS to SCK Delay Scaler (min 20 ns) = 27.78ns
- | SPIx_CTARn_PBR(0) // Baud Rate Prescaler = 2
- | SPIx_CTARn_BR(0) // Baud rate (min 50ns) = 55.56ns
-};
-
-static GFXINLINE void acquire_bus(GDisplay *g) {
- (void)g;
- // Only the LCD is using the SPI bus, so no need to acquire
- // spiAcquireBus(&SPID1);
- spiSelect(&SPID1);
-}
-
-static GFXINLINE void release_bus(GDisplay *g) {
- (void)g;
- // Only the LCD is using the SPI bus, so no need to release
- // spiReleaseBus(&SPID1);
- spiUnselect(&SPID1);
-}
-
-static GFXINLINE void init_board(GDisplay *g) {
- (void)g;
- setPinOutput(ST7565_A0_PIN);
- writePinHigh(ST7565_A0_PIN);
- setPinOutput(ST7565_RST_PIN);
- writePinHigh(ST7565_RST_PIN);
- setPinOutput(ST7565_SS_PIN);
-
- palSetPadMode(PAL_PORT(ST7565_MOSI_PIN), PAL_PAD(ST7565_MOSI_PIN), PAL_MODE_ALTERNATIVE_2);
- palSetPadMode(PAL_PORT(ST7565_SCLK_PIN), PAL_PAD(ST7565_SCLK_PIN), PAL_MODE_ALTERNATIVE_2);
-
- spiInit();
- spiStart(&SPID1, &spi1config);
- release_bus(g);
-}
-
-static GFXINLINE void post_init_board(GDisplay *g) { (void)g; }
-
-static GFXINLINE void setpin_reset(GDisplay *g, bool_t state) {
- (void)g;
- writePin(ST7565_RST_PIN, !state);
-}
-
-static GFXINLINE void write_cmd(GDisplay *g, gU8 cmd) {
- (void)g;
- writePinLow(ST7565_A0_PIN);
- spiSend(&SPID1, 1, &cmd);
-}
-
-static GFXINLINE void write_data(GDisplay *g, gU8 *data, gU16 length) {
- (void)g;
- writePinHigh(ST7565_A0_PIN);
- spiSend(&SPID1, length, data);
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/ugfx/gdisp/st7565/driver.mk b/drivers/ugfx/gdisp/st7565/driver.mk
deleted file mode 100644
index 799a986b0a..0000000000
--- a/drivers/ugfx/gdisp/st7565/driver.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-GFXINC += drivers/ugfx/gdisp/st7565
-GFXSRC += drivers/ugfx/gdisp/st7565/gdisp_lld_ST7565.c
-GDISP_DRIVER_LIST += GDISPVMT_ST7565_QMK
diff --git a/drivers/ugfx/gdisp/st7565/gdisp_lld_ST7565.c b/drivers/ugfx/gdisp/st7565/gdisp_lld_ST7565.c
deleted file mode 100644
index f586f97e38..0000000000
--- a/drivers/ugfx/gdisp/st7565/gdisp_lld_ST7565.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-# define GDISP_DRIVER_VMT GDISPVMT_ST7565_QMK
-# include "gdisp_lld_config.h"
-# include "src/gdisp/gdisp_driver.h"
-
-# include "board_st7565.h"
-
-/*===========================================================================*/
-/* Driver local definitions. */
-/*===========================================================================*/
-
-# ifndef GDISP_SCREEN_HEIGHT
-# define GDISP_SCREEN_HEIGHT LCD_HEIGHT
-# endif
-# ifndef GDISP_SCREEN_WIDTH
-# define GDISP_SCREEN_WIDTH LCD_WIDTH
-# endif
-# ifndef GDISP_INITIAL_CONTRAST
-# define GDISP_INITIAL_CONTRAST 35
-# endif
-# ifndef GDISP_INITIAL_BACKLIGHT
-# define GDISP_INITIAL_BACKLIGHT 100
-# endif
-
-# define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER << 0)
-
-# include "st7565.h"
-
-/*===========================================================================*/
-/* Driver config defaults for backward compatibility. */
-/*===========================================================================*/
-# ifndef ST7565_LCD_BIAS
-# define ST7565_LCD_BIAS ST7565_LCD_BIAS_7
-# endif
-# ifndef ST7565_ADC
-# define ST7565_ADC ST7565_ADC_NORMAL
-# endif
-# ifndef ST7565_COM_SCAN
-# define ST7565_COM_SCAN ST7565_COM_SCAN_INC
-# endif
-# ifndef ST7565_PAGE_ORDER
-# define ST7565_PAGE_ORDER 0, 1, 2, 3, 4, 5, 6, 7
-# endif
-
-/*===========================================================================*/
-/* Driver local functions. */
-/*===========================================================================*/
-
-// Some common routines and macros
-# define RAM(g) ((gU8 *)g->priv)
-# define write_cmd2(g, cmd1, cmd2) \
- { \
- write_cmd(g, cmd1); \
- write_cmd(g, cmd2); \
- }
-# define write_cmd3(g, cmd1, cmd2, cmd3) \
- { \
- write_cmd(g, cmd1); \
- write_cmd(g, cmd2); \
- write_cmd(g, cmd3); \
- }
-
-// Some common routines and macros
-# define delay(us) gfxSleepMicroseconds(us)
-# define delay_ms(ms) gfxSleepMilliseconds(ms)
-
-# define xyaddr(x, y) ((x) + ((y) >> 3) * GDISP_SCREEN_WIDTH)
-# define xybit(y) (1 << ((y)&7))
-
-/*===========================================================================*/
-/* Driver exported functions. */
-/*===========================================================================*/
-
-/*
- * As this controller can't update on a pixel boundary we need to maintain the
- * the entire display surface in memory so that we can do the necessary bit
- * operations. Fortunately it is a small display in monochrome.
- * 64 * 128 / 8 = 1024 bytes.
- */
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
- // The private area is the display surface.
- g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8);
- if (!g->priv) {
- return gFalse;
- }
-
- // Initialise the board interface
- init_board(g);
-
- // Hardware reset
- setpin_reset(g, TRUE);
- gfxSleepMilliseconds(20);
- setpin_reset(g, FALSE);
- gfxSleepMilliseconds(20);
- acquire_bus(g);
-
- write_cmd(g, ST7565_LCD_BIAS);
- write_cmd(g, ST7565_ADC);
- write_cmd(g, ST7565_COM_SCAN);
-
- write_cmd(g, ST7565_START_LINE | 0);
-
- write_cmd2(g, ST7565_CONTRAST, GDISP_INITIAL_CONTRAST * 64 / 101);
- write_cmd(g, ST7565_RESISTOR_RATIO | 0x1);
-
- // turn on voltage converter (VC=1, VR=0, VF=0)
- write_cmd(g, ST7565_POWER_CONTROL | 0x04);
- delay_ms(50);
-
- // turn on voltage regulator (VC=1, VR=1, VF=0)
- write_cmd(g, ST7565_POWER_CONTROL | 0x06);
- delay_ms(50);
-
- // turn on voltage follower (VC=1, VR=1, VF=1)
- write_cmd(g, ST7565_POWER_CONTROL | 0x07);
- delay_ms(50);
-
- write_cmd(g, ST7565_DISPLAY_ON);
- write_cmd(g, ST7565_ALLON_NORMAL);
- write_cmd(g, ST7565_INVERT_DISPLAY); // Disable Inversion of display.
-
- write_cmd(g, ST7565_RMW);
-
- // Finish Init
- post_init_board(g);
-
- // Release the bus
- release_bus(g);
-
- /* Initialise the GDISP structure */
- g->g.Width = GDISP_SCREEN_WIDTH;
- g->g.Height = GDISP_SCREEN_HEIGHT;
- g->g.Orientation = GDISP_ROTATE_0;
- g->g.Powermode = powerOff;
- g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
- g->g.Contrast = GDISP_INITIAL_CONTRAST;
- return TRUE;
-}
-
-# if GDISP_HARDWARE_FLUSH
-LLDSPEC void gdisp_lld_flush(GDisplay *g) {
- unsigned p;
-
- // Don't flush if we don't need it.
- if (!(g->flags & GDISP_FLG_NEEDFLUSH)) return;
-
- acquire_bus(g);
- gU8 pagemap[] = {ST7565_PAGE_ORDER};
- for (p = 0; p < sizeof(pagemap); p++) {
- write_cmd(g, ST7565_PAGE | pagemap[p]);
- write_cmd(g, ST7565_COLUMN_MSB | 0);
- write_cmd(g, ST7565_COLUMN_LSB | 0);
- write_cmd(g, ST7565_RMW);
- write_data(g, RAM(g) + (p * GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH);
- }
- release_bus(g);
-
- g->flags &= ~GDISP_FLG_NEEDFLUSH;
-}
-# endif
-
-# if GDISP_HARDWARE_DRAWPIXEL
-LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
- coord_t x, y;
-
- switch (g->g.Orientation) {
- default:
- case GDISP_ROTATE_0:
- x = g->p.x;
- y = g->p.y;
- break;
- case GDISP_ROTATE_90:
- x = g->p.y;
- y = GDISP_SCREEN_HEIGHT - 1 - g->p.x;
- break;
- case GDISP_ROTATE_180:
- x = GDISP_SCREEN_WIDTH - 1 - g->p.x;
- y = GDISP_SCREEN_HEIGHT - 1 - g->p.y;
- break;
- case GDISP_ROTATE_270:
- x = GDISP_SCREEN_HEIGHT - 1 - g->p.y;
- y = g->p.x;
- break;
- }
- if (gdispColor2Native(g->p.color) != Black)
- RAM(g)[xyaddr(x, y)] |= xybit(y);
- else
- RAM(g)[xyaddr(x, y)] &= ~xybit(y);
- g->flags |= GDISP_FLG_NEEDFLUSH;
-}
-# endif
-
-# if GDISP_HARDWARE_PIXELREAD
-LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
- coord_t x, y;
-
- switch (g->g.Orientation) {
- default:
- case GDISP_ROTATE_0:
- x = g->p.x;
- y = g->p.y;
- break;
- case GDISP_ROTATE_90:
- x = g->p.y;
- y = GDISP_SCREEN_HEIGHT - 1 - g->p.x;
- break;
- case GDISP_ROTATE_180:
- x = GDISP_SCREEN_WIDTH - 1 - g->p.x;
- y = GDISP_SCREEN_HEIGHT - 1 - g->p.y;
- break;
- case GDISP_ROTATE_270:
- x = GDISP_SCREEN_HEIGHT - 1 - g->p.y;
- y = g->p.x;
- break;
- }
- return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
-}
-# endif
-
-# if GDISP_HARDWARE_BITFILLS
-LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
- uint8_t *buffer = (uint8_t *)g->p.ptr;
- int linelength = g->p.cx;
- for (int i = 0; i < g->p.cy; i++) {
- unsigned dstx = g->p.x;
- unsigned dsty = g->p.y + i;
- unsigned srcx = g->p.x1;
- unsigned srcy = g->p.y1 + i;
- unsigned srcbit = srcy * g->p.x2 + srcx;
- for (int j = 0; j < linelength; j++) {
- uint8_t src = buffer[srcbit / 8];
- uint8_t bit = 7 - (srcbit % 8);
- uint8_t bitset = (src >> bit) & 1;
- uint8_t *dst = &(RAM(g)[xyaddr(dstx, dsty)]);
- if (bitset) {
- *dst |= xybit(dsty);
- } else {
- *dst &= ~xybit(dsty);
- }
- dstx++;
- srcbit++;
- }
- }
- g->flags |= GDISP_FLG_NEEDFLUSH;
-}
-# endif
-
-# if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-LLDSPEC void gdisp_lld_control(GDisplay *g) {
- switch (g->p.x) {
- case GDISP_CONTROL_POWER:
- if (g->g.Powermode == (powermode_t)g->p.ptr) return;
- switch ((powermode_t)g->p.ptr) {
- case powerOff:
- case powerSleep:
- case powerDeepSleep:
- acquire_bus(g);
- write_cmd(g, ST7565_DISPLAY_OFF);
- release_bus(g);
- break;
- case powerOn:
- acquire_bus(g);
- write_cmd(g, ST7565_DISPLAY_ON);
- release_bus(g);
- break;
- default:
- return;
- }
- g->g.Powermode = (powermode_t)g->p.ptr;
- return;
-
- case GDISP_CONTROL_ORIENTATION:
- if (g->g.Orientation == (orientation_t)g->p.ptr) return;
- switch ((orientation_t)g->p.ptr) {
- /* Rotation is handled by the drawing routines */
- case GDISP_ROTATE_0:
- case GDISP_ROTATE_180:
- g->g.Height = GDISP_SCREEN_HEIGHT;
- g->g.Width = GDISP_SCREEN_WIDTH;
- break;
- case GDISP_ROTATE_90:
- case GDISP_ROTATE_270:
- g->g.Height = GDISP_SCREEN_WIDTH;
- g->g.Width = GDISP_SCREEN_HEIGHT;
- break;
- default:
- return;
- }
- g->g.Orientation = (orientation_t)g->p.ptr;
- return;
-
- case GDISP_CONTROL_CONTRAST:
- if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
- acquire_bus(g);
- write_cmd2(g, ST7565_CONTRAST, ((((unsigned)g->p.ptr) << 6) / 101) & 0x3F);
- release_bus(g);
- g->g.Contrast = (unsigned)g->p.ptr;
- return;
- }
-}
-# endif // GDISP_NEED_CONTROL
-
-#endif // GFX_USE_GDISP
diff --git a/drivers/ugfx/gdisp/st7565/gdisp_lld_config.h b/drivers/ugfx/gdisp/st7565/gdisp_lld_config.h
deleted file mode 100644
index 6052058ec2..0000000000
--- a/drivers/ugfx/gdisp/st7565/gdisp_lld_config.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-#ifndef _GDISP_LLD_CONFIG_H
-#define _GDISP_LLD_CONFIG_H
-
-#if GFX_USE_GDISP
-
-/*===========================================================================*/
-/* Driver hardware support. */
-/*===========================================================================*/
-
-# define GDISP_HARDWARE_FLUSH GFXON // This controller requires flushing
-# define GDISP_HARDWARE_DRAWPIXEL GFXON
-# define GDISP_HARDWARE_PIXELREAD GFXON
-# define GDISP_HARDWARE_CONTROL GFXON
-# define GDISP_HARDWARE_BITFILLS GFXON
-
-# define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_MONO
-
-#endif /* GFX_USE_GDISP */
-
-#endif /* _GDISP_LLD_CONFIG_H */
diff --git a/drivers/ugfx/gdisp/st7565/st7565.h b/drivers/ugfx/gdisp/st7565/st7565.h
deleted file mode 100644
index 3c77a88569..0000000000
--- a/drivers/ugfx/gdisp/st7565/st7565.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://ugfx.org/license.html
- */
-
-#ifndef _ST7565_H
-#define _ST7565_H
-
-#define ST7565_CONTRAST 0x81
-#define ST7565_ALLON_NORMAL 0xA4
-#define ST7565_ALLON 0xA5
-#define ST7565_POSITIVE_DISPLAY 0xA6
-#define ST7565_INVERT_DISPLAY 0xA7
-#define ST7565_DISPLAY_OFF 0xAE
-#define ST7565_DISPLAY_ON 0xAF
-
-#define ST7565_LCD_BIAS_7 0xA3
-#define ST7565_LCD_BIAS_9 0xA2
-
-#define ST7565_ADC_NORMAL 0xA0
-#define ST7565_ADC_REVERSE 0xA1
-
-#define ST7565_COM_SCAN_INC 0xC0
-#define ST7565_COM_SCAN_DEC 0xC8
-
-#define ST7565_START_LINE 0x40
-#define ST7565_PAGE 0xB0
-#define ST7565_COLUMN_MSB 0x10
-#define ST7565_COLUMN_LSB 0x00
-#define ST7565_RMW 0xE0
-
-#define ST7565_RESISTOR_RATIO 0x20
-#define ST7565_POWER_CONTROL 0x28
-
-#define ST7565_RESET 0xE2
-
-#endif /* _ST7565_H */
diff --git a/tmk_core/protocol/arm_atsam/usb/usb2422.h b/drivers/usb2422.c
index b4830b5bc8..62b919093b 100644
--- a/tmk_core/protocol/arm_atsam/usb/usb2422.h
+++ b/drivers/usb2422.c
@@ -1,32 +1,25 @@
-/*
-Copyright 2018 Massdrop Inc.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _USB2422_H_
-#define _USB2422_H_
-
-#define REV_USB2422 0x100
-
-#define USB2422_ADDR 0x58 // I2C device address, one instance
-
-#define USB2422_HUB_ACTIVE_GROUP 0 // PA
-#define USB2422_HUB_ACTIVE_PIN 18 // 18
+/* Copyright 2021 QMK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <string.h>
+#include "usb2422.h"
+#include "i2c_master.h"
+#include "wait.h"
+#include "gpio.h"
/* -------- USB2422_VID : (USB2422L Offset: 0x00) (R/W 16) Vendor ID -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint16_t VID_LSB : 8;
@@ -34,10 +27,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} USB2422_VID_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PID : (USB2422L Offset: 0x02) (R/W 16) Product ID -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint16_t PID_LSB : 8;
@@ -45,10 +36,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} USB2422_PID_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_DID : (USB2422L Offset: 0x04) (R/W 16) Device ID -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint16_t DID_LSB : 8;
@@ -56,10 +45,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint16_t reg; /*!< Type used for register access */
} USB2422_DID_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_CFG1 : (USB2422L Offset: 0x06) (R/W 8) Configuration Data Byte 1-------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t PORT_PWR : 1;
@@ -72,10 +59,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_CFG1_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_CFG2 : (USB2422L Offset: 0x07) (R/W 8) Configuration Data Byte 2-------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 3;
@@ -86,10 +71,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_CFG2_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_CFG3 : (USB2422L Offset: 0x08) (R/W 16) Configuration Data Byte 3-------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t STRING_EN : 1;
@@ -99,10 +82,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_CFG3_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_NRD : (USB2422L Offset: 0x09) (R/W 8) Non Removable Device -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 5;
@@ -112,10 +93,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_NRD_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PDS : (USB2422L Offset: 0x0A) (R/W 8) Port Diable for Self-Powered Operation -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 1;
@@ -125,10 +104,9 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PDS_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PDB : (USB2422L Offset: 0x0B) (R/W 8) Port Diable for Bus-Powered Operation -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
+
typedef union {
struct {
uint8_t : 1;
@@ -138,125 +116,98 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PDB_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_MAXPS : (USB2422L Offset: 0x0C) (R/W 8) Max Power for Self-Powered Operation -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t MAX_PWR_SP : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_MAXPS_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_MAXPB : (USB2422L Offset: 0x0D) (R/W 8) Max Power for Bus-Powered Operation -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t MAX_PWR_BP : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_MAXPB_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_HCMCS : (USB2422L Offset: 0x0E) (R/W 8) Hub Controller Max Current for Self-Powered Operation -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t HC_MAX_C_SP : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_HCMCS_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_HCMCB : (USB2422L Offset: 0x0F) (R/W 8) Hub Controller Max Current for Bus-Powered Operation -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t HC_MAX_C_BP : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_HCMCB_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PWRT : (USB2422L Offset: 0x10) (R/W 8) Power On Time -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t POWER_ON_TIME : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PWRT_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_LANGID LSB : (USB2422L Offset: 0x11) (R/W 16) Language ID -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t LANGID_LSB : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_LANGID_LSB_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_LANGID MSB : (USB2422L Offset: 0x12) (R/W 16) Language ID -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t LANGID_MSB : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_LANGID_MSB_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_MFRSL : (USB2422L Offset: 0x13) (R/W 8) Manufacturer String Length -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t MFR_STR_LEN : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_MFRSL_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PRDSL : (USB2422L Offset: 0x14) (R/W 8) Product String Length -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t PRD_STR_LEN : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PRDSL_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_SERSL : (USB2422L Offset: 0x15) (R/W 8) Serial String Length -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t SER_STR_LEN : 8;
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_SERSL_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_MFRSTR : (USB2422L Offset: 0x16-53) (R/W 8) Maufacturer String -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef uint16_t USB2422_MFRSTR_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PRDSTR : (USB2422L Offset: 0x54-91) (R/W 8) Product String -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef uint16_t USB2422_PRDSTR_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_SERSTR : (USB2422L Offset: 0x92-CF) (R/W 8) Serial String -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef uint16_t USB2422_SERSTR_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_BCEN : (USB2422L Offset: 0xD0) (R/W 8) Battery Charging Enable -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
+
typedef union {
struct {
uint8_t : 1;
@@ -266,10 +217,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_BCEN_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_BOOSTUP : (USB2422L Offset: 0xF6) (R/W 8) Boost Upstream -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t BOOST : 2;
@@ -277,10 +226,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_BOOSTUP_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_BOOSTDOWN : (USB2422L Offset: 0xF8) (R/W 8) Boost Downstream -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t BOOST1 : 2;
@@ -289,10 +236,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_BOOSTDOWN_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PRTSP : (USB2422L Offset: 0xFA) (R/W 8) Port Swap -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t : 1;
@@ -302,10 +247,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PRTSP_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/* -------- USB2422_PRTR12 : (USB2422L Offset: 0xFB) (R/W 8) Port 1/2 Remap -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t PORT1_REMAP : 4;
@@ -313,7 +256,7 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_PRTR12_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
+
#define USB2422_PRTR12_DISABLE 0
#define USB2422_PRT12_P2TOL1 1
#define USB2422_PRT12_P2XTOL2 2
@@ -321,7 +264,6 @@ typedef union {
#define USB2422_PRT12_P1XTOL2 2
/* -------- USB2422_STCD : (USB2422L Offset: 0xFF) (R/W 8) Status Command -------- */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef union {
struct {
uint8_t USB_ATTACH : 1;
@@ -331,10 +273,8 @@ typedef union {
} bit; /*!< Structure used for bit access */
uint8_t reg; /*!< Type used for register access */
} USB2422_STCD_Type;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
/** \brief USB2422 device hardware registers */
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
typedef struct {
USB2422_VID_Type VID; /**< \brief Offset: 0x00*/
USB2422_PID_Type PID; /**< \brief Offset: 0x02*/
@@ -368,35 +308,95 @@ typedef struct {
USB2422_PRTR12_Type PRTR12; /**< \brief Offset: 0xFB*/
uint8_t Reserved4[0x3];
USB2422_STCD_Type STCD; /**< \brief Offset: 0xFF*/
-} Usb2422;
-#endif
+} Usb2422_t;
+
+// ***************************************************************
+
+static Usb2422_t config;
-#define PORT_DETECT_RETRY_INTERVAL 2000
+// ***************************************************************
-#define USB_EXTRA_ADC_THRESHOLD 900
+/** \brief Handle the conversion to allow simple strings
+ */
+static void USB2422_strcpy(const char* str, USB2422_MFRSTR_Type* dest, uint8_t len) {
+ for (uint8_t i = 0; i < len; i++) {
+ dest[i] = str[i];
+ }
+}
-#define USB_EXTRA_STATE_DISABLED 0
-#define USB_EXTRA_STATE_ENABLED 1
-#define USB_EXTRA_STATE_UNKNOWN 2
-#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3
+/** \brief Handle the conversion to allow simple strings
+ */
+static void USB2422_write_block(void) {
+ static unsigned char i2c0_buf[34];
-#define USB_HOST_PORT_1 0
-#define USB_HOST_PORT_2 1
-#define USB_HOST_PORT_UNKNOWN 2
+ unsigned char* dest = i2c0_buf;
+ unsigned char* src;
+ unsigned char* base = (unsigned char*)&config;
-extern uint8_t usb_host_port;
-extern uint8_t usb_extra_state;
-extern uint8_t usb_extra_manual;
-extern uint8_t usb_gcr_auto;
+ for (src = base; src < base + 256; src += 32) {
+ dest[0] = src - base;
+ dest[1] = 32;
+ memcpy(&dest[2], src, 32);
+ i2c_transmit(USB2422_ADDRESS, dest, 34, 50000);
+ wait_us(100);
+ }
+}
-void USB2422_init(void);
-void USB_reset(void);
-void USB_configure(void);
-uint16_t USB_active(void);
-void USB_set_host_by_voltage(void);
-uint16_t adc_get(uint8_t muxpos);
-uint8_t USB2422_Port_Detect_Init(void);
-void USB_HandleExtraDevice(void);
-void USB_ExtraSetState(uint8_t state);
+// ***************************************************************
-#endif //_USB2422_H_
+void USB2422_init() {
+#ifdef USB2422_RESET_PIN
+ setPinOutput(USB2422_RESET_PIN);
+#endif
+#ifdef USB2422_ACTIVE_PIN
+ setPinInput(USB2422_ACTIVE_PIN);
+#endif
+
+ i2c_init(); // IC2 clk must be high at USB2422 reset release time to signal SMB configuration
+}
+
+void USB2422_configure() {
+ static const char SERNAME[] = "Unavailable";
+
+ memset(&config, 0, sizeof(Usb2422_t));
+
+ // configure Usb2422 registers
+ config.VID.reg = USB2422_VENDOR_ID;
+ config.PID.reg = USB2422_PRODUCT_ID;
+ config.DID.reg = USB2422_DEVICE_VER; // BCD format, eg 01.01
+ config.CFG1.bit.SELF_BUS_PWR = 1; // self powered for now
+ config.CFG1.bit.HS_DISABLE = 1; // full or high speed
+ // config.CFG2.bit.COMPOUND = 0; // compound device
+ config.CFG3.bit.STRING_EN = 1; // strings enabled
+ // config.NRD.bit.PORT2_NR = 0; // MCU is non-removable
+ config.MAXPB.reg = 20; // 0mA
+ config.HCMCB.reg = 20; // 0mA
+ config.MFRSL.reg = sizeof(USB2422_MANUFACTURER);
+ config.PRDSL.reg = sizeof(USB2422_PRODUCT);
+ config.SERSL.reg = sizeof(SERNAME);
+ USB2422_strcpy(USB2422_MANUFACTURER, config.MFRSTR, sizeof(USB2422_MANUFACTURER));
+ USB2422_strcpy(USB2422_PRODUCT, config.PRDSTR, sizeof(USB2422_PRODUCT));
+ USB2422_strcpy(SERNAME, config.SERSTR, sizeof(SERNAME));
+ // config.BOOSTUP.bit.BOOST=3; //upstream port
+ // config.BOOSTDOWN.bit.BOOST1=0; // extra port
+ // config.BOOSTDOWN.bit.BOOST2=2; //MCU is close
+ config.STCD.bit.USB_ATTACH = 1;
+
+ USB2422_write_block();
+}
+
+void USB2422_reset() {
+#ifdef USB2422_RESET_PIN
+ writePinLow(USB2422_RESET_PIN);
+ wait_us(2);
+ writePinHigh(USB2422_RESET_PIN);
+#endif
+}
+
+bool USB2422_active() {
+#ifdef USB2422_ACTIVE_PIN
+ return readPin(USB2422_ACTIVE_PIN);
+#else
+ return 1;
+#endif
+}
diff --git a/drivers/usb2422.h b/drivers/usb2422.h
new file mode 100644
index 0000000000..2e435b02bc
--- /dev/null
+++ b/drivers/usb2422.h
@@ -0,0 +1,59 @@
+/* Copyright 2021 QMK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <stdbool.h>
+
+#ifndef USB2422_ADDRESS
+# define USB2422_ADDRESS 0x58
+#endif
+
+#ifndef USB2422_VENDOR_ID
+# define USB2422_VENDOR_ID 0xFEED
+#endif
+#ifndef USB2422_PRODUCT_ID
+# define USB2422_PRODUCT_ID 0x0001
+#endif
+#ifndef USB2422_DEVICE_VER
+# define USB2422_DEVICE_VER 0x0001
+#endif
+
+#ifndef USB2422_MANUFACTURER
+# define USB2422_MANUFACTURER "QMK"
+#endif
+#ifndef USB2422_PRODUCT
+# define USB2422_PRODUCT "QMK Hub"
+#endif
+
+/** \brief Initialises the dependent subsystems */
+void USB2422_init(void);
+
+/** \brief Push configuration to the USB2422 device */
+void USB2422_configure(void);
+
+/** \brief Reset the chip (RESET_N)
+ *
+ * NOTE:
+ * Depends on a valid USB2422_RESET_PIN configuration
+ */
+void USB2422_reset(void);
+
+/** \brief Indicates the USB state of the hub (SUSP_IND)
+ *
+ * NOTE:
+ * Depends on a valid USB2422_ACTIVE_PIN configuration
+ */
+bool USB2422_active(void);
diff --git a/drivers/ws2812.h b/drivers/ws2812.h
index f179fcb0ef..945b3d0728 100644
--- a/drivers/ws2812.h
+++ b/drivers/ws2812.h
@@ -18,10 +18,40 @@
#include "quantum/color.h"
/*
+ * The WS2812 datasheets define T1H 900ns, T0H 350ns, T1L 350ns, T0L 900ns. Hence, by default, these
+ * are chosen to be conservative and avoid problems rather than for maximum throughput; in the code,
+ * this is done by default using a WS2812_TIMING parameter that accounts for the whole window (1250ns)
+ * and defining T1H and T0H; T1L and T0L are obtained by subtracting their low counterparts from the window.
+ *
+ * However, there are certain "WS2812"-like LEDs, like the SK6812s, which work in a similar
+ * communication topology but use different timings for the window and the T1L, T1H, T0L and T0H.
+ * This means that, albeit the same driver being applicable, the timings must be adapted.
+ */
+
+#ifndef WS2812_TIMING
+# define WS2812_TIMING 1250
+#endif
+
+#ifndef WS2812_T1H
+# define WS2812_T1H 900 // Width of a 1 bit in ns
+#endif
+
+#ifndef WS2812_T1L
+# define WS2812_T1L (WS2812_TIMING - WS2812_T1H) // Width of a 1 bit in ns
+#endif
+
+#ifndef WS2812_T0H
+# define WS2812_T0H 350 // Width of a 0 bit in ns
+#endif
+
+#ifndef WS2812_T0L
+# define WS2812_T0L (WS2812_TIMING - WS2812_T0H) // Width of a 0 bit in ns
+#endif
+
+/*
* Older WS2812s can handle a reset time (TRST) of 50us, but recent
* component revisions require a minimum of 280us.
*/
-
#if !defined(WS2812_TRST_US)
# define WS2812_TRST_US 280
#endif
diff --git a/keyboards/ergodox_ez/config.h b/keyboards/ergodox_ez/config.h
index 5fdc4e5f19..d1b954043e 100644
--- a/keyboards/ergodox_ez/config.h
+++ b/keyboards/ergodox_ez/config.h
@@ -127,6 +127,54 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define RGB_MATRIX_LED_FLUSH_LIMIT 26
#define RGB_DISABLE_WHEN_USB_SUSPENDED
+// RGB Matrix Animation modes. Explicitly enabled
+// For full list of effects, see:
+// https://docs.qmk.fm/#/feature_rgb_matrix?id=rgb-matrix-effects
+#define ENABLE_RGB_MATRIX_ALPHAS_MODS
+#define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
+#define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
+#define ENABLE_RGB_MATRIX_BREATHING
+#define ENABLE_RGB_MATRIX_BAND_SAT
+#define ENABLE_RGB_MATRIX_BAND_VAL
+#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
+#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
+#define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
+#define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
+#define ENABLE_RGB_MATRIX_CYCLE_ALL
+#define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+#define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
+#define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
+#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
+#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
+#define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
+#define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
+#define ENABLE_RGB_MATRIX_DUAL_BEACON
+#define ENABLE_RGB_MATRIX_RAINBOW_BEACON
+#define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
+#define ENABLE_RGB_MATRIX_RAINDROPS
+#define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
+#define ENABLE_RGB_MATRIX_HUE_BREATHING
+#define ENABLE_RGB_MATRIX_HUE_PENDULUM
+#define ENABLE_RGB_MATRIX_HUE_WAVE
+#define ENABLE_RGB_MATRIX_PIXEL_RAIN
+#define ENABLE_RGB_MATRIX_PIXEL_FLOW
+#define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
+// enabled only if RGB_MATRIX_FRAMEBUFFER_EFFECTS is defined
+#define ENABLE_RGB_MATRIX_TYPING_HEATMAP
+#define ENABLE_RGB_MATRIX_DIGITAL_RAIN
+// enabled only of RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is defined
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
+#define ENABLE_RGB_MATRIX_SPLASH
+#define ENABLE_RGB_MATRIX_MULTISPLASH
+#define ENABLE_RGB_MATRIX_SOLID_SPLASH
+#define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
// #define RGBLIGHT_COLOR_LAYER_0 0x00, 0x00, 0xFF
/* #define RGBLIGHT_COLOR_LAYER_1 0x00, 0x00, 0xFF */
diff --git a/keyboards/ergodox_ez/ergodox_ez.c b/keyboards/ergodox_ez/ergodox_ez.c
index c7fded7fbb..f415fa0255 100644
--- a/keyboards/ergodox_ez/ergodox_ez.c
+++ b/keyboards/ergodox_ez/ergodox_ez.c
@@ -245,7 +245,7 @@ const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
#ifdef RGB_MATRIX_ENABLE
// clang-format off
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* driver
* | R location
* | | G location
diff --git a/keyboards/ergodox_ez/rules.mk b/keyboards/ergodox_ez/rules.mk
index 88821a1deb..ccd1bde03b 100644
--- a/keyboards/ergodox_ez/rules.mk
+++ b/keyboards/ergodox_ez/rules.mk
@@ -16,7 +16,7 @@ BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
-COMMAND_ENABLE = yes # Commands for debug and configuration
+COMMAND_ENABLE = no # Commands for debug and configuration
CUSTOM_MATRIX = lite # Custom matrix file for the ErgoDox EZ
NKRO_ENABLE = yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
diff --git a/keyboards/moonlander/config.h b/keyboards/moonlander/config.h
index a3e2975735..221610f14a 100644
--- a/keyboards/moonlander/config.h
+++ b/keyboards/moonlander/config.h
@@ -90,6 +90,54 @@
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
#define RGB_MATRIX_KEYPRESSES
#define RGB_DISABLE_WHEN_USB_SUSPENDED
+// RGB Matrix Animation modes. Explicitly enabled
+// For full list of effects, see:
+// https://docs.qmk.fm/#/feature_rgb_matrix?id=rgb-matrix-effects
+# define ENABLE_RGB_MATRIX_ALPHAS_MODS
+# define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
+# define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
+# define ENABLE_RGB_MATRIX_BREATHING
+# define ENABLE_RGB_MATRIX_BAND_SAT
+# define ENABLE_RGB_MATRIX_BAND_VAL
+# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
+# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
+# define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
+# define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
+# define ENABLE_RGB_MATRIX_CYCLE_ALL
+# define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+# define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
+# define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
+# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
+# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
+# define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
+# define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
+# define ENABLE_RGB_MATRIX_DUAL_BEACON
+# define ENABLE_RGB_MATRIX_RAINBOW_BEACON
+# define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
+# define ENABLE_RGB_MATRIX_RAINDROPS
+# define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
+# define ENABLE_RGB_MATRIX_HUE_BREATHING
+# define ENABLE_RGB_MATRIX_HUE_PENDULUM
+# define ENABLE_RGB_MATRIX_HUE_WAVE
+# define ENABLE_RGB_MATRIX_PIXEL_RAIN
+# define ENABLE_RGB_MATRIX_PIXEL_FLOW
+# define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
+// enabled only if RGB_MATRIX_FRAMEBUFFER_EFFECTS is defined
+# define ENABLE_RGB_MATRIX_TYPING_HEATMAP
+# define ENABLE_RGB_MATRIX_DIGITAL_RAIN
+// enabled only of RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is defined
+# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
+# define ENABLE_RGB_MATRIX_SOLID_REACTIVE
+# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
+# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
+# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
+# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
+# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
+# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
+# define ENABLE_RGB_MATRIX_SPLASH
+# define ENABLE_RGB_MATRIX_MULTISPLASH
+# define ENABLE_RGB_MATRIX_SOLID_SPLASH
+# define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
// #define RGB_MATRIX_LED_PROCESS_LIMIT 5
// #define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/moonlander/moonlander.c b/keyboards/moonlander/moonlander.c
index 4452a3a5e2..329f8d2866 100644
--- a/keyboards/moonlander/moonlander.c
+++ b/keyboards/moonlander/moonlander.c
@@ -219,7 +219,7 @@ layer_state_t layer_state_set_kb(layer_state_t state) {
#ifdef RGB_MATRIX_ENABLE
// clang-format off
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -415,6 +415,7 @@ const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS] = LAYOUT_moonlander(
#endif
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
+ if (!process_record_user(keycode, record)) { return false; }
switch (keycode) {
#ifdef WEBUSB_ENABLE
case WEBUSB_PAIR:
@@ -465,7 +466,7 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
return false;
#endif
}
- return process_record_user(keycode, record);
+ return true;
}
void matrix_init_kb(void) {
@@ -483,6 +484,7 @@ void matrix_init_kb(void) {
rgb_matrix_set_flags(LED_FLAG_NONE);
}
#endif
+ matrix_init_user();
}
void eeconfig_init_kb(void) { // EEPROM is getting reset!
diff --git a/keyboards/moonlander/rules.mk b/keyboards/moonlander/rules.mk
index 2295b7db95..c6f6790565 100644
--- a/keyboards/moonlander/rules.mk
+++ b/keyboards/moonlander/rules.mk
@@ -12,8 +12,6 @@ MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = yes # Console for debug
COMMAND_ENABLE = yes # Commands for debug and configuration
-# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
-SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = yes # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
diff --git a/keyboards/planck/config.h b/keyboards/planck/config.h
index 71111eca21..a86359327a 100644
--- a/keyboards/planck/config.h
+++ b/keyboards/planck/config.h
@@ -15,8 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CONFIG_H
-#define CONFIG_H
+#pragma once
#include "config_common.h"
@@ -78,5 +77,3 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//#define NO_ACTION_ONESHOT
//#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION
-
-#endif
diff --git a/keyboards/planck/ez/config.h b/keyboards/planck/ez/config.h
index 41abb00808..6008d24f92 100644
--- a/keyboards/planck/ez/config.h
+++ b/keyboards/planck/ez/config.h
@@ -111,11 +111,9 @@
//#define NO_ACTION_FUNCTION
#define DRIVER_ADDR_1 0b1010000
-#define DRIVER_ADDR_2 0b1010000 // this is here for compliancy reasons.
#define DRIVER_COUNT 1
-#define DRIVER_1_LED_TOTAL 47
-#define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL
+#define DRIVER_LED_TOTAL 47
#define RGB_MATRIX_KEYPRESSES
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
@@ -123,7 +121,54 @@
#define RGB_MATRIX_LED_PROCESS_LIMIT 5
#define RGB_MATRIX_LED_FLUSH_LIMIT 26
-
+// RGB Matrix Animation modes. Explicitly enabled
+// For full list of effects, see:
+// https://docs.qmk.fm/#/feature_rgb_matrix?id=rgb-matrix-effects
+#define ENABLE_RGB_MATRIX_ALPHAS_MODS
+#define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
+#define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
+#define ENABLE_RGB_MATRIX_BREATHING
+#define ENABLE_RGB_MATRIX_BAND_SAT
+#define ENABLE_RGB_MATRIX_BAND_VAL
+#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
+#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
+#define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
+#define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
+#define ENABLE_RGB_MATRIX_CYCLE_ALL
+#define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+#define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
+#define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
+#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
+#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
+#define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
+#define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
+#define ENABLE_RGB_MATRIX_DUAL_BEACON
+#define ENABLE_RGB_MATRIX_RAINBOW_BEACON
+#define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
+#define ENABLE_RGB_MATRIX_RAINDROPS
+#define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
+#define ENABLE_RGB_MATRIX_HUE_BREATHING
+#define ENABLE_RGB_MATRIX_HUE_PENDULUM
+#define ENABLE_RGB_MATRIX_HUE_WAVE
+#define ENABLE_RGB_MATRIX_PIXEL_RAIN
+#define ENABLE_RGB_MATRIX_PIXEL_FLOW
+#define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
+// enabled only if RGB_MATRIX_FRAMEBUFFER_EFFECTS is defined
+#define ENABLE_RGB_MATRIX_TYPING_HEATMAP
+#define ENABLE_RGB_MATRIX_DIGITAL_RAIN
+// enabled only of RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is defined
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
+#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
+#define ENABLE_RGB_MATRIX_SPLASH
+#define ENABLE_RGB_MATRIX_MULTISPLASH
+#define ENABLE_RGB_MATRIX_SOLID_SPLASH
+#define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
#define IGNORE_MOD_TAP_INTERRUPT
diff --git a/keyboards/planck/ez/ez.c b/keyboards/planck/ez/ez.c
index dc95607604..bfb2fff697 100644
--- a/keyboards/planck/ez/ez.c
+++ b/keyboards/planck/ez/ez.c
@@ -21,7 +21,7 @@
keyboard_config_t keyboard_config;
#ifdef RGB_MATRIX_ENABLE
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
diff --git a/keyboards/planck/ez/rules.mk b/keyboards/planck/ez/rules.mk
index bc18497a74..5584a90454 100755
--- a/keyboards/planck/ez/rules.mk
+++ b/keyboards/planck/ez/rules.mk
@@ -19,9 +19,6 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
AUDIO_ENABLE = yes # Audio output on port C6
RGBLIGHT_ENABLE = no
-# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
-SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
-
ENCODER_ENABLE = yes
RGB_MATRIX_DRIVER = IS31FL3737
diff --git a/lib/chibios b/lib/chibios
-Subproject 413e39c5681d181720440f2a8b7391f581788d7
+Subproject d7b9d1c87f724bd7c8cd1486d6d0dc3ba52e0d5
diff --git a/lib/chibios-contrib b/lib/chibios-contrib
-Subproject 4568901a91e9bef78ea96a7a83e8150fe1f7353
+Subproject d1c2126d1cd867c50127da84425805e225df855
diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py
index 539d03e2fc..c51eece955 100644
--- a/lib/python/qmk/cli/__init__.py
+++ b/lib/python/qmk/cli/__init__.py
@@ -31,11 +31,11 @@ safe_commands = [
subcommands = [
'qmk.cli.bux',
'qmk.cli.c2json',
+ 'qmk.cli.cd',
'qmk.cli.cformat',
'qmk.cli.chibios.confmigrate',
'qmk.cli.clean',
'qmk.cli.compile',
- 'qmk.cli.console',
'qmk.cli.docs',
'qmk.cli.doctor',
'qmk.cli.fileformat',
@@ -45,7 +45,9 @@ subcommands = [
'qmk.cli.format.python',
'qmk.cli.format.text',
'qmk.cli.generate.api',
+ 'qmk.cli.generate.compilation_database',
'qmk.cli.generate.config_h',
+ 'qmk.cli.generate.develop_pr_list',
'qmk.cli.generate.dfu_header',
'qmk.cli.generate.docs',
'qmk.cli.generate.info_json',
diff --git a/lib/python/qmk/cli/cd.py b/lib/python/qmk/cli/cd.py
new file mode 100755
index 0000000000..c62c3f56c6
--- /dev/null
+++ b/lib/python/qmk/cli/cd.py
@@ -0,0 +1,46 @@
+"""Open a shell in the QMK Home directory
+"""
+import sys
+import os
+
+from milc import cli
+
+from qmk.path import under_qmk_firmware
+
+
+@cli.subcommand('Go to QMK Home')
+def cd(cli):
+ """Go to QMK Home
+ """
+ if not sys.stdout.isatty():
+ cli.log.error("This command is for interactive usage only. For non-interactive usage, 'cd $(qmk env QMK_HOME)' is more robust.")
+ sys.exit(1)
+
+ if not under_qmk_firmware():
+ # Only do anything if the user is not under qmk_firmware already
+ # in order to reduce the possibility of starting multiple shells
+ cli.log.info("Spawning a subshell in your QMK_HOME directory.")
+ cli.log.info("Type 'exit' to get back to the parent shell.")
+ if not cli.platform.lower().startswith('windows'):
+ # For Linux/Mac/etc
+ # Check the user's login shell from 'passwd'
+ # alternatively fall back to $SHELL env var
+ # and finally to '/bin/bash'.
+ import getpass
+ import pwd
+ shell = pwd.getpwnam(getpass.getuser()).pw_shell
+ if not shell:
+ shell = os.environ.get('SHELL', '/bin/bash')
+ # Start the new subshell
+ os.execl(shell, shell)
+ else:
+ # For Windows
+ # Check the $SHELL env var
+ # and fall back to '/usr/bin/bash'.
+ qmk_env = os.environ.copy()
+ # Set the prompt for the new shell
+ qmk_env['MSYS2_PS1'] = qmk_env['PS1']
+ # Start the new subshell
+ cli.run([os.environ.get('SHELL', '/usr/bin/bash')], env=qmk_env)
+ else:
+ cli.log.info("Already within qmk_firmware directory.")
diff --git a/lib/python/qmk/cli/console.py b/lib/python/qmk/cli/console.py
deleted file mode 100644
index 98c6bc0dc0..0000000000
--- a/lib/python/qmk/cli/console.py
+++ /dev/null
@@ -1,303 +0,0 @@
-"""Acquire debugging information from usb hid devices
-
-cli implementation of https://www.pjrc.com/teensy/hid_listen.html
-"""
-from pathlib import Path
-from threading import Thread
-from time import sleep, strftime
-
-import hid
-import usb.core
-
-from milc import cli
-
-LOG_COLOR = {
- 'next': 0,
- 'colors': [
- '{fg_blue}',
- '{fg_cyan}',
- '{fg_green}',
- '{fg_magenta}',
- '{fg_red}',
- '{fg_yellow}',
- ],
-}
-
-KNOWN_BOOTLOADERS = {
- # VID , PID
- ('03EB', '2FEF'): 'atmel-dfu: ATmega16U2',
- ('03EB', '2FF0'): 'atmel-dfu: ATmega32U2',
- ('03EB', '2FF3'): 'atmel-dfu: ATmega16U4',
- ('03EB', '2FF4'): 'atmel-dfu: ATmega32U4',
- ('03EB', '2FF9'): 'atmel-dfu: AT90USB64',
- ('03EB', '2FFA'): 'atmel-dfu: AT90USB162',
- ('03EB', '2FFB'): 'atmel-dfu: AT90USB128',
- ('03EB', '6124'): 'Microchip SAM-BA',
- ('0483', 'DF11'): 'stm32-dfu: STM32 BOOTLOADER',
- ('16C0', '05DC'): 'usbasploader: USBaspLoader',
- ('16C0', '05DF'): 'bootloadhid: HIDBoot',
- ('16C0', '0478'): 'halfkay: Teensy Halfkay',
- ('1B4F', '9203'): 'caterina: Pro Micro 3.3V',
- ('1B4F', '9205'): 'caterina: Pro Micro 5V',
- ('1B4F', '9207'): 'caterina: LilyPadUSB',
- ('1C11', 'B007'): 'kiibohd: Kiibohd DFU Bootloader',
- ('1EAF', '0003'): 'stm32duino: Maple 003',
- ('1FFB', '0101'): 'caterina: Polou A-Star 32U4 Bootloader',
- ('2341', '0036'): 'caterina: Arduino Leonardo',
- ('2341', '0037'): 'caterina: Arduino Micro',
- ('239A', '000C'): 'caterina: Adafruit Feather 32U4',
- ('239A', '000D'): 'caterina: Adafruit ItsyBitsy 32U4 3v',
- ('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v',
- ('2A03', '0036'): 'caterina: Arduino Leonardo',
- ('2A03', '0037'): 'caterina: Arduino Micro',
- ('314B', '0106'): 'apm32-dfu: APM32 DFU ISP Mode',
- ('03EB', '2067'): 'qmk-hid: HID Bootloader',
- ('03EB', '2045'): 'lufa-ms: LUFA Mass Storage Bootloader'
-}
-
-
-class MonitorDevice(object):
- def __init__(self, hid_device, numeric):
- self.hid_device = hid_device
- self.numeric = numeric
- self.device = hid.Device(path=hid_device['path'])
- self.current_line = ''
-
- cli.log.info('Console Connected: %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s%(vendor_id)04X:%(product_id)04X:%(index)d{style_reset_all})', hid_device)
-
- def read(self, size, encoding='ascii', timeout=1):
- """Read size bytes from the device.
- """
- return self.device.read(size, timeout).decode(encoding)
-
- def read_line(self):
- """Read from the device's console until we get a \n.
- """
- while '\n' not in self.current_line:
- self.current_line += self.read(32).replace('\x00', '')
-
- lines = self.current_line.split('\n', 1)
- self.current_line = lines[1]
-
- return lines[0]
-
- def run_forever(self):
- while True:
- try:
- message = {**self.hid_device, 'text': self.read_line()}
- identifier = (int2hex(message['vendor_id']), int2hex(message['product_id'])) if self.numeric else (message['manufacturer_string'], message['product_string'])
- message['identifier'] = ':'.join(identifier)
- message['ts'] = '{style_dim}{fg_green}%s{style_reset_all} ' % (strftime(cli.config.general.datetime_fmt),) if cli.args.timestamp else ''
-
- cli.echo('%(ts)s%(color)s%(identifier)s:%(index)d{style_reset_all}: %(text)s' % message)
-
- except hid.HIDException:
- break
-
-
-class FindDevices(object):
- def __init__(self, vid, pid, index, numeric):
- self.vid = vid
- self.pid = pid
- self.index = index
- self.numeric = numeric
-
- def run_forever(self):
- """Process messages from our queue in a loop.
- """
- live_devices = {}
- live_bootloaders = {}
-
- while True:
- try:
- for device in list(live_devices):
- if not live_devices[device]['thread'].is_alive():
- cli.log.info('Console Disconnected: %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s%(vendor_id)04X:%(product_id)04X:%(index)d{style_reset_all})', live_devices[device])
- del live_devices[device]
-
- for device in self.find_devices():
- if device['path'] not in live_devices:
- device['color'] = LOG_COLOR['colors'][LOG_COLOR['next']]
- LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors'])
- live_devices[device['path']] = device
-
- try:
- monitor = MonitorDevice(device, self.numeric)
- device['thread'] = Thread(target=monitor.run_forever, daemon=True)
-
- device['thread'].start()
- except Exception as e:
- device['e'] = e
- device['e_name'] = e.__class__.__name__
- cli.log.error("Could not connect to %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s:%(vendor_id)04X:%(product_id)04X:%(index)d): %(e_name)s: %(e)s", device)
- if cli.config.general.verbose:
- cli.log.exception(e)
- del live_devices[device['path']]
-
- if cli.args.bootloaders:
- for device in self.find_bootloaders():
- if device.address in live_bootloaders:
- live_bootloaders[device.address]._qmk_found = True
- else:
- name = KNOWN_BOOTLOADERS[(int2hex(device.idVendor), int2hex(device.idProduct))]
- cli.log.info('Bootloader Connected: {style_bright}{fg_magenta}%s', name)
- device._qmk_found = True
- live_bootloaders[device.address] = device
-
- for device in list(live_bootloaders):
- if live_bootloaders[device]._qmk_found:
- live_bootloaders[device]._qmk_found = False
- else:
- name = KNOWN_BOOTLOADERS[(int2hex(live_bootloaders[device].idVendor), int2hex(live_bootloaders[device].idProduct))]
- cli.log.info('Bootloader Disconnected: {style_bright}{fg_magenta}%s', name)
- del live_bootloaders[device]
-
- sleep(.1)
-
- except KeyboardInterrupt:
- break
-
- def is_bootloader(self, hid_device):
- """Returns true if the device in question matches a known bootloader vid/pid.
- """
- return (int2hex(hid_device.idVendor), int2hex(hid_device.idProduct)) in KNOWN_BOOTLOADERS
-
- def is_console_hid(self, hid_device):
- """Returns true when the usage page indicates it's a teensy-style console.
- """
- return hid_device['usage_page'] == 0xFF31 and hid_device['usage'] == 0x0074
-
- def is_filtered_device(self, hid_device):
- """Returns True if the device should be included in the list of available consoles.
- """
- return int2hex(hid_device['vendor_id']) == self.vid and int2hex(hid_device['product_id']) == self.pid
-
- def find_devices_by_report(self, hid_devices):
- """Returns a list of available teensy-style consoles by doing a brute-force search.
-
- Some versions of linux don't report usage and usage_page. In that case we fallback to reading the report (possibly inaccurately) ourselves.
- """
- devices = []
-
- for device in hid_devices:
- path = device['path'].decode('utf-8')
-
- if path.startswith('/dev/hidraw'):
- number = path[11:]
- report = Path(f'/sys/class/hidraw/hidraw{number}/device/report_descriptor')
-
- if report.exists():
- rp = report.read_bytes()
-
- if rp[1] == 0x31 and rp[3] == 0x09:
- devices.append(device)
-
- return devices
-
- def find_bootloaders(self):
- """Returns a list of available bootloader devices.
- """
- return list(filter(self.is_bootloader, usb.core.find(find_all=True)))
-
- def find_devices(self):
- """Returns a list of available teensy-style consoles.
- """
- hid_devices = hid.enumerate()
- devices = list(filter(self.is_console_hid, hid_devices))
-
- if not devices:
- devices = self.find_devices_by_report(hid_devices)
-
- if self.vid and self.pid:
- devices = list(filter(self.is_filtered_device, devices))
-
- # Add index numbers
- device_index = {}
- for device in devices:
- id = ':'.join((int2hex(device['vendor_id']), int2hex(device['product_id'])))
-
- if id not in device_index:
- device_index[id] = 0
-
- device_index[id] += 1
- device['index'] = device_index[id]
-
- return devices
-
-
-def int2hex(number):
- """Returns a string representation of the number as hex.
- """
- return "%04X" % number
-
-
-def list_devices(device_finder):
- """Show the user a nicely formatted list of devices.
- """
- devices = device_finder.find_devices()
-
- if devices:
- cli.log.info('Available devices:')
- for dev in devices:
- color = LOG_COLOR['colors'][LOG_COLOR['next']]
- LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors'])
- cli.log.info("\t%s%s:%s:%d{style_reset_all}\t%s %s", color, int2hex(dev['vendor_id']), int2hex(dev['product_id']), dev['index'], dev['manufacturer_string'], dev['product_string'])
-
- if cli.args.bootloaders:
- bootloaders = device_finder.find_bootloaders()
-
- if bootloaders:
- cli.log.info('Available Bootloaders:')
-
- for dev in bootloaders:
- cli.log.info("\t%s:%s\t%s", int2hex(dev.idVendor), int2hex(dev.idProduct), KNOWN_BOOTLOADERS[(int2hex(dev.idVendor), int2hex(dev.idProduct))])
-
-
-@cli.argument('--bootloaders', arg_only=True, default=True, action='store_boolean', help='displaying bootloaders.')
-@cli.argument('-d', '--device', help='Device to select - uses format <pid>:<vid>[:<index>].')
-@cli.argument('-l', '--list', arg_only=True, action='store_true', help='List available hid_listen devices.')
-@cli.argument('-n', '--numeric', arg_only=True, action='store_true', help='Show VID/PID instead of names.')
-@cli.argument('-t', '--timestamp', arg_only=True, action='store_true', help='Print the timestamp for received messages as well.')
-@cli.argument('-w', '--wait', type=int, default=1, help="How many seconds to wait between checks (Default: 1)")
-@cli.subcommand('Acquire debugging information from usb hid devices.', hidden=False if cli.config.user.developer else True)
-def console(cli):
- """Acquire debugging information from usb hid devices
- """
- vid = None
- pid = None
- index = 1
-
- if cli.config.console.device:
- device = cli.config.console.device.split(':')
-
- if len(device) == 2:
- vid, pid = device
-
- elif len(device) == 3:
- vid, pid, index = device
-
- if not index.isdigit():
- cli.log.error('Device index must be a number! Got "%s" instead.', index)
- exit(1)
-
- index = int(index)
-
- if index < 1:
- cli.log.error('Device index must be greater than 0! Got %s', index)
- exit(1)
-
- else:
- cli.log.error('Invalid format for device, expected "<pid>:<vid>[:<index>]" but got "%s".', cli.config.console.device)
- cli.print_help()
- exit(1)
-
- vid = vid.upper()
- pid = pid.upper()
-
- device_finder = FindDevices(vid, pid, index, cli.args.numeric)
-
- if cli.args.list:
- return list_devices(device_finder)
-
- print('Looking for devices...', flush=True)
- device_finder.run_forever()
diff --git a/lib/python/qmk/cli/docs.py b/lib/python/qmk/cli/docs.py
index d8f9b045a1..c24b914bc1 100644
--- a/lib/python/qmk/cli/docs.py
+++ b/lib/python/qmk/cli/docs.py
@@ -2,6 +2,7 @@
"""
import http.server
import os
+import shutil
import webbrowser
from milc import cli
@@ -11,20 +12,33 @@ from milc import cli
@cli.argument('-b', '--browser', action='store_true', help='Open the docs in the default browser.')
@cli.subcommand('Run a local webserver for QMK documentation.', hidden=False if cli.config.user.developer else True)
def docs(cli):
- """Spin up a local HTTPServer instance for the QMK docs.
+ """Spin up a local HTTP server for the QMK docs.
"""
os.chdir('docs')
- with http.server.HTTPServer(('', cli.config.docs.port), http.server.SimpleHTTPRequestHandler) as httpd:
- cli.log.info(f"Serving QMK docs at http://localhost:{cli.config.docs.port}/")
- cli.log.info("Press Control+C to exit.")
+ # If docsify-cli is installed, run that instead so we get live reload
+ if shutil.which('docsify'):
+ command = ['docsify', 'serve', '--port', f'{cli.config.docs.port}', '--open' if cli.config.docs.browser else '']
- if cli.config.docs.browser:
- webbrowser.open(f'http://localhost:{cli.config.docs.port}')
+ cli.log.info(f"Running {{fg_cyan}}{str.join(' ', command)}{{fg_reset}}")
+ cli.log.info("Press Control+C to exit.")
try:
- httpd.serve_forever()
+ cli.run(command, capture_output=False)
except KeyboardInterrupt:
cli.log.info("Stopping HTTP server...")
- finally:
- httpd.shutdown()
+ else:
+ # Fall back to Python HTTPServer
+ with http.server.HTTPServer(('', cli.config.docs.port), http.server.SimpleHTTPRequestHandler) as httpd:
+ cli.log.info(f"Serving QMK docs at http://localhost:{cli.config.docs.port}/")
+ cli.log.info("Press Control+C to exit.")
+
+ if cli.config.docs.browser:
+ webbrowser.open(f'http://localhost:{cli.config.docs.port}')
+
+ try:
+ httpd.serve_forever()
+ except KeyboardInterrupt:
+ cli.log.info("Stopping HTTP server...")
+ finally:
+ httpd.shutdown()
diff --git a/lib/python/qmk/cli/doctor/check.py b/lib/python/qmk/cli/doctor/check.py
index 0807f41518..2d691b64b0 100644
--- a/lib/python/qmk/cli/doctor/check.py
+++ b/lib/python/qmk/cli/doctor/check.py
@@ -26,7 +26,6 @@ ESSENTIAL_BINARIES = {
'arm-none-eabi-gcc': {
'version_arg': '-dumpversion'
},
- 'bin/qmk': {},
}
diff --git a/lib/python/qmk/cli/flash.py b/lib/python/qmk/cli/flash.py
index c2d9e09c69..28e48a4101 100644
--- a/lib/python/qmk/cli/flash.py
+++ b/lib/python/qmk/cli/flash.py
@@ -18,17 +18,21 @@ def print_bootloader_help():
"""Prints the available bootloaders listed in docs.qmk.fm.
"""
cli.log.info('Here are the available bootloaders:')
+ cli.echo('\tavrdude')
+ cli.echo('\tbootloadhid')
cli.echo('\tdfu')
+ cli.echo('\tdfu-util')
+ cli.echo('\tmdloader')
+ cli.echo('\tst-flash')
+ cli.echo('\tst-link-cli')
+ cli.log.info('Enhanced variants for split keyboards:')
+ cli.echo('\tavrdude-split-left')
+ cli.echo('\tavrdude-split-right')
cli.echo('\tdfu-ee')
cli.echo('\tdfu-split-left')
cli.echo('\tdfu-split-right')
- cli.echo('\tavrdude')
- cli.echo('\tBootloadHID')
- cli.echo('\tdfu-util')
cli.echo('\tdfu-util-split-left')
cli.echo('\tdfu-util-split-right')
- cli.echo('\tst-link-cli')
- cli.echo('\tst-flash')
cli.echo('For more info, visit https://docs.qmk.fm/#/flashing')
diff --git a/lib/python/qmk/cli/format/c.py b/lib/python/qmk/cli/format/c.py
index 0160e6036f..568684ed56 100644
--- a/lib/python/qmk/cli/format/c.py
+++ b/lib/python/qmk/cli/format/c.py
@@ -74,7 +74,7 @@ def filter_files(files, core_only=False):
# The following statement checks each file to see if the file path is
# - in the core directories
# - not in the ignored directories
- if not any(i in str(file) for i in core_dirs) or any(i in str(file) for i in ignored):
+ if not any(str(file).startswith(i) for i in core_dirs) or any(str(file).startswith(i) for i in ignored):
files[index] = None
cli.log.debug("Skipping non-core file %s, as '--core-only' is used.", file)
diff --git a/lib/python/qmk/cli/format/python.py b/lib/python/qmk/cli/format/python.py
index 00612f97ec..47b5c45fd5 100755
--- a/lib/python/qmk/cli/format/python.py
+++ b/lib/python/qmk/cli/format/python.py
@@ -4,23 +4,66 @@ from subprocess import CalledProcessError, DEVNULL
from milc import cli
+from qmk.path import normpath
-@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually format.")
-@cli.subcommand("Format python code according to QMK's style.", hidden=False if cli.config.user.developer else True)
-def format_python(cli):
- """Format python code according to QMK's style.
- """
+py_file_suffixes = ('py',)
+py_dirs = ['lib/python']
+
+
+def yapf_run(files):
edit = '--diff' if cli.args.dry_run else '--in-place'
- yapf_cmd = ['yapf', '-vv', '--recursive', edit, 'bin/qmk', 'lib/python']
+ yapf_cmd = ['yapf', '-vv', '--recursive', edit, *files]
try:
cli.run(yapf_cmd, check=True, capture_output=False, stdin=DEVNULL)
- cli.log.info('Python code in `bin/qmk` and `lib/python` is correctly formatted.')
- return True
+ cli.log.info('Successfully formatted the python code.')
except CalledProcessError:
- if cli.args.dry_run:
- cli.log.error('Python code in `bin/qmk` and `lib/python` incorrectly formatted!')
+ cli.log.error(f'Python code in {",".join(py_dirs)} incorrectly formatted!')
+ return False
+
+
+def filter_files(files):
+ """Yield only files to be formatted and skip the rest
+ """
+ for file in files:
+ if file and normpath(file).name.split('.')[-1] in py_file_suffixes:
+ yield file
else:
- cli.log.error('Error formatting python code!')
+ cli.log.debug('Skipping file %s', file)
+
+
+@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually format.")
+@cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.')
+@cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all files.')
+@cli.argument('files', nargs='*', arg_only=True, type=normpath, help='Filename(s) to format.')
+@cli.subcommand("Format python code according to QMK's style.", hidden=False if cli.config.user.developer else True)
+def format_python(cli):
+ """Format python code according to QMK's style.
+ """
+ # Find the list of files to format
+ if cli.args.files:
+ files = list(filter_files(cli.args.files))
+
+ if not files:
+ cli.log.error('No Python files in filelist: %s', ', '.join(map(str, cli.args.files)))
+ exit(0)
+
+ if cli.args.all_files:
+ cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(map(str, files)))
+
+ elif cli.args.all_files:
+ git_ls_cmd = ['git', 'ls-files', *py_dirs]
+ git_ls = cli.run(git_ls_cmd, stdin=DEVNULL)
+ files = list(filter_files(git_ls.stdout.split('\n')))
+
+ else:
+ git_diff_cmd = ['git', 'diff', '--name-only', cli.args.base_branch, *py_dirs]
+ git_diff = cli.run(git_diff_cmd, stdin=DEVNULL)
+ files = list(filter_files(git_diff.stdout.split('\n')))
+
+ # Sanity check
+ if not files:
+ cli.log.error('No changed files detected. Use "qmk format-python -a" to format all files')
+ return False
- return False
+ return yapf_run(files)
diff --git a/lib/python/qmk/cli/format/text.py b/lib/python/qmk/cli/format/text.py
index e7e07b7297..6dd4511896 100644
--- a/lib/python/qmk/cli/format/text.py
+++ b/lib/python/qmk/cli/format/text.py
@@ -1,27 +1,57 @@
"""Ensure text files have the proper line endings.
"""
-from subprocess import CalledProcessError
+from itertools import islice
+from subprocess import DEVNULL
from milc import cli
+from qmk.path import normpath
+
+def _get_chunks(it, size):
+ """Break down a collection into smaller parts
+ """
+ it = iter(it)
+ return iter(lambda: tuple(islice(it, size)), ())
+
+
+def dos2unix_run(files):
+ """Spawn multiple dos2unix subprocess avoiding too long commands on formatting everything
+ """
+ for chunk in _get_chunks(files, 10):
+ dos2unix = cli.run(['dos2unix', *chunk])
+
+ if dos2unix.returncode:
+ return False
+
+
+@cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.')
+@cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all files.')
+@cli.argument('files', nargs='*', arg_only=True, type=normpath, help='Filename(s) to format.')
@cli.subcommand("Ensure text files have the proper line endings.", hidden=True)
def format_text(cli):
"""Ensure text files have the proper line endings.
"""
- try:
- file_list_cmd = cli.run(['git', 'ls-files', '-z'], check=True)
- except CalledProcessError as e:
- cli.log.error('Could not get file list: %s', e)
- exit(1)
- except Exception as e:
- cli.log.error('Unhandled exception: %s: %s', e.__class__.__name__, e)
- cli.log.exception(e)
- exit(1)
-
- dos2unix = cli.run(['xargs', '-0', 'dos2unix'], stdin=None, input=file_list_cmd.stdout)
-
- if dos2unix.returncode != 0:
- print(dos2unix.stderr)
-
- return dos2unix.returncode
+ # Find the list of files to format
+ if cli.args.files:
+ files = list(cli.args.files)
+
+ if cli.args.all_files:
+ cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(map(str, files)))
+
+ elif cli.args.all_files:
+ git_ls_cmd = ['git', 'ls-files']
+ git_ls = cli.run(git_ls_cmd, stdin=DEVNULL)
+ files = list(filter(None, git_ls.stdout.split('\n')))
+
+ else:
+ git_diff_cmd = ['git', 'diff', '--name-only', cli.args.base_branch]
+ git_diff = cli.run(git_diff_cmd, stdin=DEVNULL)
+ files = list(filter(None, git_diff.stdout.split('\n')))
+
+ # Sanity check
+ if not files:
+ cli.log.error('No changed files detected. Use "qmk format-text -a" to format all files')
+ return False
+
+ return dos2unix_run(files)
diff --git a/lib/python/qmk/cli/generate/compilation_database.py b/lib/python/qmk/cli/generate/compilation_database.py
new file mode 100755
index 0000000000..602635270c
--- /dev/null
+++ b/lib/python/qmk/cli/generate/compilation_database.py
@@ -0,0 +1,133 @@
+"""Creates a compilation database for the given keyboard build.
+"""
+
+import json
+import os
+import re
+import shlex
+import shutil
+from functools import lru_cache
+from pathlib import Path
+from typing import Dict, Iterator, List, Union
+
+from milc import cli, MILC
+
+from qmk.commands import create_make_command
+from qmk.constants import QMK_FIRMWARE
+from qmk.decorators import automagic_keyboard, automagic_keymap
+
+
+@lru_cache(maxsize=10)
+def system_libs(binary: str) -> List[Path]:
+ """Find the system include directory that the given build tool uses.
+ """
+ cli.log.debug("searching for system library directory for binary: %s", binary)
+ bin_path = shutil.which(binary)
+
+ # Actually query xxxxxx-gcc to find its include paths.
+ if binary.endswith("gcc") or binary.endswith("g++"):
+ result = cli.run([binary, '-E', '-Wp,-v', '-'], capture_output=True, check=True, input='\n')
+ paths = []
+ for line in result.stderr.splitlines():
+ if line.startswith(" "):
+ paths.append(Path(line.strip()).resolve())
+ return paths
+
+ return list(Path(bin_path).resolve().parent.parent.glob("*/include")) if bin_path else []
+
+
+file_re = re.compile(r'printf "Compiling: ([^"]+)')
+cmd_re = re.compile(r'LOG=\$\((.+?)&&')
+
+
+def parse_make_n(f: Iterator[str]) -> List[Dict[str, str]]:
+ """parse the output of `make -n <target>`
+
+ This function makes many assumptions about the format of your build log.
+ This happens to work right now for qmk.
+ """
+
+ state = 'start'
+ this_file = None
+ records = []
+ for line in f:
+ if state == 'start':
+ m = file_re.search(line)
+ if m:
+ this_file = m.group(1)
+ state = 'cmd'
+
+ if state == 'cmd':
+ assert this_file
+ m = cmd_re.search(line)
+ if m:
+ # we have a hit!
+ this_cmd = m.group(1)
+ args = shlex.split(this_cmd)
+ for s in system_libs(args[0]):
+ args += ['-isystem', '%s' % s]
+ new_cmd = ' '.join(shlex.quote(s) for s in args if s != '-mno-thumb-interwork')
+ records.append({"directory": str(QMK_FIRMWARE.resolve()), "command": new_cmd, "file": this_file})
+ state = 'start'
+
+ return records
+
+
+@cli.argument('-kb', '--keyboard', help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.')
+@cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Ignored when a configurator export is supplied.')
+@cli.subcommand('Create a compilation database.')
+@automagic_keyboard
+@automagic_keymap
+def generate_compilation_database(cli: MILC) -> Union[bool, int]:
+ """Creates a compilation database for the given keyboard build.
+
+ Does a make clean, then a make -n for this target and uses the dry-run output to create
+ a compilation database (compile_commands.json). This file can help some IDEs and
+ IDE-like editors work better. For more information about this:
+
+ https://clang.llvm.org/docs/JSONCompilationDatabase.html
+ """
+ command = None
+ # check both config domains: the magic decorator fills in `generate_compilation_database` but the user is
+ # more likely to have set `compile` in their config file.
+ current_keyboard = cli.config.generate_compilation_database.keyboard or cli.config.user.keyboard
+ current_keymap = cli.config.generate_compilation_database.keymap or cli.config.user.keymap
+
+ if current_keyboard and current_keymap:
+ # Generate the make command for a specific keyboard/keymap.
+ command = create_make_command(current_keyboard, current_keymap, dry_run=True)
+ elif not current_keyboard:
+ cli.log.error('Could not determine keyboard!')
+ elif not current_keymap:
+ cli.log.error('Could not determine keymap!')
+
+ if not command:
+ cli.log.error('You must supply both `--keyboard` and `--keymap`, or be in a directory for a keyboard or keymap.')
+ cli.echo('usage: qmk compiledb [-kb KEYBOARD] [-km KEYMAP]')
+ return False
+
+ # remove any environment variable overrides which could trip us up
+ env = os.environ.copy()
+ env.pop("MAKEFLAGS", None)
+
+ # re-use same executable as the main make invocation (might be gmake)
+ clean_command = [command[0], 'clean']
+ cli.log.info('Making clean with {fg_cyan}%s', ' '.join(clean_command))
+ cli.run(clean_command, capture_output=False, check=True, env=env)
+
+ cli.log.info('Gathering build instructions from {fg_cyan}%s', ' '.join(command))
+
+ result = cli.run(command, capture_output=True, check=True, env=env)
+ db = parse_make_n(result.stdout.splitlines())
+ if not db:
+ cli.log.error("Failed to parse output from make output:\n%s", result.stdout)
+ return False
+
+ cli.log.info("Found %s compile commands", len(db))
+
+ dbpath = QMK_FIRMWARE / 'compile_commands.json'
+
+ cli.log.info(f"Writing build database to {dbpath}")
+ dbpath.write_text(json.dumps(db, indent=4))
+
+ return True
diff --git a/lib/python/qmk/cli/generate/develop_pr_list.py b/lib/python/qmk/cli/generate/develop_pr_list.py
new file mode 100755
index 0000000000..07e46752a6
--- /dev/null
+++ b/lib/python/qmk/cli/generate/develop_pr_list.py
@@ -0,0 +1,119 @@
+"""Export the initial list of PRs associated with a `develop` merge to `master`.
+"""
+import os
+import re
+from pathlib import Path
+from subprocess import DEVNULL
+
+from milc import cli
+
+cache_timeout = 7 * 86400
+fix_expr = re.compile(r'fix', flags=re.IGNORECASE)
+clean1_expr = re.compile(r'\[(develop|keyboard|keymap|core|cli|bug|docs|feature)\]', flags=re.IGNORECASE)
+clean2_expr = re.compile(r'^(develop|keyboard|keymap|core|cli|bug|docs|feature):', flags=re.IGNORECASE)
+
+
+def _get_pr_info(cache, gh, pr_num):
+ pull = cache.get(f'pull:{pr_num}')
+ if pull is None:
+ print(f'Retrieving info for PR #{pr_num}')
+ pull = gh.pulls.get(owner='qmk', repo='qmk_firmware', pull_number=pr_num)
+ cache.set(f'pull:{pr_num}', pull, cache_timeout)
+ return pull
+
+
+def _try_open_cache(cli):
+ # These dependencies are manually handled because people complain. Fun.
+ try:
+ from sqlite_cache.sqlite_cache import SqliteCache
+ except ImportError:
+ return None
+
+ cache_loc = Path(cli.config_file).parent
+ return SqliteCache(cache_loc)
+
+
+def _get_github():
+ try:
+ from ghapi.all import GhApi
+ except ImportError:
+ return None
+
+ return GhApi()
+
+
+@cli.argument('-f', '--from-ref', default='0.11.0', help='Git revision/tag/reference/branch to begin search')
+@cli.argument('-b', '--branch', default='upstream/develop', help='Git branch to iterate (default: "upstream/develop")')
+@cli.subcommand('Creates the develop PR list.', hidden=False if cli.config.user.developer else True)
+def generate_develop_pr_list(cli):
+ """Retrieves information from GitHub regarding the list of PRs associated
+ with a merge of `develop` branch into `master`.
+
+ Requires environment variable GITHUB_TOKEN to be set.
+ """
+
+ if 'GITHUB_TOKEN' not in os.environ or os.environ['GITHUB_TOKEN'] == '':
+ cli.log.error('Environment variable "GITHUB_TOKEN" is not set.')
+ return 1
+
+ cache = _try_open_cache(cli)
+ gh = _get_github()
+
+ git_args = ['git', 'rev-list', '--oneline', '--no-merges', '--reverse', f'{cli.args.from_ref}...{cli.args.branch}', '^upstream/master']
+ commit_list = cli.run(git_args, capture_output=True, stdin=DEVNULL)
+
+ if cache is None or gh is None:
+ cli.log.error('Missing one or more dependent python packages: "ghapi", "python-sqlite-cache"')
+ return 1
+
+ pr_list_bugs = []
+ pr_list_dependencies = []
+ pr_list_core = []
+ pr_list_keyboards = []
+ pr_list_keyboard_fixes = []
+ pr_list_cli = []
+ pr_list_others = []
+
+ def _categorise_commit(commit_info):
+ def fix_or_normal(info, fixes_collection, normal_collection):
+ if "bug" in info['pr_labels'] or fix_expr.search(info['title']):
+ fixes_collection.append(info)
+ else:
+ normal_collection.append(info)
+
+ if "dependencies" in commit_info['pr_labels']:
+ fix_or_normal(commit_info, pr_list_bugs, pr_list_dependencies)
+ elif "core" in commit_info['pr_labels']:
+ fix_or_normal(commit_info, pr_list_bugs, pr_list_core)
+ elif "keyboard" in commit_info['pr_labels'] or "keymap" in commit_info['pr_labels'] or "via" in commit_info['pr_labels']:
+ fix_or_normal(commit_info, pr_list_keyboard_fixes, pr_list_keyboards)
+ elif "cli" in commit_info['pr_labels']:
+ fix_or_normal(commit_info, pr_list_bugs, pr_list_cli)
+ else:
+ fix_or_normal(commit_info, pr_list_bugs, pr_list_others)
+
+ git_expr = re.compile(r'^(?P<hash>[a-f0-9]+) (?P<title>.*) \(#(?P<pr>[0-9]+)\)$')
+ for line in commit_list.stdout.split('\n'):
+ match = git_expr.search(line)
+ if match:
+ pr_info = _get_pr_info(cache, gh, match.group("pr"))
+ commit_info = {'hash': match.group("hash"), 'title': match.group("title"), 'pr_num': int(match.group("pr")), 'pr_labels': [label.name for label in pr_info.labels.items]}
+ _categorise_commit(commit_info)
+
+ def _dump_commit_list(name, collection):
+ if len(collection) == 0:
+ return
+ print("")
+ print(f"{name}:")
+ for commit in sorted(collection, key=lambda x: x['pr_num']):
+ title = clean1_expr.sub('', clean2_expr.sub('', commit['title'])).strip()
+ pr_num = commit['pr_num']
+ print(f'* {title} ([#{pr_num}](https://github.com/qmk/qmk_firmware/pull/{pr_num}))')
+
+ _dump_commit_list("Core", pr_list_core)
+ _dump_commit_list("CLI", pr_list_cli)
+ _dump_commit_list("Submodule updates", pr_list_dependencies)
+ _dump_commit_list("Keyboards", pr_list_keyboards)
+ _dump_commit_list("Keyboard fixes", pr_list_keyboard_fixes)
+ _dump_commit_list("Others", pr_list_others)
+ _dump_commit_list("Bugs", pr_list_bugs)
diff --git a/lib/python/qmk/cli/generate/dfu_header.py b/lib/python/qmk/cli/generate/dfu_header.py
index 5a1b109f1e..7fb585fc7d 100644
--- a/lib/python/qmk/cli/generate/dfu_header.py
+++ b/lib/python/qmk/cli/generate/dfu_header.py
@@ -32,7 +32,7 @@ def generate_dfu_header(cli):
keyboard_h_lines = ['/* This file was generated by `qmk generate-dfu-header`. Do not edit or copy.', ' */', '', '#pragma once']
keyboard_h_lines.append(f'#define MANUFACTURER {kb_info_json["manufacturer"]}')
- keyboard_h_lines.append(f'#define PRODUCT {cli.config.generate_dfu_header.keyboard} Bootloader')
+ keyboard_h_lines.append(f'#define PRODUCT {kb_info_json["keyboard_name"]} Bootloader')
# Optional
if 'qmk_lufa_bootloader.esc_output' in kb_info_json:
diff --git a/lib/python/qmk/cli/generate/rules_mk.py b/lib/python/qmk/cli/generate/rules_mk.py
index dcaff29fae..5d8d7cc8a7 100755
--- a/lib/python/qmk/cli/generate/rules_mk.py
+++ b/lib/python/qmk/cli/generate/rules_mk.py
@@ -67,12 +67,9 @@ def generate_rules_mk(cli):
# Iterate through features to enable/disable them
if 'features' in kb_info_json:
for feature, enabled in kb_info_json['features'].items():
- if feature == 'bootmagic_lite' and enabled:
- rules_mk_lines.append('BOOTMAGIC_ENABLE ?= lite')
- else:
- feature = feature.upper()
- enabled = 'yes' if enabled else 'no'
- rules_mk_lines.append(f'{feature}_ENABLE ?= {enabled}')
+ feature = feature.upper()
+ enabled = 'yes' if enabled else 'no'
+ rules_mk_lines.append(f'{feature}_ENABLE ?= {enabled}')
# Set SPLIT_TRANSPORT, if needed
if kb_info_json.get('split', {}).get('transport', {}).get('protocol') == 'custom':
diff --git a/lib/python/qmk/cli/json2c.py b/lib/python/qmk/cli/json2c.py
index a90578c021..ae8248e6b7 100755
--- a/lib/python/qmk/cli/json2c.py
+++ b/lib/python/qmk/cli/json2c.py
@@ -33,7 +33,7 @@ def json2c(cli):
cli.args.output = None
# Generate the keymap
- keymap_c = qmk.keymap.generate_c(user_keymap['keyboard'], user_keymap['layout'], user_keymap['layers'])
+ keymap_c = qmk.keymap.generate_c(user_keymap)
if cli.args.output:
cli.args.output.parent.mkdir(parents=True, exist_ok=True)
diff --git a/lib/python/qmk/cli/lint.py b/lib/python/qmk/cli/lint.py
index 02b31fbc41..96593ed69b 100644
--- a/lib/python/qmk/cli/lint.py
+++ b/lib/python/qmk/cli/lint.py
@@ -1,72 +1,129 @@
"""Command to look over a keyboard/keymap and check for common mistakes.
"""
+from pathlib import Path
+
from milc import cli
from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.info import info_json
-from qmk.keyboard import find_readme, keyboard_completer
+from qmk.keyboard import keyboard_completer, list_keyboards
from qmk.keymap import locate_keymap
from qmk.path import is_keyboard, keyboard
-@cli.argument('--strict', action='store_true', help='Treat warnings as errors.')
-@cli.argument('-kb', '--keyboard', completer=keyboard_completer, help='The keyboard to check.')
-@cli.argument('-km', '--keymap', help='The keymap to check.')
+def keymap_check(kb, km):
+ """Perform the keymap level checks.
+ """
+ ok = True
+ keymap_path = locate_keymap(kb, km)
+
+ if not keymap_path:
+ ok = False
+ cli.log.error("%s: Can't find %s keymap.", kb, km)
+
+ return ok
+
+
+def rules_mk_assignment_only(keyboard_path):
+ """Check the keyboard-level rules.mk to ensure it only has assignments.
+ """
+ current_path = Path()
+ errors = []
+
+ for path_part in keyboard_path.parts:
+ current_path = current_path / path_part
+ rules_mk = current_path / 'rules.mk'
+
+ if rules_mk.exists():
+ continuation = None
+
+ for i, line in enumerate(rules_mk.open()):
+ line = line.strip()
+
+ if '#' in line:
+ line = line[:line.index('#')]
+
+ if continuation:
+ line = continuation + line
+ continuation = None
+
+ if line:
+ if line[-1] == '\\':
+ continuation = line[:-1]
+ continue
+
+ if line and '=' not in line:
+ errors.append(f'Non-assignment code on line +{i} {rules_mk}: {line}')
+
+ return errors
+
+
+@cli.argument('--strict', action='store_true', help='Treat warnings as errors')
+@cli.argument('-kb', '--keyboard', completer=keyboard_completer, help='Comma separated list of keyboards to check')
+@cli.argument('-km', '--keymap', help='The keymap to check')
+@cli.argument('--all-kb', action='store_true', arg_only=True, help='Check all keyboards')
@cli.subcommand('Check keyboard and keymap for common mistakes.')
@automagic_keyboard
@automagic_keymap
def lint(cli):
"""Check keyboard and keymap for common mistakes.
"""
- if not cli.config.lint.keyboard:
- cli.log.error('Missing required argument: --keyboard')
- cli.print_help()
- return False
+ failed = []
- if not is_keyboard(cli.config.lint.keyboard):
- cli.log.error('No such keyboard: %s', cli.config.lint.keyboard)
- return False
+ # Determine our keyboard list
+ if cli.args.all_kb:
+ if cli.args.keyboard:
+ cli.log.warning('Both --all-kb and --keyboard passed, --all-kb takes presidence.')
- # Gather data about the keyboard.
- ok = True
- keyboard_path = keyboard(cli.config.lint.keyboard)
- keyboard_info = info_json(cli.config.lint.keyboard)
- readme_path = find_readme(cli.config.lint.keyboard)
- missing_readme_path = keyboard_path / 'readme.md'
+ keyboard_list = list_keyboards()
+ elif not cli.config.lint.keyboard:
+ cli.log.error('Missing required arguments: --keyboard or --all-kb')
+ cli.print_help()
+ return False
+ else:
+ keyboard_list = cli.config.lint.keyboard.split(',')
- # Check for errors in the info.json
- if keyboard_info['parse_errors']:
- ok = False
- cli.log.error('Errors found when generating info.json.')
+ # Lint each keyboard
+ for kb in keyboard_list:
+ if not is_keyboard(kb):
+ cli.log.error('No such keyboard: %s', kb)
+ continue
- if cli.config.lint.strict and keyboard_info['parse_warnings']:
- ok = False
- cli.log.error('Warnings found when generating info.json (Strict mode enabled.)')
+ # Gather data about the keyboard.
+ ok = True
+ keyboard_path = keyboard(kb)
+ keyboard_info = info_json(kb)
- # Check for a readme.md and warn if it doesn't exist
- if not readme_path:
- ok = False
- cli.log.error('Missing %s', missing_readme_path)
+ # Check for errors in the info.json
+ if keyboard_info['parse_errors']:
+ ok = False
+ cli.log.error('%s: Errors found when generating info.json.', kb)
- # Keymap specific checks
- if cli.config.lint.keymap:
- keymap_path = locate_keymap(cli.config.lint.keyboard, cli.config.lint.keymap)
+ if cli.config.lint.strict and keyboard_info['parse_warnings']:
+ ok = False
+ cli.log.error('%s: Warnings found when generating info.json (Strict mode enabled.)', kb)
- if not keymap_path:
+ # Check the rules.mk file(s)
+ rules_mk_assignment_errors = rules_mk_assignment_only(keyboard_path)
+ if rules_mk_assignment_errors:
ok = False
- cli.log.error("Can't find %s keymap for %s keyboard.", cli.config.lint.keymap, cli.config.lint.keyboard)
- else:
- keymap_readme = keymap_path.parent / 'readme.md'
- if not keymap_readme.exists():
- cli.log.warning('Missing %s', keymap_readme)
+ cli.log.error('%s: Non-assignment code found in rules.mk. Move it to post_rules.mk instead.', kb)
+ for assignment_error in rules_mk_assignment_errors:
+ cli.log.error(assignment_error)
- if cli.config.lint.strict:
- ok = False
+ # Keymap specific checks
+ if cli.config.lint.keymap:
+ if not keymap_check(kb, cli.config.lint.keymap):
+ ok = False
+
+ # Report status
+ if not ok:
+ failed.append(kb)
# Check and report the overall status
- if ok:
- cli.log.info('Lint check passed!')
- return True
+ if failed:
+ cli.log.error('Lint check failed for: %s', ', '.join(failed))
+ return False
- cli.log.error('Lint check failed!')
- return False
+ cli.log.info('Lint check passed!')
+ return True
diff --git a/lib/python/qmk/cli/list/keymaps.py b/lib/python/qmk/cli/list/keymaps.py
index d79ab75b58..d2ef136c06 100644
--- a/lib/python/qmk/cli/list/keymaps.py
+++ b/lib/python/qmk/cli/list/keymaps.py
@@ -13,5 +13,10 @@ from qmk.keyboard import keyboard_completer, keyboard_folder
def list_keymaps(cli):
"""List the keymaps for a specific keyboard
"""
+ if not cli.config.list_keymaps.keyboard:
+ cli.log.error('Missing required arguments: --keyboard')
+ cli.subcommands['list-keymaps'].print_help()
+ return False
+
for name in qmk.keymap.list_keymaps(cli.config.list_keymaps.keyboard):
print(name)
diff --git a/lib/python/qmk/cli/list/layouts.py b/lib/python/qmk/cli/list/layouts.py
index 8e07afeeca..df593dc390 100644
--- a/lib/python/qmk/cli/list/layouts.py
+++ b/lib/python/qmk/cli/list/layouts.py
@@ -13,6 +13,11 @@ from qmk.info import info_json
def list_layouts(cli):
"""List the layouts for a specific keyboard
"""
+ if not cli.config.list_layouts.keyboard:
+ cli.log.error('Missing required arguments: --keyboard')
+ cli.subcommands['list-layouts'].print_help()
+ return False
+
info_data = info_json(cli.config.list_layouts.keyboard)
for name in sorted(info_data.get('community_layouts', [])):
print(name)
diff --git a/lib/python/qmk/cli/new/keyboard.py b/lib/python/qmk/cli/new/keyboard.py
index 369d2bd7da..4093b8c90d 100644
--- a/lib/python/qmk/cli/new/keyboard.py
+++ b/lib/python/qmk/cli/new/keyboard.py
@@ -1,10 +1,8 @@
"""This script automates the creation of new keyboard directories using a starter template.
"""
from datetime import date
-import fileinput
from pathlib import Path
import re
-import shutil
from qmk.commands import git_get_username
import qmk.path
@@ -32,6 +30,7 @@ def validate_keyboard_name(name):
@cli.argument('-kb', '--keyboard', help='Specify the name for the new keyboard directory', arg_only=True, type=keyboard_name)
@cli.argument('-t', '--type', help='Specify the keyboard type', arg_only=True, choices=KEYBOARD_TYPES)
@cli.argument('-u', '--username', help='Specify your username (default from Git config)', arg_only=True)
+@cli.argument('-n', '--realname', help='Specify your real name if you want to use that. Defaults to username', arg_only=True)
@cli.subcommand('Creates a new keyboard directory')
def new_keyboard(cli):
"""Creates a new keyboard.
@@ -69,7 +68,7 @@ def new_keyboard(cli):
# Get username
user_name = None
while not user_name:
- user_name = question('Your Name:', default=find_user_name())
+ user_name = question('Your GitHub User Name:', default=find_user_name())
if not user_name:
cli.log.error('You didn\'t provide a username, and we couldn\'t find one set in your QMK or Git configs. Please try again.')
@@ -78,26 +77,21 @@ def new_keyboard(cli):
if cli.args.username:
return False
- # Copy all the files
- copy_templates(keyboard_type, keyboard_path)
+ real_name = None
+ while not real_name:
+ real_name = question('Your real name:', default=user_name)
- # Replace all the placeholders
keyboard_basename = keyboard_path.name
- replacements = [
- ('%YEAR%', str(date.today().year)),
- ('%KEYBOARD%', keyboard_basename),
- ('%YOUR_NAME%', user_name),
- ]
- filenames = [
- keyboard_path / 'config.h',
- keyboard_path / 'info.json',
- keyboard_path / 'readme.md',
- keyboard_path / f'{keyboard_basename}.c',
- keyboard_path / f'{keyboard_basename}.h',
- keyboard_path / 'keymaps/default/readme.md',
- keyboard_path / 'keymaps/default/keymap.c',
- ]
- replace_placeholders(replacements, filenames)
+ replacements = {
+ "YEAR": str(date.today().year),
+ "KEYBOARD": keyboard_basename,
+ "USER_NAME": user_name,
+ "YOUR_NAME": real_name,
+ }
+
+ template_dir = Path('data/templates')
+ template_tree(template_dir / 'base', keyboard_path, replacements)
+ template_tree(template_dir / keyboard_type, keyboard_path, replacements)
cli.echo('')
cli.log.info(f'{{fg_green}}Created a new keyboard called {{fg_cyan}}{new_keyboard_name}{{fg_green}}.{{fg_reset}}')
@@ -114,29 +108,32 @@ def find_user_name():
return git_get_username()
-def copy_templates(keyboard_type, keyboard_path):
- """Copies the template files from data/templates to the new keyboard directory.
- """
- template_base_path = Path('data/templates')
- keyboard_basename = keyboard_path.name
+def template_tree(src: Path, dst: Path, replacements: dict):
+ """Recursively copy template and replace placeholders
- cli.log.info('Copying base template files...')
- shutil.copytree(template_base_path / 'base', keyboard_path)
+ Args:
+ src (Path)
+ The source folder to copy from
+ dst (Path)
+ The destination folder to copy to
+ replacements (dict)
+ a dictionary with "key":"value" pairs to replace.
- cli.log.info(f'Copying {{fg_cyan}}{keyboard_type}{{fg_reset}} template files...')
- shutil.copytree(template_base_path / keyboard_type, keyboard_path, dirs_exist_ok=True)
+ Raises:
+ FileExistsError
+ When trying to overwrite existing files
+ """
- cli.log.info(f'Renaming {{fg_cyan}}keyboard.[ch]{{fg_reset}} to {{fg_cyan}}{keyboard_basename}.[ch]{{fg_reset}}...')
- shutil.move(keyboard_path / 'keyboard.c', keyboard_path / f'{keyboard_basename}.c')
- shutil.move(keyboard_path / 'keyboard.h', keyboard_path / f'{keyboard_basename}.h')
+ dst.mkdir(parents=True, exist_ok=True)
+ for child in src.iterdir():
+ if child.is_dir():
+ template_tree(child, dst / child.name, replacements=replacements)
-def replace_placeholders(replacements, filenames):
- """Replaces the given placeholders in each template file.
- """
- for replacement in replacements:
- cli.log.info(f'Replacing {{fg_cyan}}{replacement[0]}{{fg_reset}} with {{fg_cyan}}{replacement[1]}{{fg_reset}}...')
+ if child.is_file():
+ file_name = dst / (child.name % replacements)
- with fileinput.input(files=filenames, inplace=True) as file:
- for line in file:
- print(line.replace(replacement[0], replacement[1]), end='')
+ with file_name.open(mode='x') as dst_f:
+ with child.open() as src_f:
+ template = src_f.read()
+ dst_f.write(template % replacements)
diff --git a/lib/python/qmk/cli/pytest.py b/lib/python/qmk/cli/pytest.py
index bdb336b9a7..a7f01a872a 100644
--- a/lib/python/qmk/cli/pytest.py
+++ b/lib/python/qmk/cli/pytest.py
@@ -12,6 +12,6 @@ def pytest(cli):
"""Run several linting/testing commands.
"""
nose2 = cli.run(['nose2', '-v'], capture_output=False, stdin=DEVNULL)
- flake8 = cli.run(['flake8', 'lib/python', 'bin/qmk'], capture_output=False, stdin=DEVNULL)
+ flake8 = cli.run(['flake8', 'lib/python'], capture_output=False, stdin=DEVNULL)
return flake8.returncode | nose2.returncode
diff --git a/lib/python/qmk/commands.py b/lib/python/qmk/commands.py
index 421453d837..5a01943773 100644
--- a/lib/python/qmk/commands.py
+++ b/lib/python/qmk/commands.py
@@ -28,7 +28,7 @@ def _find_make():
return make_cmd
-def create_make_target(target, parallel=1, **env_vars):
+def create_make_target(target, dry_run=False, parallel=1, **env_vars):
"""Create a make command
Args:
@@ -36,6 +36,9 @@ def create_make_target(target, parallel=1, **env_vars):
target
Usually a make rule, such as 'clean' or 'all'.
+ dry_run
+ make -n -- don't actually build
+
parallel
The number of make jobs to run in parallel
@@ -52,10 +55,10 @@ def create_make_target(target, parallel=1, **env_vars):
for key, value in env_vars.items():
env.append(f'{key}={value}')
- return [make_cmd, *get_make_parallel_args(parallel), *env, target]
+ return [make_cmd, *(['-n'] if dry_run else []), *get_make_parallel_args(parallel), *env, target]
-def create_make_command(keyboard, keymap, target=None, parallel=1, **env_vars):
+def create_make_command(keyboard, keymap, target=None, dry_run=False, parallel=1, **env_vars):
"""Create a make compile command
Args:
@@ -69,6 +72,9 @@ def create_make_command(keyboard, keymap, target=None, parallel=1, **env_vars):
target
Usually a bootloader.
+ dry_run
+ make -n -- don't actually build
+
parallel
The number of make jobs to run in parallel
@@ -84,7 +90,7 @@ def create_make_command(keyboard, keymap, target=None, parallel=1, **env_vars):
if target:
make_args.append(target)
- return create_make_target(':'.join(make_args), parallel, **env_vars)
+ return create_make_target(':'.join(make_args), dry_run=dry_run, parallel=parallel, **env_vars)
def get_git_version(current_time, repo_dir='.', check_dir='.'):
@@ -184,7 +190,7 @@ def compile_configurator_json(user_keymap, bootloader=None, parallel=1, **env_va
target = f'{keyboard_filesafe}_{user_keymap["keymap"]}'
keyboard_output = Path(f'{KEYBOARD_OUTPUT_PREFIX}{keyboard_filesafe}')
keymap_output = Path(f'{keyboard_output}_{user_keymap["keymap"]}')
- c_text = qmk.keymap.generate_c(user_keymap['keyboard'], user_keymap['layout'], user_keymap['layers'])
+ c_text = qmk.keymap.generate_c(user_keymap)
keymap_dir = keymap_output / 'src'
keymap_c = keymap_dir / 'keymap.c'
@@ -233,7 +239,7 @@ def compile_configurator_json(user_keymap, bootloader=None, parallel=1, **env_va
f'VERBOSE={verbose}',
f'COLOR={color}',
'SILENT=false',
- f'QMK_BIN={"bin/qmk" if "DEPRECATED_BIN_QMK" in os.environ else "qmk"}',
+ 'QMK_BIN="qmk"',
])
return make_command
diff --git a/lib/python/qmk/constants.py b/lib/python/qmk/constants.py
index 71a6c91c77..754091a97e 100644
--- a/lib/python/qmk/constants.py
+++ b/lib/python/qmk/constants.py
@@ -13,7 +13,7 @@ QMK_FIRMWARE_UPSTREAM = 'qmk/qmk_firmware'
MAX_KEYBOARD_SUBFOLDERS = 5
# Supported processor types
-CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66F18', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32L412', 'STM32L422', 'STM32L433', 'STM32L443'
+CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66FX1M0', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32L412', 'STM32L422', 'STM32L433', 'STM32L443', 'GD32VF103', 'WB32F3G71'
LUFA_PROCESSORS = 'at90usb162', 'atmega16u2', 'atmega32u2', 'atmega16u4', 'atmega32u4', 'at90usb646', 'at90usb647', 'at90usb1286', 'at90usb1287', None
VUSB_PROCESSORS = 'atmega32a', 'atmega328p', 'atmega328', 'attiny85'
diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py
index 350e5e2178..9a07fc842f 100644
--- a/lib/python/qmk/info.py
+++ b/lib/python/qmk/info.py
@@ -25,6 +25,13 @@ def _valid_community_layout(layout):
return (Path('layouts/default') / layout).exists()
+def _remove_newlines_from_labels(layouts):
+ for layout_name, layout_json in layouts.items():
+ for key in layout_json['layout']:
+ if '\n' in key['label']:
+ key['label'] = key['label'].split('\n')[0]
+
+
def info_json(keyboard):
"""Generate the info.json data for a specific keyboard.
"""
@@ -99,6 +106,9 @@ def info_json(keyboard):
# Check that the reported matrix size is consistent with the actual matrix size
_check_matrix(info_data)
+ # Remove newline characters from layout labels
+ _remove_newlines_from_labels(layouts)
+
return info_data
@@ -112,11 +122,6 @@ def _extract_features(info_data, rules):
if rules.get('BOOTMAGIC_ENABLE') == 'full':
rules['BOOTMAGIC_ENABLE'] = 'on'
- # Skip non-boolean features we haven't implemented special handling for
- for feature in 'HAPTIC_ENABLE', 'QWIIC_ENABLE':
- if rules.get(feature):
- del rules[feature]
-
# Process the rest of the rules as booleans
for key, value in rules.items():
if key.endswith('_ENABLE'):
@@ -619,6 +624,8 @@ def arm_processor_rules(info_data, rules):
if 'bootloader' not in info_data:
if 'STM32' in info_data['processor']:
info_data['bootloader'] = 'stm32-dfu'
+ elif 'WB32' in info_data['processor']:
+ info_data['bootloader'] = 'wb32-dfu'
else:
info_data['bootloader'] = 'unknown'
diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py
index 6eec49cfd1..00b5a78a5a 100644
--- a/lib/python/qmk/keymap.py
+++ b/lib/python/qmk/keymap.py
@@ -17,6 +17,7 @@ from qmk.errors import CppError
# The `keymap.c` template to use when a keyboard doesn't have its own
DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H
+__INCLUDES__
/* THIS FILE WAS GENERATED!
*
@@ -27,6 +28,7 @@ DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
__KEYMAP_GOES_HERE__
};
+
"""
@@ -180,10 +182,11 @@ def generate_json(keymap, keyboard, layout, layers):
return new_keymap
-def generate_c(keyboard, layout, layers):
- """Returns a `keymap.c` or `keymap.json` for the specified keyboard, layout, and layers.
+def generate_c(keymap_json):
+ """Returns a `keymap.c`.
+
+ `keymap_json` is a dictionary with the following keys:
- Args:
keyboard
The name of the keyboard
@@ -192,19 +195,89 @@ def generate_c(keyboard, layout, layers):
layers
An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
+
+ macros
+ A sequence of strings containing macros to implement for this keyboard.
"""
- new_keymap = template_c(keyboard)
+ new_keymap = template_c(keymap_json['keyboard'])
layer_txt = []
- for layer_num, layer in enumerate(layers):
+
+ for layer_num, layer in enumerate(keymap_json['layers']):
if layer_num != 0:
layer_txt[-1] = layer_txt[-1] + ','
layer = map(_strip_any, layer)
layer_keys = ', '.join(layer)
- layer_txt.append('\t[%s] = %s(%s)' % (layer_num, layout, layer_keys))
+ layer_txt.append('\t[%s] = %s(%s)' % (layer_num, keymap_json['layout'], layer_keys))
keymap = '\n'.join(layer_txt)
new_keymap = new_keymap.replace('__KEYMAP_GOES_HERE__', keymap)
+ if keymap_json.get('macros'):
+ macro_txt = [
+ 'bool process_record_user(uint16_t keycode, keyrecord_t *record) {',
+ ' if (record->event.pressed) {',
+ ' switch (keycode) {',
+ ]
+
+ for i, macro_array in enumerate(keymap_json['macros']):
+ macro = []
+
+ for macro_fragment in macro_array:
+ if isinstance(macro_fragment, str):
+ macro_fragment = macro_fragment.replace('\\', '\\\\')
+ macro_fragment = macro_fragment.replace('\r\n', r'\n')
+ macro_fragment = macro_fragment.replace('\n', r'\n')
+ macro_fragment = macro_fragment.replace('\r', r'\n')
+ macro_fragment = macro_fragment.replace('\t', r'\t')
+ macro_fragment = macro_fragment.replace('"', r'\"')
+
+ macro.append(f'"{macro_fragment}"')
+
+ elif isinstance(macro_fragment, dict):
+ newstring = []
+
+ if macro_fragment['action'] == 'delay':
+ newstring.append(f"SS_DELAY({macro_fragment['duration']})")
+
+ elif macro_fragment['action'] == 'beep':
+ newstring.append(r'"\a"')
+
+ elif macro_fragment['action'] == 'tap' and len(macro_fragment['keycodes']) > 1:
+ last_keycode = macro_fragment['keycodes'].pop()
+
+ for keycode in macro_fragment['keycodes']:
+ newstring.append(f'SS_DOWN(X_{keycode})')
+
+ newstring.append(f'SS_TAP(X_{last_keycode})')
+
+ for keycode in reversed(macro_fragment['keycodes']):
+ newstring.append(f'SS_UP(X_{keycode})')
+
+ else:
+ for keycode in macro_fragment['keycodes']:
+ newstring.append(f"SS_{macro_fragment['action'].upper()}(X_{keycode})")
+
+ macro.append(''.join(newstring))
+
+ new_macro = "".join(macro)
+ new_macro = new_macro.replace('""', '')
+ macro_txt.append(f' case MACRO_{i}:')
+ macro_txt.append(f' SEND_STRING({new_macro});')
+ macro_txt.append(' return false;')
+
+ macro_txt.append(' }')
+ macro_txt.append(' }')
+ macro_txt.append('\n return true;')
+ macro_txt.append('};')
+ macro_txt.append('')
+
+ new_keymap = '\n'.join((new_keymap, *macro_txt))
+
+ if keymap_json.get('host_language'):
+ new_keymap = new_keymap.replace('__INCLUDES__', f'#include "keymap_{keymap_json["host_language"]}.h"\n#include "sendstring_{keymap_json["host_language"]}.h"\n')
+ else:
+ new_keymap = new_keymap.replace('__INCLUDES__', '')
+
return new_keymap
@@ -217,7 +290,7 @@ def write_file(keymap_filename, keymap_content):
return keymap_filename
-def write_json(keyboard, keymap, layout, layers):
+def write_json(keyboard, keymap, layout, layers, macros=None):
"""Generate the `keymap.json` and write it to disk.
Returns the filename written to.
@@ -235,19 +308,19 @@ def write_json(keyboard, keymap, layout, layers):
layers
An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
"""
- keymap_json = generate_json(keyboard, keymap, layout, layers)
+ keymap_json = generate_json(keyboard, keymap, layout, layers, macros=None)
keymap_content = json.dumps(keymap_json)
keymap_file = qmk.path.keymap(keyboard) / keymap / 'keymap.json'
return write_file(keymap_file, keymap_content)
-def write(keyboard, keymap, layout, layers):
+def write(keymap_json):
"""Generate the `keymap.c` and write it to disk.
Returns the filename written to.
- Args:
+ `keymap_json` should be a dict with the following keys:
keyboard
The name of the keyboard
@@ -259,9 +332,12 @@ def write(keyboard, keymap, layout, layers):
layers
An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
+
+ macros
+ A list of macros for this keymap.
"""
- keymap_content = generate_c(keyboard, layout, layers)
- keymap_file = qmk.path.keymap(keyboard) / keymap / 'keymap.c'
+ keymap_content = generate_c(keymap_json)
+ keymap_file = qmk.path.keymap(keymap_json['keyboard']) / keymap_json['keymap'] / 'keymap.c'
return write_file(keymap_file, keymap_content)
diff --git a/lib/python/qmk/tests/minimal_info.json b/lib/python/qmk/tests/minimal_info.json
index 11ef12fefe..3aae4722bf 100644
--- a/lib/python/qmk/tests/minimal_info.json
+++ b/lib/python/qmk/tests/minimal_info.json
@@ -4,7 +4,7 @@
"layouts": {
"LAYOUT": {
"layout": [
- { "label": "KC_A", "x": 0, "y": 0, "matrix": [0, 0] }
+ { "label": "KC_A", "matrix": [0, 0], "x": 0, "y": 0 }
]
}
}
diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py
index b39fe5e46d..2973f81702 100644
--- a/lib/python/qmk/tests/test_cli_commands.py
+++ b/lib/python/qmk/tests/test_cli_commands.py
@@ -81,9 +81,9 @@ def test_hello():
def test_format_python():
- result = check_subcommand('format-python', '--dry-run')
+ result = check_subcommand('format-python', '-n', '-a')
check_returncode(result)
- assert 'Python code in `bin/qmk` and `lib/python` is correctly formatted.' in result.stdout
+ assert 'Successfully formatted the python code.' in result.stdout
def test_list_keyboards():
@@ -142,6 +142,14 @@ def test_json2c():
assert result.stdout == '#include QMK_KEYBOARD_H\nconst uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {\t[0] = LAYOUT_ortho_1x1(KC_A)};\n\n'
+def test_json2c_macros():
+ result = check_subcommand("json2c", 'keyboards/handwired/pytest/macro/keymaps/default/keymap.json')
+ check_returncode(result)
+ assert 'LAYOUT_ortho_1x1(MACRO_0)' in result.stdout
+ assert 'case MACRO_0:' in result.stdout
+ assert 'SEND_STRING("Hello, World!"SS_TAP(X_ENTER));' in result.stdout
+
+
def test_json2c_stdin():
result = check_subcommand_stdin('keyboards/handwired/pytest/has_template/keymaps/default_json/keymap.json', 'json2c', '-')
check_returncode(result)
@@ -151,7 +159,7 @@ def test_json2c_stdin():
def test_info():
result = check_subcommand('info', '-kb', 'handwired/pytest/basic')
check_returncode(result)
- assert 'Keyboard Name: handwired/pytest/basic' in result.stdout
+ assert 'Keyboard Name: pytest' in result.stdout
assert 'Processor: atmega32u4' in result.stdout
assert 'Layout:' not in result.stdout
assert 'k0' not in result.stdout
@@ -160,7 +168,7 @@ def test_info():
def test_info_keyboard_render():
result = check_subcommand('info', '-kb', 'handwired/pytest/basic', '-l')
check_returncode(result)
- assert 'Keyboard Name: handwired/pytest/basic' in result.stdout
+ assert 'Keyboard Name: pytest' in result.stdout
assert 'Processor: atmega32u4' in result.stdout
assert 'Layouts:' in result.stdout
assert 'k0' in result.stdout
@@ -169,7 +177,7 @@ def test_info_keyboard_render():
def test_info_keymap_render():
result = check_subcommand('info', '-kb', 'handwired/pytest/basic', '-km', 'default_json')
check_returncode(result)
- assert 'Keyboard Name: handwired/pytest/basic' in result.stdout
+ assert 'Keyboard Name: pytest' in result.stdout
assert 'Processor: atmega32u4' in result.stdout
if is_windows:
@@ -181,7 +189,7 @@ def test_info_keymap_render():
def test_info_matrix_render():
result = check_subcommand('info', '-kb', 'handwired/pytest/basic', '-m')
check_returncode(result)
- assert 'Keyboard Name: handwired/pytest/basic' in result.stdout
+ assert 'Keyboard Name: pytest' in result.stdout
assert 'Processor: atmega32u4' in result.stdout
assert 'LAYOUT_ortho_1x1' in result.stdout
@@ -242,7 +250,7 @@ def test_generate_config_h():
assert '# define DESCRIPTION handwired/pytest/basic' in result.stdout
assert '# define DIODE_DIRECTION COL2ROW' in result.stdout
assert '# define MANUFACTURER none' in result.stdout
- assert '# define PRODUCT handwired/pytest/basic' in result.stdout
+ assert '# define PRODUCT pytest' in result.stdout
assert '# define PRODUCT_ID 0x6465' in result.stdout
assert '# define VENDOR_ID 0xFEED' in result.stdout
assert '# define MATRIX_COLS 1' in result.stdout
diff --git a/lib/python/qmk/tests/test_qmk_keymap.py b/lib/python/qmk/tests/test_qmk_keymap.py
index b9e80df672..5e2efc1232 100644
--- a/lib/python/qmk/tests/test_qmk_keymap.py
+++ b/lib/python/qmk/tests/test_qmk_keymap.py
@@ -22,7 +22,13 @@ def test_template_json_pytest_has_template():
def test_generate_c_pytest_has_template():
- templ = qmk.keymap.generate_c('handwired/pytest/has_template', 'LAYOUT', [['KC_A']])
+ keymap_json = {
+ 'keyboard': 'handwired/pytest/has_template',
+ 'layout': 'LAYOUT',
+ 'layers': [['KC_A']],
+ 'macros': None,
+ }
+ templ = qmk.keymap.generate_c(keymap_json)
assert templ == '#include QMK_KEYBOARD_H\nconst uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {\t[0] = LAYOUT(KC_A)};\n'
diff --git a/lib/ugfx b/lib/ugfx
deleted file mode 160000
-Subproject 40b48f470addad6a4fb1177de1a69a181158739
diff --git a/common.mk b/paths.mk
index 8acea39376..5a39d00ecd 100644
--- a/common.mk
+++ b/paths.mk
@@ -1,5 +1,3 @@
-include message.mk
-
# Directory common source files exist
TOP_DIR = .
TMK_DIR = tmk_core
@@ -15,6 +13,12 @@ DRIVER_PATH = $(DRIVER_DIR)
PLATFORM_DIR = platforms
PLATFORM_PATH = $(PLATFORM_DIR)
+PROTOCOL_DIR = protocol
+PROTOCOL_PATH = $(TMK_DIR)/$(PROTOCOL_DIR)
+
+BUILDDEFS_DIR = builddefs
+BUILDDEFS_PATH = $(BUILDDEFS_DIR)
+
BUILD_DIR := .build
COMMON_VPATH := $(TOP_DIR)
@@ -23,6 +27,5 @@ COMMON_VPATH += $(QUANTUM_PATH)
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/tmk_core/common/arm_atsam/_timer.h b/platforms/arm_atsam/_timer.h
index 77402b612a..77402b612a 100644
--- a/tmk_core/common/arm_atsam/_timer.h
+++ b/platforms/arm_atsam/_timer.h
diff --git a/tmk_core/common/arm_atsam/_wait.h b/platforms/arm_atsam/_wait.h
index 41b686b56c..41b686b56c 100644
--- a/tmk_core/common/arm_atsam/_wait.h
+++ b/platforms/arm_atsam/_wait.h
diff --git a/tmk_core/common/arm_atsam/atomic_util.h b/platforms/arm_atsam/atomic_util.h
index 848542d23a..848542d23a 100644
--- a/tmk_core/common/arm_atsam/atomic_util.h
+++ b/platforms/arm_atsam/atomic_util.h
diff --git a/tmk_core/common/arm_atsam/bootloader.c b/platforms/arm_atsam/bootloader.c
index 9015b00aab..9015b00aab 100644
--- a/tmk_core/common/arm_atsam/bootloader.c
+++ b/platforms/arm_atsam/bootloader.c
diff --git a/tmk_core/common/arm_atsam/eeprom.c b/platforms/arm_atsam/eeprom.c
index ccd5d15a54..ff1a692623 100644
--- a/tmk_core/common/arm_atsam/eeprom.c
+++ b/platforms/arm_atsam/eeprom.c
@@ -13,24 +13,110 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
#include "eeprom.h"
+#include "debug.h"
+#include "samd51j18a.h"
+#include "core_cm4.h"
+#include "component/nvmctrl.h"
#ifndef EEPROM_SIZE
# include "eeconfig.h"
# define EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO
#endif
-__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE];
+#ifndef MAX
+# define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+#endif
+
+#ifndef BUSY_RETRIES
+# define BUSY_RETRIES 10000
+#endif
+
+// #define DEBUG_EEPROM_OUTPUT
+
+/*
+ * Debug print utils
+ */
+#if defined(DEBUG_EEPROM_OUTPUT)
+# define eeprom_printf(fmt, ...) xprintf(fmt, ##__VA_ARGS__);
+#else /* NO_DEBUG */
+# define eeprom_printf(fmt, ...)
+#endif /* NO_DEBUG */
+
+__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE] = {0};
+volatile uint8_t * SmartEEPROM8 = (uint8_t *)SEEPROM_ADDR;
+
+static inline bool eeprom_is_busy(void) {
+ int timeout = BUSY_RETRIES;
+ while (NVMCTRL->SEESTAT.bit.BUSY && timeout-- > 0)
+ ;
+
+ return NVMCTRL->SEESTAT.bit.BUSY;
+}
+
+static uint32_t get_virtual_eeprom_size(void) {
+ // clang-format off
+ static const uint32_t VIRTUAL_EEPROM_MAP[11][8] = {
+ /* 4 8 16 32 64 128 256 512 */
+ /* 0*/ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ /* 1*/ { 512, 1024, 2048, 4096, 4096, 4096, 4096, 4096 },
+ /* 2*/ { 512, 1024, 2048, 4096, 8192, 8192, 8192, 8192 },
+ /* 3*/ { 512, 1024, 2048, 4096, 8192, 16384, 16384, 16384 },
+ /* 4*/ { 512, 1024, 2048, 4096, 8192, 16384, 16384, 16384 },
+ /* 5*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
+ /* 6*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
+ /* 7*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
+ /* 8*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 32768 },
+ /* 9*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 },
+ /*10*/ { 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 },
+ };
+ // clang-format on
+
+ static uint32_t virtual_eeprom_size = UINT32_MAX;
+ if (virtual_eeprom_size == UINT32_MAX) {
+ virtual_eeprom_size = VIRTUAL_EEPROM_MAP[NVMCTRL->SEESTAT.bit.PSZ][NVMCTRL->SEESTAT.bit.SBLK];
+ }
+ // eeprom_printf("get_virtual_eeprom_size:: %d:%d:%d\n", NVMCTRL->SEESTAT.bit.PSZ, NVMCTRL->SEESTAT.bit.SBLK, virtual_eeprom_size);
+ return virtual_eeprom_size;
+}
uint8_t eeprom_read_byte(const uint8_t *addr) {
uintptr_t offset = (uintptr_t)addr;
- return buffer[offset];
+ if (offset >= MAX(EEPROM_SIZE, get_virtual_eeprom_size())) {
+ eeprom_printf("eeprom_read_byte:: out of bounds\n");
+ return 0x0;
+ }
+
+ if (get_virtual_eeprom_size() == 0) {
+ return buffer[offset];
+ }
+
+ if (eeprom_is_busy()) {
+ eeprom_printf("eeprom_write_byte:: timeout\n");
+ return 0x0;
+ }
+
+ return SmartEEPROM8[offset];
}
void eeprom_write_byte(uint8_t *addr, uint8_t value) {
uintptr_t offset = (uintptr_t)addr;
- buffer[offset] = value;
+ if (offset >= MAX(EEPROM_SIZE, get_virtual_eeprom_size())) {
+ eeprom_printf("eeprom_write_byte:: out of bounds\n");
+ return;
+ }
+
+ if (get_virtual_eeprom_size() == 0) {
+ buffer[offset] = value;
+ return;
+ }
+
+ if (eeprom_is_busy()) {
+ eeprom_printf("eeprom_write_byte:: timeout\n");
+ return;
+ }
+
+ SmartEEPROM8[offset] = value;
}
uint16_t eeprom_read_word(const uint16_t *addr) {
diff --git a/platforms/arm_atsam/flash.mk b/platforms/arm_atsam/flash.mk
index f31d4b4d95..8152610ceb 100644
--- a/platforms/arm_atsam/flash.mk
+++ b/platforms/arm_atsam/flash.mk
@@ -3,9 +3,20 @@
# Architecture or project specific options
#
+MDLOADER_CLI ?= mdloader
+
+define EXEC_MDLOADER
+ $(MDLOADER_CLI) --first --download $(BUILD_DIR)/$(TARGET).bin --restart
+endef
+
+mdloader: bin
+ $(call EXEC_MDLOADER)
+
flash: bin
ifneq ($(strip $(PROGRAM_CMD)),)
$(UNSYNC_OUTPUT_CMD) && $(PROGRAM_CMD)
+else ifeq ($(strip $(ARM_ATSAM)),SAMD51J18A)
+ $(UNSYNC_OUTPUT_CMD) && $(call EXEC_MDLOADER)
else
$(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_ARCH)"
endif
diff --git a/tmk_core/common/arm_atsam/gpio.h b/platforms/arm_atsam/gpio.h
index c2d5a30889..915ed0ef4f 100644
--- a/tmk_core/common/arm_atsam/gpio.h
+++ b/platforms/arm_atsam/gpio.h
@@ -64,7 +64,13 @@ typedef uint8_t pin_t;
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
} while (0)
-#define writePin(pin, level) ((level) ? (writePinHigh(pin)) : (writePinLow(pin)))
+#define writePin(pin, level) \
+ do { \
+ if (level) \
+ PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
+ else \
+ PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
+ } while (0)
#define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0)
diff --git a/tmk_core/common/arm_atsam/pin_defs.h b/platforms/arm_atsam/pin_defs.h
index 5b50b23910..5b50b23910 100644
--- a/tmk_core/common/arm_atsam/pin_defs.h
+++ b/platforms/arm_atsam/pin_defs.h
diff --git a/tmk_core/common/arm_atsam/platform.c b/platforms/arm_atsam/platform.c
index 3e35b4fe4c..3e35b4fe4c 100644
--- a/tmk_core/common/arm_atsam/platform.c
+++ b/platforms/arm_atsam/platform.c
diff --git a/tmk_core/arm_atsam.mk b/platforms/arm_atsam/platform.mk
index b29de9132b..b49bf764d7 100644
--- a/tmk_core/arm_atsam.mk
+++ b/platforms/arm_atsam/platform.mk
@@ -2,7 +2,7 @@
##############################################################################
# Compiler settings
#
-CC = arm-none-eabi-gcc
+CC = $(CC_PREFIX) arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy
OBJDUMP = arm-none-eabi-objdump
SIZE = arm-none-eabi-size
diff --git a/tmk_core/common/arm_atsam/platform_deps.h b/platforms/arm_atsam/platform_deps.h
index f296d1d535..f296d1d535 100644
--- a/tmk_core/common/arm_atsam/platform_deps.h
+++ b/platforms/arm_atsam/platform_deps.h
diff --git a/tmk_core/common/arm_atsam/suspend.c b/platforms/arm_atsam/suspend.c
index e51426128d..e51426128d 100644
--- a/tmk_core/common/arm_atsam/suspend.c
+++ b/platforms/arm_atsam/suspend.c
diff --git a/tmk_core/common/arm_atsam/timer.c b/platforms/arm_atsam/timer.c
index b835dd5e75..b835dd5e75 100644
--- a/tmk_core/common/arm_atsam/timer.c
+++ b/platforms/arm_atsam/timer.c
diff --git a/tmk_core/common/atomic_util.h b/platforms/atomic_util.h
index 2c95302a13..2c95302a13 100644
--- a/tmk_core/common/atomic_util.h
+++ b/platforms/atomic_util.h
diff --git a/tmk_core/common/avr/_print.h b/platforms/avr/_print.h
index 5c1fdd26d8..5c1fdd26d8 100644
--- a/tmk_core/common/avr/_print.h
+++ b/platforms/avr/_print.h
diff --git a/tmk_core/common/avr/_timer.h b/platforms/avr/_timer.h
index b81e0f68b7..b81e0f68b7 100644
--- a/tmk_core/common/avr/_timer.h
+++ b/platforms/avr/_timer.h
diff --git a/tmk_core/common/avr/_wait.h b/platforms/avr/_wait.h
index 683db6ae57..683db6ae57 100644
--- a/tmk_core/common/avr/_wait.h
+++ b/platforms/avr/_wait.h
diff --git a/tmk_core/common/avr/atomic_util.h b/platforms/avr/atomic_util.h
index 7c5d2e7dcc..7c5d2e7dcc 100644
--- a/tmk_core/common/avr/atomic_util.h
+++ b/platforms/avr/atomic_util.h
diff --git a/tmk_core/common/avr/bootloader.c b/platforms/avr/bootloader.c
index c0272903b8..c0272903b8 100644
--- a/tmk_core/common/avr/bootloader.c
+++ b/platforms/avr/bootloader.c
diff --git a/tmk_core/common/avr/bootloader_size.c b/platforms/avr/bootloader_size.c
index a029f9321f..a029f9321f 100644
--- a/tmk_core/common/avr/bootloader_size.c
+++ b/platforms/avr/bootloader_size.c
diff --git a/platforms/avr/drivers/analog.c b/platforms/avr/drivers/analog.c
index 8d299ffdb9..628835ccef 100644
--- a/platforms/avr/drivers/analog.c
+++ b/platforms/avr/drivers/analog.c
@@ -23,29 +23,6 @@ static uint8_t aref = ADC_REF_POWER;
void analogReference(uint8_t mode) { aref = mode & (_BV(REFS1) | _BV(REFS0)); }
-// Arduino compatible pin input
-int16_t analogRead(uint8_t pin) {
-#if defined(__AVR_ATmega32U4__)
- // clang-format off
- static const uint8_t PROGMEM pin_to_mux[] = {
- //A0 A1 A2 A3 A4 A5
- //F7 F6 F5 F4 F1 F0
- 0x07, 0x06, 0x05, 0x04, 0x01, 0x00,
- //A6 A7 A8 A9 A10 A11
- //D4 D7 B4 B5 B6 D6
- 0x20, 0x22, 0x23, 0x24, 0x25, 0x21
- };
- // clang-format on
- if (pin >= 12) return 0;
- return adc_read(pgm_read_byte(pin_to_mux + pin));
-#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
- if (pin >= 8) return 0;
- return adc_read(pin);
-#else
- return 0;
-#endif
-}
-
int16_t analogReadPin(pin_t pin) { return adc_read(pinToMux(pin)); }
uint8_t pinToMux(pin_t pin) {
diff --git a/platforms/avr/drivers/analog.h b/platforms/avr/drivers/analog.h
index 058882450d..fa2fb0d89b 100644
--- a/platforms/avr/drivers/analog.h
+++ b/platforms/avr/drivers/analog.h
@@ -22,8 +22,7 @@
#ifdef __cplusplus
extern "C" {
#endif
-void analogReference(uint8_t mode);
-int16_t analogRead(uint8_t pin);
+void analogReference(uint8_t mode);
int16_t analogReadPin(pin_t pin);
uint8_t pinToMux(pin_t pin);
diff --git a/quantum/audio/driver_avr_pwm.h b/platforms/avr/drivers/audio_pwm.h
index d6eb3571da..d6eb3571da 100644
--- a/quantum/audio/driver_avr_pwm.h
+++ b/platforms/avr/drivers/audio_pwm.h
diff --git a/quantum/audio/driver_avr_pwm_hardware.c b/platforms/avr/drivers/audio_pwm_hardware.c
index df03a4558c..df03a4558c 100644
--- a/quantum/audio/driver_avr_pwm_hardware.c
+++ b/platforms/avr/drivers/audio_pwm_hardware.c
diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c
index 2773e00778..111b55d6b0 100644
--- a/platforms/avr/drivers/i2c_master.c
+++ b/platforms/avr/drivers/i2c_master.c
@@ -202,6 +202,25 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,
return status;
}
+i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
+ i2c_status_t status = i2c_start(devaddr | 0x00, timeout);
+ if (status >= 0) {
+ status = i2c_write(regaddr >> 8, timeout);
+
+ if (status >= 0) {
+ status = i2c_write(regaddr & 0xFF, timeout);
+
+ for (uint16_t i = 0; i < length && status >= 0; i++) {
+ status = i2c_write(data[i], timeout);
+ }
+ }
+ }
+
+ i2c_stop();
+
+ return status;
+}
+
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
i2c_status_t status = i2c_start(devaddr, timeout);
if (status < 0) {
@@ -235,6 +254,43 @@ error:
return (status < 0) ? status : I2C_STATUS_SUCCESS;
}
+i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
+ i2c_status_t status = i2c_start(devaddr, timeout);
+ if (status < 0) {
+ goto error;
+ }
+
+ status = i2c_write(regaddr >> 8, timeout);
+ if (status < 0) {
+ goto error;
+ }
+ status = i2c_write(regaddr & 0xFF, timeout);
+ if (status < 0) {
+ goto error;
+ }
+
+ status = i2c_start(devaddr | 0x01, timeout);
+
+ for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {
+ status = i2c_read_ack(timeout);
+ if (status >= 0) {
+ data[i] = status;
+ }
+ }
+
+ if (status >= 0) {
+ status = i2c_read_nack(timeout);
+ if (status >= 0) {
+ data[(length - 1)] = status;
+ }
+ }
+
+error:
+ i2c_stop();
+
+ return (status < 0) ? status : I2C_STATUS_SUCCESS;
+}
+
void i2c_stop(void) {
// transmit STOP condition
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
diff --git a/platforms/avr/drivers/i2c_master.h b/platforms/avr/drivers/i2c_master.h
index e5af73364b..2d95846db5 100644
--- a/platforms/avr/drivers/i2c_master.h
+++ b/platforms/avr/drivers/i2c_master.h
@@ -39,5 +39,7 @@ int16_t i2c_read_nack(uint16_t timeout);
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
void i2c_stop(void);
diff --git a/platforms/avr/drivers/ps2/ps2_io.c b/platforms/avr/drivers/ps2/ps2_io.c
new file mode 100644
index 0000000000..7c826fbf1a
--- /dev/null
+++ b/platforms/avr/drivers/ps2/ps2_io.c
@@ -0,0 +1,51 @@
+#include <stdbool.h>
+#include "ps2_io.h"
+#include "gpio.h"
+#include "wait.h"
+
+/* Check port settings for clock and data line */
+#if !(defined(PS2_CLOCK_PIN))
+# error "PS/2 clock setting is required in config.h"
+#endif
+
+#if !(defined(PS2_DATA_PIN))
+# error "PS/2 data setting is required in config.h"
+#endif
+
+/*
+ * Clock
+ */
+void clock_init(void) {}
+
+void clock_lo(void) {
+ // Transition from input with pull-up to output low via Hi-Z instead of output high
+ writePinLow(PS2_CLOCK_PIN);
+ setPinOutput(PS2_CLOCK_PIN);
+}
+
+void clock_hi(void) { setPinInputHigh(PS2_CLOCK_PIN); }
+
+bool clock_in(void) {
+ setPinInputHigh(PS2_CLOCK_PIN);
+ wait_us(1);
+ return readPin(PS2_CLOCK_PIN);
+}
+
+/*
+ * Data
+ */
+void data_init(void) {}
+
+void data_lo(void) {
+ // Transition from input with pull-up to output low via Hi-Z instead of output high
+ writePinLow(PS2_DATA_PIN);
+ setPinOutput(PS2_DATA_PIN);
+}
+
+void data_hi(void) { setPinInputHigh(PS2_DATA_PIN); }
+
+bool data_in(void) {
+ setPinInputHigh(PS2_DATA_PIN);
+ wait_us(1);
+ return readPin(PS2_DATA_PIN);
+}
diff --git a/tmk_core/protocol/ps2_usart.c b/platforms/avr/drivers/ps2/ps2_usart.c
index 6a66dc4a1e..151cfcd68f 100644
--- a/tmk_core/protocol/ps2_usart.c
+++ b/platforms/avr/drivers/ps2/ps2_usart.c
@@ -42,10 +42,24 @@ POSSIBILITY OF SUCH DAMAGE.
#include <stdbool.h>
#include <avr/interrupt.h>
#include <util/delay.h>
+#include "gpio.h"
#include "ps2.h"
#include "ps2_io.h"
#include "print.h"
+#ifndef PS2_CLOCK_DDR
+# define PS2_CLOCK_DDR PORTx_ADDRESS(PS2_CLOCK_PIN)
+#endif
+#ifndef PS2_CLOCK_BIT
+# define PS2_CLOCK_BIT (PS2_CLOCK_PIN & 0xF)
+#endif
+#ifndef PS2_DATA_DDR
+# define PS2_DATA_DDR PORTx_ADDRESS(PS2_DATA_PIN)
+#endif
+#ifndef PS2_DATA_BIT
+# define PS2_DATA_BIT (PS2_DATA_PIN & 0xF)
+#endif
+
#define WAIT(stat, us, err) \
do { \
if (!wait_##stat(us)) { \
diff --git a/platforms/avr/drivers/uart.c b/platforms/avr/drivers/uart.c
index c6abcb6fe0..01cf6b1fb8 100644
--- a/platforms/avr/drivers/uart.c
+++ b/platforms/avr/drivers/uart.c
@@ -100,7 +100,7 @@ void uart_init(uint32_t baud) {
}
// Transmit a byte
-void uart_putchar(uint8_t c) {
+void uart_write(uint8_t data) {
uint8_t i;
i = tx_buffer_head + 1;
@@ -110,27 +110,39 @@ void uart_putchar(uint8_t c) {
while (tx_buffer_tail == i)
; // wait until space in buffer
// cli();
- tx_buffer[i] = c;
+ tx_buffer[i] = data;
tx_buffer_head = i;
UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn);
// sei();
}
// Receive a byte
-uint8_t uart_getchar(void) {
- uint8_t c, i;
+uint8_t uart_read(void) {
+ uint8_t data, i;
while (rx_buffer_head == rx_buffer_tail)
; // wait for character
i = rx_buffer_tail + 1;
if (i >= RX_BUFFER_SIZE) i = 0;
- c = rx_buffer[i];
+ data = rx_buffer[i];
rx_buffer_tail = i;
- return c;
+ return data;
+}
+
+void uart_transmit(const uint8_t *data, uint16_t length) {
+ for (uint16_t i = 0; i < length; i++) {
+ uart_write(data[i]);
+ }
+}
+
+void uart_receive(uint8_t *data, uint16_t length) {
+ for (uint16_t i = 0; i < length; i++) {
+ data[i] = uart_read();
+ }
}
// Return whether the number of bytes waiting in the receive buffer is nonzero.
-// Call this before uart_getchar() to check if it will need
+// Call this before uart_read() to check if it will need
// to wait for a byte to arrive.
bool uart_available(void) {
uint8_t head, tail;
diff --git a/platforms/avr/drivers/uart.h b/platforms/avr/drivers/uart.h
index 602eb3d8b0..e2dc664eda 100644
--- a/platforms/avr/drivers/uart.h
+++ b/platforms/avr/drivers/uart.h
@@ -28,8 +28,12 @@
void uart_init(uint32_t baud);
-void uart_putchar(uint8_t c);
+void uart_write(uint8_t data);
-uint8_t uart_getchar(void);
+uint8_t uart_read(void);
+
+void uart_transmit(const uint8_t *data, uint16_t length);
+
+void uart_receive(uint8_t *data, uint16_t length);
bool uart_available(void);
diff --git a/platforms/avr/drivers/ws2812.c b/platforms/avr/drivers/ws2812.c
index 77c492cd4c..9150b3c520 100644
--- a/platforms/avr/drivers/ws2812.c
+++ b/platforms/avr/drivers/ws2812.c
@@ -52,20 +52,15 @@ void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) {
using the fast 800kHz clockless WS2811/2812 protocol.
*/
-// Timing in ns
-#define w_zeropulse 350
-#define w_onepulse 900
-#define w_totalperiod 1250
-
// Fixed cycles used by the inner loop
#define w_fixedlow 2
#define w_fixedhigh 4
#define w_fixedtotal 8
// Insert NOPs to match the timing, if possible
-#define w_zerocycles (((F_CPU / 1000) * w_zeropulse) / 1000000)
-#define w_onecycles (((F_CPU / 1000) * w_onepulse + 500000) / 1000000)
-#define w_totalcycles (((F_CPU / 1000) * w_totalperiod + 500000) / 1000000)
+#define w_zerocycles (((F_CPU / 1000) * WS2812_T0H) / 1000000)
+#define w_onecycles (((F_CPU / 1000) * WS2812_T1H + 500000) / 1000000)
+#define w_totalcycles (((F_CPU / 1000) * WS2812_TIMING + 500000) / 1000000)
// w1_nops - nops between rising edge and falling edge - low
#if w_zerocycles >= w_fixedlow
diff --git a/platforms/avr/flash.mk b/platforms/avr/flash.mk
index 985cb60e52..6d50e72534 100644
--- a/platforms/avr/flash.mk
+++ b/platforms/avr/flash.mk
@@ -130,6 +130,15 @@ avrdude-split-right: $(BUILD_DIR)/$(TARGET).hex check-size cpfirmware
$(call EXEC_AVRDUDE,eeprom-righthand.eep)
define EXEC_USBASP
+ if $(AVRDUDE_PROGRAMMER) -p $(AVRDUDE_MCU) -c usbasp 2>&1 | grep -q "could not find USB device with"; then \
+ printf "$(MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY)" ;\
+ sleep $(BOOTLOADER_RETRY_TIME) ;\
+ until $(AVRDUDE_PROGRAMMER) -p $(AVRDUDE_MCU) -c usbasp 2>&1 | (! grep -q "could not find USB device with"); do\
+ printf "." ;\
+ sleep $(BOOTLOADER_RETRY_TIME) ;\
+ done ;\
+ printf "\n" ;\
+ fi
$(AVRDUDE_PROGRAMMER) -p $(AVRDUDE_MCU) -c usbasp -U flash:w:$(BUILD_DIR)/$(TARGET).hex
endef
diff --git a/tmk_core/common/avr/gpio.h b/platforms/avr/gpio.h
index e9be68491d..e9be68491d 100644
--- a/tmk_core/common/avr/gpio.h
+++ b/platforms/avr/gpio.h
diff --git a/tmk_core/common/avr/pin_defs.h b/platforms/avr/pin_defs.h
index 23d948041d..23d948041d 100644
--- a/tmk_core/common/avr/pin_defs.h
+++ b/platforms/avr/pin_defs.h
diff --git a/tmk_core/common/avr/platform.c b/platforms/avr/platform.c
index 3e35b4fe4c..3e35b4fe4c 100644
--- a/tmk_core/common/avr/platform.c
+++ b/platforms/avr/platform.c
diff --git a/tmk_core/avr.mk b/platforms/avr/platform.mk
index 940e95397b..b45108736f 100644
--- a/tmk_core/avr.mk
+++ b/platforms/avr/platform.mk
@@ -2,7 +2,7 @@
##############################################################################
# Compiler settings
#
-CC = avr-gcc
+CC = $(CC_PREFIX) avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
@@ -163,7 +163,7 @@ ifeq ($(strip $(QMK_BOOTLOADER_TYPE)),)
else
make -C lib/lufa/Bootloaders/$(QMK_BOOTLOADER_TYPE)/ clean
$(QMK_BIN) generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/$(QMK_BOOTLOADER_TYPE)/Keyboard.h
- $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0))
+ $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) platforms/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0))
$(eval PROGRAM_SIZE_KB=$(shell n=`expr $(MAX_SIZE) / 1024` && echo $$(($$n)) || echo 0))
$(eval BOOT_SECTION_SIZE_KB=$(shell n=`expr $(BOOTLOADER_SIZE) / 1024` && echo $$(($$n)) || echo 0))
$(eval FLASH_SIZE_KB=$(shell n=`expr $(PROGRAM_SIZE_KB) + $(BOOT_SECTION_SIZE_KB)` && echo $$(($$n)) || echo 0))
diff --git a/tmk_core/common/avr/platform_deps.h b/platforms/avr/platform_deps.h
index 45d9dcebfa..45d9dcebfa 100644
--- a/tmk_core/common/avr/platform_deps.h
+++ b/platforms/avr/platform_deps.h
diff --git a/tmk_core/common/avr/printf.c b/platforms/avr/printf.c
index 9ad7a38693..9ad7a38693 100644
--- a/tmk_core/common/avr/printf.c
+++ b/platforms/avr/printf.c
diff --git a/tmk_core/common/avr/printf.mk b/platforms/avr/printf.mk
index 060ad88c57..060ad88c57 100644
--- a/tmk_core/common/avr/printf.mk
+++ b/platforms/avr/printf.mk
diff --git a/tmk_core/common/avr/sleep_led.c b/platforms/avr/sleep_led.c
index 9a3b52abe5..9a3b52abe5 100644
--- a/tmk_core/common/avr/sleep_led.c
+++ b/platforms/avr/sleep_led.c
diff --git a/tmk_core/common/avr/suspend.c b/platforms/avr/suspend.c
index 690d7f38ca..b614746e6c 100644
--- a/tmk_core/common/avr/suspend.c
+++ b/platforms/avr/suspend.c
@@ -16,25 +16,6 @@
# include "vusb.h"
#endif
-#ifdef BACKLIGHT_ENABLE
-# include "backlight.h"
-#endif
-
-#ifdef AUDIO_ENABLE
-# include "audio.h"
-#endif /* AUDIO_ENABLE */
-
-#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
-# include "rgblight.h"
-#endif
-
-#ifdef LED_MATRIX_ENABLE
-# include "led_matrix.h"
-#endif
-#ifdef RGB_MATRIX_ENABLE
-# include "rgb_matrix.h"
-#endif
-
/** \brief Suspend idle
*
* FIXME: needs doc
@@ -50,17 +31,6 @@ void suspend_idle(uint8_t time) {
// TODO: This needs some cleanup
-/** \brief Run keyboard level Power down
- *
- * FIXME: needs doc
- */
-__attribute__((weak)) void suspend_power_down_user(void) {}
-/** \brief Run keyboard level Power down
- *
- * FIXME: needs doc
- */
-__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
-
#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)
// clang-format off
@@ -135,41 +105,9 @@ void suspend_power_down(void) {
if (!vusb_suspended) return;
#endif
- suspend_power_down_kb();
+ suspend_power_down_quantum();
#ifndef NO_SUSPEND_POWER_DOWN
- // Turn off backlight
-# ifdef BACKLIGHT_ENABLE
- backlight_set(0);
-# endif
-
- // Turn off LED indicators
- uint8_t leds_off = 0;
-# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
- if (is_backlight_enabled()) {
- // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
- leds_off |= (1 << USB_LED_CAPS_LOCK);
- }
-# endif
- led_set(leds_off);
-
- // Turn off audio
-# ifdef AUDIO_ENABLE
- stop_all_notes();
-# endif
-
- // Turn off underglow
-# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
- rgblight_suspend();
-# endif
-
-# if defined(LED_MATRIX_ENABLE)
- led_matrix_set_suspend_state(true);
-# endif
-# if defined(RGB_MATRIX_ENABLE)
- rgb_matrix_set_suspend_state(true);
-# endif
-
// Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt)
# if defined(WDT_vect)
power_down(WDTO_15MS);
@@ -189,18 +127,6 @@ bool suspend_wakeup_condition(void) {
return false;
}
-/** \brief run user level code immediately after wakeup
- *
- * FIXME: needs doc
- */
-__attribute__((weak)) void suspend_wakeup_init_user(void) {}
-
-/** \brief run keyboard level code immediately after wakeup
- *
- * FIXME: needs doc
- */
-__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
-
/** \brief run immediately after wakeup
*
* FIXME: needs doc
@@ -209,27 +135,7 @@ void suspend_wakeup_init(void) {
// clear keyboard state
clear_keyboard();
- // Turn on backlight
-#ifdef BACKLIGHT_ENABLE
- backlight_init();
-#endif
-
- // Restore LED indicators
- led_set(host_keyboard_leds());
-
- // Wake up underglow
-#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
- rgblight_wakeup();
-#endif
-
-#if defined(LED_MATRIX_ENABLE)
- led_matrix_set_suspend_state(false);
-#endif
-#if defined(RGB_MATRIX_ENABLE)
- rgb_matrix_set_suspend_state(false);
-#endif
-
- suspend_wakeup_init_kb();
+ suspend_wakeup_init_quantum();
}
#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)
diff --git a/tmk_core/common/avr/timer.c b/platforms/avr/timer.c
index c2e6c6e081..c2e6c6e081 100644
--- a/tmk_core/common/avr/timer.c
+++ b/platforms/avr/timer.c
diff --git a/tmk_core/common/avr/timer_avr.h b/platforms/avr/timer_avr.h
index c1b726bd01..c1b726bd01 100644
--- a/tmk_core/common/avr/timer_avr.h
+++ b/platforms/avr/timer_avr.h
diff --git a/tmk_core/common/avr/xprintf.S b/platforms/avr/xprintf.S
index c5a414c35c..c5a414c35c 100644
--- a/tmk_core/common/avr/xprintf.S
+++ b/platforms/avr/xprintf.S
diff --git a/tmk_core/common/avr/xprintf.h b/platforms/avr/xprintf.h
index 80834f1714..80834f1714 100644
--- a/tmk_core/common/avr/xprintf.h
+++ b/platforms/avr/xprintf.h
diff --git a/tmk_core/common/bootloader.h b/platforms/bootloader.h
index 25ebd95288..25ebd95288 100644
--- a/tmk_core/common/bootloader.h
+++ b/platforms/bootloader.h
diff --git a/tmk_core/common/chibios/_timer.h b/platforms/chibios/_timer.h
index 77402b612a..77402b612a 100644
--- a/tmk_core/common/chibios/_timer.h
+++ b/platforms/chibios/_timer.h
diff --git a/tmk_core/common/chibios/_wait.c b/platforms/chibios/_wait.c
index 1fbea2dd5e..1fbea2dd5e 100644
--- a/tmk_core/common/chibios/_wait.c
+++ b/platforms/chibios/_wait.c
diff --git a/tmk_core/common/chibios/_wait.h b/platforms/chibios/_wait.h
index b740afbd24..2f36c64a2e 100644
--- a/tmk_core/common/chibios/_wait.h
+++ b/platforms/chibios/_wait.h
@@ -43,8 +43,6 @@ void wait_us(uint16_t duration);
#include "_wait.c"
-#define CPU_CLOCK STM32_SYSCLK
-
/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus
* to which the GPIO is connected.
* The connected buses differ depending on the various series of MCUs.
diff --git a/tmk_core/common/chibios/atomic_util.h b/platforms/chibios/atomic_util.h
index 8975045153..8975045153 100644
--- a/tmk_core/common/chibios/atomic_util.h
+++ b/platforms/chibios/atomic_util.h
diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/mcuconf.h b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/mcuconf.h
index ba6e934fe7..a21fd7bd12 100644
--- a/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/mcuconf.h
+++ b/platforms/chibios/boards/BLACKPILL_STM32_F401/configs/mcuconf.h
@@ -1,5 +1,5 @@
/*
- ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2006..2020 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.
@@ -32,11 +32,15 @@
*/
#define STM32F4xx_MCUCONF
+#define STM32F401_MCUCONF
/*
* HAL driver system settings.
*/
#define STM32_NO_INIT FALSE
+#define STM32_PVD_ENABLE FALSE
+#define STM32_PLS STM32_PLS_LEV0
+#define STM32_BKPRAM_ENABLE FALSE
#define STM32_HSI_ENABLED TRUE
#define STM32_LSI_ENABLED TRUE
#define STM32_HSE_ENABLED TRUE
@@ -44,13 +48,13 @@
#define STM32_CLOCK48_REQUIRED TRUE
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
-#define STM32_PLLM_VALUE 25
-#define STM32_PLLN_VALUE 336
-#define STM32_PLLP_VALUE 4
-#define STM32_PLLQ_VALUE 7
-#define STM32_HPRE STM32_HPRE_DIV1
-#define STM32_PPRE1 STM32_PPRE1_DIV4
-#define STM32_PPRE2 STM32_PPRE2_DIV2
+#define STM32_PLLM_VALUE 25
+#define STM32_PLLN_VALUE 336
+#define STM32_PLLP_VALUE 4
+#define STM32_PLLQ_VALUE 7
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE1 STM32_PPRE1_DIV4
+#define STM32_PPRE2 STM32_PPRE2_DIV2
#define STM32_RTCSEL STM32_RTCSEL_LSI
#define STM32_RTCPRE_VALUE 8
#define STM32_MCO1SEL STM32_MCO1SEL_HSI
@@ -60,9 +64,6 @@
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5
-#define STM32_PVD_ENABLE FALSE
-#define STM32_PLS STM32_PLS_LEV0
-#define STM32_BKPRAM_ENABLE FALSE
/*
* IRQ system settings.
@@ -82,6 +83,19 @@
#define STM32_IRQ_EXTI21_PRIORITY 15
#define STM32_IRQ_EXTI22_PRIORITY 15
+#define STM32_IRQ_TIM1_BRK_TIM9_PRIORITY 7
+#define STM32_IRQ_TIM1_UP_TIM10_PRIORITY 7
+#define STM32_IRQ_TIM1_TRGCO_TIM11_PRIORITY 7
+#define STM32_IRQ_TIM1_CC_PRIORITY 7
+#define STM32_IRQ_TIM2_PRIORITY 7
+#define STM32_IRQ_TIM3_PRIORITY 7
+#define STM32_IRQ_TIM4_PRIORITY 7
+#define STM32_IRQ_TIM5_PRIORITY 7
+
+#define STM32_IRQ_USART1_PRIORITY 12
+#define STM32_IRQ_USART2_PRIORITY 12
+#define STM32_IRQ_USART6_PRIORITY 12
+
/*
* ADC driver system settings.
*/
@@ -101,14 +115,8 @@
#define STM32_GPT_USE_TIM4 FALSE
#define STM32_GPT_USE_TIM5 FALSE
#define STM32_GPT_USE_TIM9 FALSE
+#define STM32_GPT_USE_TIM10 FALSE
#define STM32_GPT_USE_TIM11 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_TIM9_IRQ_PRIORITY 7
-#define STM32_GPT_TIM11_IRQ_PRIORITY 7
/*
* I2C driver system settings.
@@ -155,29 +163,20 @@
#define STM32_ICU_USE_TIM4 FALSE
#define STM32_ICU_USE_TIM5 FALSE
#define STM32_ICU_USE_TIM9 FALSE
-#define STM32_ICU_TIM1_IRQ_PRIORITY 7
-#define STM32_ICU_TIM2_IRQ_PRIORITY 7
-#define STM32_ICU_TIM3_IRQ_PRIORITY 7
-#define STM32_ICU_TIM4_IRQ_PRIORITY 7
-#define STM32_ICU_TIM5_IRQ_PRIORITY 7
-#define STM32_ICU_TIM9_IRQ_PRIORITY 7
+#define STM32_ICU_USE_TIM10 FALSE
+#define STM32_ICU_USE_TIM11 FALSE
/*
* PWM driver system settings.
*/
-#define STM32_PWM_USE_ADVANCED FALSE
#define STM32_PWM_USE_TIM1 FALSE
#define STM32_PWM_USE_TIM2 FALSE
#define STM32_PWM_USE_TIM3 FALSE
#define STM32_PWM_USE_TIM4 FALSE
#define STM32_PWM_USE_TIM5 FALSE
#define STM32_PWM_USE_TIM9 FALSE
-#define STM32_PWM_TIM1_IRQ_PRIORITY 7
-#define STM32_PWM_TIM2_IRQ_PRIORITY 7
-#define STM32_PWM_TIM3_IRQ_PRIORITY 7
-#define STM32_PWM_TIM4_IRQ_PRIORITY 7
-#define STM32_PWM_TIM5_IRQ_PRIORITY 7
-#define STM32_PWM_TIM9_IRQ_PRIORITY 7
+#define STM32_PWM_USE_TIM10 FALSE
+#define STM32_PWM_USE_TIM11 FALSE
/*
* SERIAL driver system settings.
@@ -185,9 +184,6 @@
#define STM32_SERIAL_USE_USART1 FALSE
#define STM32_SERIAL_USE_USART2 FALSE
#define STM32_SERIAL_USE_USART6 FALSE
-#define STM32_SERIAL_USART1_PRIORITY 12
-#define STM32_SERIAL_USART2_PRIORITY 12
-#define STM32_SERIAL_USART6_PRIORITY 12
/*
* SPI driver system settings.
@@ -227,9 +223,6 @@
#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
-#define STM32_UART_USART1_IRQ_PRIORITY 12
-#define STM32_UART_USART2_IRQ_PRIORITY 12
-#define STM32_UART_USART6_IRQ_PRIORITY 12
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART6_DMA_PRIORITY 0
@@ -241,9 +234,7 @@
#define STM32_USB_USE_OTG1 TRUE
#define STM32_USB_OTG1_IRQ_PRIORITY 14
#define STM32_USB_OTG1_RX_FIFO_SIZE 512
-#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1
-#define STM32_USB_OTG_THREAD_STACK_SIZE 128
-#define STM32_USB_OTGFIFO_FILL_BASEPRI 0
+#define STM32_USB_HOST_WAKEUP_DURATION 2
/*
* WDG driver system settings.
diff --git a/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/mcuconf.h b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/mcuconf.h
index 0394ff56bb..131c847661 100644
--- a/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/mcuconf.h
+++ b/platforms/chibios/boards/BLACKPILL_STM32_F411/configs/mcuconf.h
@@ -1,5 +1,5 @@
/*
- ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2006..2020 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.
@@ -32,11 +32,15 @@
*/
#define STM32F4xx_MCUCONF
+#define STM32F411_MCUCONF
/*
* HAL driver system settings.
*/
#define STM32_NO_INIT FALSE
+#define STM32_PVD_ENABLE FALSE
+#define STM32_PLS STM32_PLS_LEV0
+#define STM32_BKPRAM_ENABLE FALSE
#define STM32_HSI_ENABLED TRUE
#define STM32_LSI_ENABLED TRUE
#define STM32_HSE_ENABLED TRUE
@@ -60,9 +64,6 @@
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5
-#define STM32_PVD_ENABLE FALSE
-#define STM32_PLS STM32_PLS_LEV0
-#define STM32_BKPRAM_ENABLE FALSE
/*
* IRQ system settings.
@@ -82,6 +83,19 @@
#define STM32_IRQ_EXTI21_PRIORITY 15
#define STM32_IRQ_EXTI22_PRIORITY 15
+#define STM32_IRQ_TIM1_BRK_TIM9_PRIORITY 7
+#define STM32_IRQ_TIM1_UP_TIM10_PRIORITY 7
+#define STM32_IRQ_TIM1_TRGCO_TIM11_PRIORITY 7
+#define STM32_IRQ_TIM1_CC_PRIORITY 7
+#define STM32_IRQ_TIM2_PRIORITY 7
+#define STM32_IRQ_TIM3_PRIORITY 7
+#define STM32_IRQ_TIM4_PRIORITY 7
+#define STM32_IRQ_TIM5_PRIORITY 7
+
+#define STM32_IRQ_USART1_PRIORITY 12
+#define STM32_IRQ_USART2_PRIORITY 12
+#define STM32_IRQ_USART6_PRIORITY 12
+
/*
* ADC driver system settings.
*/
@@ -101,14 +115,8 @@
#define STM32_GPT_USE_TIM4 FALSE
#define STM32_GPT_USE_TIM5 FALSE
#define STM32_GPT_USE_TIM9 FALSE
+#define STM32_GPT_USE_TIM10 FALSE
#define STM32_GPT_USE_TIM11 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_TIM9_IRQ_PRIORITY 7
-#define STM32_GPT_TIM11_IRQ_PRIORITY 7
/*
* I2C driver system settings.
@@ -155,29 +163,28 @@
#define STM32_ICU_USE_TIM4 FALSE
#define STM32_ICU_USE_TIM5 FALSE
#define STM32_ICU_USE_TIM9 FALSE
-#define STM32_ICU_TIM1_IRQ_PRIORITY 7
-#define STM32_ICU_TIM2_IRQ_PRIORITY 7
-#define STM32_ICU_TIM3_IRQ_PRIORITY 7
-#define STM32_ICU_TIM4_IRQ_PRIORITY 7
-#define STM32_ICU_TIM5_IRQ_PRIORITY 7
-#define STM32_ICU_TIM9_IRQ_PRIORITY 7
+#define STM32_ICU_USE_TIM10 FALSE
+#define STM32_ICU_USE_TIM11 FALSE
/*
* PWM driver system settings.
*/
-#define STM32_PWM_USE_ADVANCED FALSE
#define STM32_PWM_USE_TIM1 FALSE
#define STM32_PWM_USE_TIM2 FALSE
#define STM32_PWM_USE_TIM3 FALSE
#define STM32_PWM_USE_TIM4 FALSE
#define STM32_PWM_USE_TIM5 FALSE
#define STM32_PWM_USE_TIM9 FALSE
-#define STM32_PWM_TIM1_IRQ_PRIORITY 7
-#define STM32_PWM_TIM2_IRQ_PRIORITY 7
-#define STM32_PWM_TIM3_IRQ_PRIORITY 7
-#define STM32_PWM_TIM4_IRQ_PRIORITY 7
-#define STM32_PWM_TIM5_IRQ_PRIORITY 7
-#define STM32_PWM_TIM9_IRQ_PRIORITY 7
+#define STM32_PWM_USE_TIM10 FALSE
+#define STM32_PWM_USE_TIM11 FALSE
+
+/*
+ * RTC driver system settings.
+ */
+#define STM32_RTC_PRESA_VALUE 32
+#define STM32_RTC_PRESS_VALUE 1024
+#define STM32_RTC_CR_INIT 0
+#define STM32_RTC_TAMPCR_INIT 0
/*
* SERIAL driver system settings.
@@ -185,9 +192,6 @@
#define STM32_SERIAL_USE_USART1 FALSE
#define STM32_SERIAL_USE_USART2 FALSE
#define STM32_SERIAL_USE_USART6 FALSE
-#define STM32_SERIAL_USART1_PRIORITY 12
-#define STM32_SERIAL_USART2_PRIORITY 12
-#define STM32_SERIAL_USART6_PRIORITY 12
/*
* SPI driver system settings.
@@ -227,9 +231,6 @@
#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
-#define STM32_UART_USART1_IRQ_PRIORITY 12
-#define STM32_UART_USART2_IRQ_PRIORITY 12
-#define STM32_UART_USART6_IRQ_PRIORITY 12
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART6_DMA_PRIORITY 0
@@ -241,9 +242,7 @@
#define STM32_USB_USE_OTG1 TRUE
#define STM32_USB_OTG1_IRQ_PRIORITY 14
#define STM32_USB_OTG1_RX_FIFO_SIZE 512
-#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1
-#define STM32_USB_OTG_THREAD_STACK_SIZE 128
-#define STM32_USB_OTGFIFO_FILL_BASEPRI 0
+#define STM32_USB_HOST_WAKEUP_DURATION 2
/*
* WDG driver system settings.
diff --git a/platforms/chibios/boards/GENERIC_STM32_F405XG/board/board.mk b/platforms/chibios/boards/GENERIC_STM32_F405XG/board/board.mk
new file mode 100644
index 0000000000..6c837bb8ee
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_STM32_F405XG/board/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC) \ No newline at end of file
diff --git a/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/board.h b/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/board.h
new file mode 100644
index 0000000000..8cb771bc12
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/board.h
@@ -0,0 +1,28 @@
+/* Copyright 2020 Nick Brassel (tzarc)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#define STM32_HSECLK 12000000
+// The following is required to disable the pull-down on PA9, when PA9 is used for the keyboard matrix:
+#define BOARD_OTG_NOVBUSSENS
+
+#include_next "board.h"
+
+#undef STM32_HSE_BYPASS
+
+#undef STM32F407xx
+#define STM32F405xG
+#define STM32F405xx
diff --git a/drivers/qwiic/qwiic.c b/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/config.h
index 316d6539cb..cc52a953ed 100644
--- a/drivers/qwiic/qwiic.c
+++ b/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/config.h
@@ -1,4 +1,4 @@
-/* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
+/* Copyright 2021 Andrei Purdea
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,19 +13,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "qwiic.h"
-void qwiic_init(void) {
-#ifdef QWIIC_JOYSTIIC_ENABLE
- joystiic_init();
-#endif
-#ifdef QWIIC_MICRO_OLED_ENABLE
- micro_oled_init();
-#endif
-}
-
-void qwiic_task(void) {
-#ifdef QWIIC_JOYSTIIC_ENABLE
- joystiic_task();
+/* Address for jumping to bootloader on STM32 chips. */
+/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.
+ */
+#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
+#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
+# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
#endif
-}
diff --git a/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/mcuconf.h
new file mode 100644
index 0000000000..908a580a91
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_STM32_F405XG/configs/mcuconf.h
@@ -0,0 +1,352 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef MCUCONF_H
+#define MCUCONF_H
+
+/*
+ * STM32F4xx drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the whole
+ * driver is enabled in halconf.h.
+ *
+ * IRQ priorities:
+ * 15...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...3 Lowest...Highest.
+ */
+
+#define STM32F4xx_MCUCONF
+#define STM32F405_MCUCONF
+#define STM32F415_MCUCONF
+#define STM32F407_MCUCONF
+#define STM32F417_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+#define STM32_NO_INIT FALSE
+#define STM32_PVD_ENABLE FALSE
+#define STM32_PLS STM32_PLS_LEV0
+#define STM32_BKPRAM_ENABLE FALSE
+#define STM32_HSI_ENABLED TRUE
+#define STM32_LSI_ENABLED TRUE
+#define STM32_HSE_ENABLED TRUE
+#define STM32_LSE_ENABLED FALSE
+#define STM32_CLOCK48_REQUIRED TRUE
+#define STM32_SW STM32_SW_PLL
+#define STM32_PLLSRC STM32_PLLSRC_HSE
+#define STM32_PLLM_VALUE 12
+#define STM32_PLLN_VALUE 336
+#define STM32_PLLP_VALUE 2
+#define STM32_PLLQ_VALUE 7
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE1 STM32_PPRE1_DIV4
+#define STM32_PPRE2 STM32_PPRE2_DIV2
+#define STM32_RTCSEL STM32_RTCSEL_LSI
+#define STM32_RTCPRE_VALUE 8
+#define STM32_MCO1SEL STM32_MCO1SEL_HSI
+#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
+#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
+#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
+#define STM32_I2SSRC STM32_I2SSRC_CKIN
+#define STM32_PLLI2SN_VALUE 192
+#define STM32_PLLI2SR_VALUE 5
+
+/*
+ * IRQ system settings.
+ */
+#define STM32_IRQ_EXTI0_PRIORITY 6
+#define STM32_IRQ_EXTI1_PRIORITY 6
+#define STM32_IRQ_EXTI2_PRIORITY 6
+#define STM32_IRQ_EXTI3_PRIORITY 6
+#define STM32_IRQ_EXTI4_PRIORITY 6
+#define STM32_IRQ_EXTI5_9_PRIORITY 6
+#define STM32_IRQ_EXTI10_15_PRIORITY 6
+#define STM32_IRQ_EXTI16_PRIORITY 6
+#define STM32_IRQ_EXTI17_PRIORITY 15
+#define STM32_IRQ_EXTI18_PRIORITY 6
+#define STM32_IRQ_EXTI19_PRIORITY 6
+#define STM32_IRQ_EXTI20_PRIORITY 6
+#define STM32_IRQ_EXTI21_PRIORITY 15
+#define STM32_IRQ_EXTI22_PRIORITY 15
+
+/*
+ * ADC driver system settings.
+ */
+#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4
+#define STM32_ADC_USE_ADC1 FALSE
+#define STM32_ADC_USE_ADC2 FALSE
+#define STM32_ADC_USE_ADC3 FALSE
+#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
+#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
+#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#define STM32_ADC_ADC2_DMA_PRIORITY 2
+#define STM32_ADC_ADC3_DMA_PRIORITY 2
+#define STM32_ADC_IRQ_PRIORITY 6
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6
+#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6
+#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6
+
+/*
+ * CAN driver system settings.
+ */
+#define STM32_CAN_USE_CAN1 FALSE
+#define STM32_CAN_USE_CAN2 FALSE
+#define STM32_CAN_CAN1_IRQ_PRIORITY 11
+#define STM32_CAN_CAN2_IRQ_PRIORITY 11
+
+/*
+ * DAC driver system settings.
+ */
+#define STM32_DAC_DUAL_MODE FALSE
+#define STM32_DAC_USE_DAC1_CH1 FALSE
+#define STM32_DAC_USE_DAC1_CH2 FALSE
+#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
+#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
+#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
+#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
+#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
+#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
+
+/*
+ * GPT driver system settings.
+ */
+#define STM32_GPT_USE_TIM1 FALSE
+#define STM32_GPT_USE_TIM2 FALSE
+#define STM32_GPT_USE_TIM3 FALSE
+#define STM32_GPT_USE_TIM4 FALSE
+#define STM32_GPT_USE_TIM5 FALSE
+#define STM32_GPT_USE_TIM6 FALSE
+#define STM32_GPT_USE_TIM7 FALSE
+#define STM32_GPT_USE_TIM8 FALSE
+#define STM32_GPT_USE_TIM9 FALSE
+#define STM32_GPT_USE_TIM11 FALSE
+#define STM32_GPT_USE_TIM12 FALSE
+#define STM32_GPT_USE_TIM14 FALSE
+#define STM32_GPT_TIM1_IRQ_PRIORITY 7
+#define STM32_GPT_TIM2_IRQ_PRIORITY 7
+#define STM32_GPT_TIM3_IRQ_PRIORITY 7
+#define STM32_GPT_TIM4_IRQ_PRIORITY 7
+#define STM32_GPT_TIM5_IRQ_PRIORITY 7
+#define STM32_GPT_TIM6_IRQ_PRIORITY 7
+#define STM32_GPT_TIM7_IRQ_PRIORITY 7
+#define STM32_GPT_TIM8_IRQ_PRIORITY 7
+#define STM32_GPT_TIM9_IRQ_PRIORITY 7
+#define STM32_GPT_TIM11_IRQ_PRIORITY 7
+#define STM32_GPT_TIM12_IRQ_PRIORITY 7
+#define STM32_GPT_TIM14_IRQ_PRIORITY 7
+
+/*
+ * I2C driver system settings.
+ */
+#define STM32_I2C_USE_I2C1 FALSE
+#define STM32_I2C_USE_I2C2 FALSE
+#define STM32_I2C_USE_I2C3 FALSE
+#define STM32_I2C_BUSY_TIMEOUT 50
+#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
+#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
+#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
+#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
+#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
+#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+#define STM32_I2C_I2C1_IRQ_PRIORITY 5
+#define STM32_I2C_I2C2_IRQ_PRIORITY 5
+#define STM32_I2C_I2C3_IRQ_PRIORITY 5
+#define STM32_I2C_I2C1_DMA_PRIORITY 3
+#define STM32_I2C_I2C2_DMA_PRIORITY 3
+#define STM32_I2C_I2C3_DMA_PRIORITY 3
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+
+/*
+ * I2S driver system settings.
+ */
+#define STM32_I2S_USE_SPI2 FALSE
+#define STM32_I2S_USE_SPI3 FALSE
+#define STM32_I2S_SPI2_IRQ_PRIORITY 10
+#define STM32_I2S_SPI3_IRQ_PRIORITY 10
+#define STM32_I2S_SPI2_DMA_PRIORITY 1
+#define STM32_I2S_SPI3_DMA_PRIORITY 1
+#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
+#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
+#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
+#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure")
+
+/*
+ * ICU driver system settings.
+ */
+#define STM32_ICU_USE_TIM1 FALSE
+#define STM32_ICU_USE_TIM2 FALSE
+#define STM32_ICU_USE_TIM3 FALSE
+#define STM32_ICU_USE_TIM4 FALSE
+#define STM32_ICU_USE_TIM5 FALSE
+#define STM32_ICU_USE_TIM8 FALSE
+#define STM32_ICU_USE_TIM9 FALSE
+#define STM32_ICU_TIM1_IRQ_PRIORITY 7
+#define STM32_ICU_TIM2_IRQ_PRIORITY 7
+#define STM32_ICU_TIM3_IRQ_PRIORITY 7
+#define STM32_ICU_TIM4_IRQ_PRIORITY 7
+#define STM32_ICU_TIM5_IRQ_PRIORITY 7
+#define STM32_ICU_TIM8_IRQ_PRIORITY 7
+#define STM32_ICU_TIM9_IRQ_PRIORITY 7
+
+/*
+ * MAC driver system settings.
+ */
+#define STM32_MAC_TRANSMIT_BUFFERS 2
+#define STM32_MAC_RECEIVE_BUFFERS 4
+#define STM32_MAC_BUFFERS_SIZE 1522
+#define STM32_MAC_PHY_TIMEOUT 100
+#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE
+#define STM32_MAC_ETH1_IRQ_PRIORITY 13
+#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0
+
+/*
+ * PWM driver system settings.
+ */
+#define STM32_PWM_USE_ADVANCED FALSE
+#define STM32_PWM_USE_TIM1 FALSE
+#define STM32_PWM_USE_TIM2 FALSE
+#define STM32_PWM_USE_TIM3 FALSE
+#define STM32_PWM_USE_TIM4 FALSE
+#define STM32_PWM_USE_TIM5 FALSE
+#define STM32_PWM_USE_TIM8 FALSE
+#define STM32_PWM_USE_TIM9 FALSE
+#define STM32_PWM_TIM1_IRQ_PRIORITY 7
+#define STM32_PWM_TIM2_IRQ_PRIORITY 7
+#define STM32_PWM_TIM3_IRQ_PRIORITY 7
+#define STM32_PWM_TIM4_IRQ_PRIORITY 7
+#define STM32_PWM_TIM5_IRQ_PRIORITY 7
+#define STM32_PWM_TIM8_IRQ_PRIORITY 7
+#define STM32_PWM_TIM9_IRQ_PRIORITY 7
+
+/*
+ * RTC driver system settings.
+ */
+#define STM32_RTC_PRESA_VALUE 32
+#define STM32_RTC_PRESS_VALUE 1024
+#define STM32_RTC_CR_INIT 0
+#define STM32_RTC_TAMPCR_INIT 0
+
+/*
+ * SDC driver system settings.
+ */
+#define STM32_SDC_SDIO_DMA_PRIORITY 3
+#define STM32_SDC_SDIO_IRQ_PRIORITY 9
+#define STM32_SDC_WRITE_TIMEOUT_MS 1000
+#define STM32_SDC_READ_TIMEOUT_MS 1000
+#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10
+#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE
+#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
+
+/*
+ * SERIAL driver system settings.
+ */
+#define STM32_SERIAL_USE_USART1 FALSE
+#define STM32_SERIAL_USE_USART2 FALSE
+#define STM32_SERIAL_USE_USART3 FALSE
+#define STM32_SERIAL_USE_UART4 FALSE
+#define STM32_SERIAL_USE_UART5 FALSE
+#define STM32_SERIAL_USE_USART6 FALSE
+#define STM32_SERIAL_USART1_PRIORITY 12
+#define STM32_SERIAL_USART2_PRIORITY 12
+#define STM32_SERIAL_USART3_PRIORITY 12
+#define STM32_SERIAL_UART4_PRIORITY 12
+#define STM32_SERIAL_UART5_PRIORITY 12
+#define STM32_SERIAL_USART6_PRIORITY 12
+
+/*
+ * SPI driver system settings.
+ */
+#define STM32_SPI_USE_SPI1 FALSE
+#define STM32_SPI_USE_SPI2 FALSE
+#define STM32_SPI_USE_SPI3 FALSE
+#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0)
+#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
+#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
+#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
+#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
+#define STM32_SPI_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_USE_UART4 FALSE
+#define STM32_UART_USE_UART5 FALSE
+#define STM32_UART_USE_USART6 FALSE
+#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
+#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
+#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
+#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
+#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
+#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
+#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
+#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
+#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
+#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
+#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
+#define STM32_UART_USART1_IRQ_PRIORITY 12
+#define STM32_UART_USART2_IRQ_PRIORITY 12
+#define STM32_UART_USART3_IRQ_PRIORITY 12
+#define STM32_UART_UART4_IRQ_PRIORITY 12
+#define STM32_UART_UART5_IRQ_PRIORITY 12
+#define STM32_UART_USART6_IRQ_PRIORITY 12
+#define STM32_UART_USART1_DMA_PRIORITY 0
+#define STM32_UART_USART2_DMA_PRIORITY 0
+#define STM32_UART_USART3_DMA_PRIORITY 0
+#define STM32_UART_UART4_DMA_PRIORITY 0
+#define STM32_UART_UART5_DMA_PRIORITY 0
+#define STM32_UART_USART6_DMA_PRIORITY 0
+#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+
+/*
+ * USB driver system settings.
+ */
+#define STM32_USB_USE_OTG1 TRUE
+#define STM32_USB_USE_OTG2 FALSE
+#define STM32_USB_OTG1_IRQ_PRIORITY 14
+#define STM32_USB_OTG2_IRQ_PRIORITY 14
+#define STM32_USB_OTG1_RX_FIFO_SIZE 512
+#define STM32_USB_OTG2_RX_FIFO_SIZE 1024
+#define STM32_USB_HOST_WAKEUP_DURATION 2
+
+/*
+ * WDG driver system settings.
+ */
+#define STM32_WDG_USE_IWDG FALSE
+
+#endif /* MCUCONF_H */
diff --git a/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/mcuconf.h
index 4be47fe1b0..928ee56c71 100644
--- a/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/mcuconf.h
+++ b/platforms/chibios/boards/GENERIC_STM32_F407XE/configs/mcuconf.h
@@ -344,9 +344,6 @@
#define STM32_USB_OTG2_RX_FIFO_SIZE 1024
#define STM32_USB_HOST_WAKEUP_DURATION 2
-#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1
-#define STM32_USB_OTG_THREAD_STACK_SIZE 128
-
/*
* WDG driver system settings.
*/
diff --git a/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/mcuconf.h
index d2de75590e..566c146c25 100644
--- a/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/mcuconf.h
+++ b/platforms/chibios/boards/GENERIC_STM32_F446XE/configs/mcuconf.h
@@ -1,5 +1,5 @@
/*
- ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2006..2020 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.
@@ -32,11 +32,15 @@
*/
#define STM32F4xx_MCUCONF
+#define STM32F446_MCUCONF
/*
* HAL driver system settings.
*/
#define STM32_NO_INIT FALSE
+#define STM32_PVD_ENABLE FALSE
+#define STM32_PLS STM32_PLS_LEV0
+#define STM32_BKPRAM_ENABLE FALSE
#define STM32_HSI_ENABLED FALSE
#define STM32_LSI_ENABLED TRUE
#define STM32_HSE_ENABLED TRUE
@@ -70,9 +74,6 @@
#define STM32_SAI1SEL STM32_SAI2SEL_PLLR
#define STM32_SAI2SEL STM32_SAI2SEL_PLLR
#define STM32_CK48MSEL STM32_CK48MSEL_PLLALT
-#define STM32_PVD_ENABLE FALSE
-#define STM32_PLS STM32_PLS_LEV0
-#define STM32_BKPRAM_ENABLE FALSE
/*
* IRQ system settings.
@@ -92,6 +93,30 @@
#define STM32_IRQ_EXTI21_PRIORITY 15
#define STM32_IRQ_EXTI22_PRIORITY 15
+#define STM32_IRQ_TIM1_BRK_TIM9_PRIORITY 7
+#define STM32_IRQ_TIM1_UP_TIM10_PRIORITY 7
+#define STM32_IRQ_TIM1_TRGCO_TIM11_PRIORITY 7
+#define STM32_IRQ_TIM1_CC_PRIORITY 7
+#define STM32_IRQ_TIM2_PRIORITY 7
+#define STM32_IRQ_TIM3_PRIORITY 7
+#define STM32_IRQ_TIM4_PRIORITY 7
+#define STM32_IRQ_TIM5_PRIORITY 7
+#define STM32_IRQ_TIM6_PRIORITY 7
+#define STM32_IRQ_TIM7_PRIORITY 7
+#define STM32_IRQ_TIM8_BRK_TIM12_PRIORITY 7
+#define STM32_IRQ_TIM8_UP_TIM13_PRIORITY 7
+#define STM32_IRQ_TIM8_TRGCO_TIM14_PRIORITY 7
+#define STM32_IRQ_TIM8_CC_PRIORITY 7
+
+#define STM32_IRQ_USART1_PRIORITY 12
+#define STM32_IRQ_USART2_PRIORITY 12
+#define STM32_IRQ_USART3_PRIORITY 12
+#define STM32_IRQ_UART4_PRIORITY 12
+#define STM32_IRQ_UART5_PRIORITY 12
+#define STM32_IRQ_USART6_PRIORITY 12
+#define STM32_IRQ_UART7_PRIORITY 12
+#define STM32_IRQ_UART8_PRIORITY 12
+
/*
* ADC driver system settings.
*/
@@ -143,21 +168,11 @@
#define STM32_GPT_USE_TIM7 FALSE
#define STM32_GPT_USE_TIM8 FALSE
#define STM32_GPT_USE_TIM9 FALSE
+#define STM32_GPT_USE_TIM10 FALSE
#define STM32_GPT_USE_TIM11 FALSE
#define STM32_GPT_USE_TIM12 FALSE
+#define STM32_GPT_USE_TIM13 FALSE
#define STM32_GPT_USE_TIM14 FALSE
-#define STM32_GPT_TIM1_IRQ_PRIORITY 7
-#define STM32_GPT_TIM2_IRQ_PRIORITY 7
-#define STM32_GPT_TIM3_IRQ_PRIORITY 7
-#define STM32_GPT_TIM4_IRQ_PRIORITY 7
-#define STM32_GPT_TIM5_IRQ_PRIORITY 7
-#define STM32_GPT_TIM6_IRQ_PRIORITY 7
-#define STM32_GPT_TIM7_IRQ_PRIORITY 7
-#define STM32_GPT_TIM8_IRQ_PRIORITY 7
-#define STM32_GPT_TIM9_IRQ_PRIORITY 7
-#define STM32_GPT_TIM11_IRQ_PRIORITY 7
-#define STM32_GPT_TIM12_IRQ_PRIORITY 7
-#define STM32_GPT_TIM14_IRQ_PRIORITY 7
/*
* I2C driver system settings.
@@ -205,13 +220,11 @@
#define STM32_ICU_USE_TIM5 FALSE
#define STM32_ICU_USE_TIM8 FALSE
#define STM32_ICU_USE_TIM9 FALSE
-#define STM32_ICU_TIM1_IRQ_PRIORITY 7
-#define STM32_ICU_TIM2_IRQ_PRIORITY 7
-#define STM32_ICU_TIM3_IRQ_PRIORITY 7
-#define STM32_ICU_TIM4_IRQ_PRIORITY 7
-#define STM32_ICU_TIM5_IRQ_PRIORITY 7
-#define STM32_ICU_TIM8_IRQ_PRIORITY 7
-#define STM32_ICU_TIM9_IRQ_PRIORITY 7
+#define STM32_ICU_USE_TIM10 FALSE
+#define STM32_ICU_USE_TIM11 FALSE
+#define STM32_ICU_USE_TIM12 FALSE
+#define STM32_ICU_USE_TIM13 FALSE
+#define STM32_ICU_USE_TIM14 FALSE
/*
* MAC driver system settings.
@@ -227,7 +240,6 @@
/*
* 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
@@ -235,13 +247,19 @@
#define STM32_PWM_USE_TIM5 FALSE
#define STM32_PWM_USE_TIM8 FALSE
#define STM32_PWM_USE_TIM9 FALSE
-#define STM32_PWM_TIM1_IRQ_PRIORITY 7
-#define STM32_PWM_TIM2_IRQ_PRIORITY 7
-#define STM32_PWM_TIM3_IRQ_PRIORITY 7
-#define STM32_PWM_TIM4_IRQ_PRIORITY 7
-#define STM32_PWM_TIM5_IRQ_PRIORITY 7
-#define STM32_PWM_TIM8_IRQ_PRIORITY 7
-#define STM32_PWM_TIM9_IRQ_PRIORITY 7
+#define STM32_PWM_USE_TIM10 FALSE
+#define STM32_PWM_USE_TIM11 FALSE
+#define STM32_PWM_USE_TIM12 FALSE
+#define STM32_PWM_USE_TIM13 FALSE
+#define STM32_PWM_USE_TIM14 FALSE
+
+/*
+ * RTC driver system settings.
+ */
+#define STM32_RTC_PRESA_VALUE 32
+#define STM32_RTC_PRESS_VALUE 1024
+#define STM32_RTC_CR_INIT 0
+#define STM32_RTC_TAMPCR_INIT 0
/*
* SDC driver system settings.
@@ -265,14 +283,6 @@
#define STM32_SERIAL_USE_USART6 FALSE
#define STM32_SERIAL_USE_UART7 FALSE
#define STM32_SERIAL_USE_UART8 FALSE
-#define STM32_SERIAL_USART1_PRIORITY 12
-#define STM32_SERIAL_USART2_PRIORITY 12
-#define STM32_SERIAL_USART3_PRIORITY 12
-#define STM32_SERIAL_UART4_PRIORITY 12
-#define STM32_SERIAL_UART5_PRIORITY 12
-#define STM32_SERIAL_USART6_PRIORITY 12
-#define STM32_SERIAL_UART7_PRIORITY 12
-#define STM32_SERIAL_UART8_PRIORITY 12
/*
* SPI driver system settings.
@@ -281,6 +291,8 @@
#define STM32_SPI_USE_SPI2 FALSE
#define STM32_SPI_USE_SPI3 FALSE
#define STM32_SPI_USE_SPI4 FALSE
+#define STM32_SPI_USE_SPI5 FALSE
+#define STM32_SPI_USE_SPI6 FALSE
#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0)
#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
@@ -289,14 +301,22 @@
#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
#define STM32_SPI_SPI4_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0)
#define STM32_SPI_SPI4_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
+#define STM32_SPI_SPI5_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
+#define STM32_SPI_SPI5_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
+#define STM32_SPI_SPI6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6)
+#define STM32_SPI_SPI6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
#define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1
#define STM32_SPI_SPI3_DMA_PRIORITY 1
#define STM32_SPI_SPI4_DMA_PRIORITY 1
+#define STM32_SPI_SPI5_DMA_PRIORITY 1
+#define STM32_SPI_SPI6_DMA_PRIORITY 1
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
#define STM32_SPI_SPI4_IRQ_PRIORITY 10
+#define STM32_SPI_SPI5_IRQ_PRIORITY 10
+#define STM32_SPI_SPI6_IRQ_PRIORITY 10
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
/*
@@ -326,12 +346,6 @@
#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
-#define STM32_UART_USART1_IRQ_PRIORITY 12
-#define STM32_UART_USART2_IRQ_PRIORITY 12
-#define STM32_UART_USART3_IRQ_PRIORITY 12
-#define STM32_UART_UART4_IRQ_PRIORITY 12
-#define STM32_UART_UART5_IRQ_PRIORITY 12
-#define STM32_UART_USART6_IRQ_PRIORITY 12
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_USART3_DMA_PRIORITY 0
@@ -349,9 +363,7 @@
#define STM32_USB_OTG2_IRQ_PRIORITY 14
#define STM32_USB_OTG1_RX_FIFO_SIZE 512
#define STM32_USB_OTG2_RX_FIFO_SIZE 1024
-#define STM32_USB_OTG_THREAD_PRIO LOWPRIO
-#define STM32_USB_OTG_THREAD_STACK_SIZE 128
-#define STM32_USB_OTGFIFO_FILL_BASEPRI 0
+#define STM32_USB_HOST_WAKEUP_DURATION 2
/*
* WDG driver system settings.
diff --git a/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/mcuconf.h
index 182d4885d7..d115028300 100644
--- a/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/mcuconf.h
+++ b/platforms/chibios/boards/GENERIC_STM32_G431XB/configs/mcuconf.h
@@ -40,9 +40,24 @@
*/
#define STM32_NO_INIT FALSE
#define STM32_VOS STM32_VOS_RANGE1
+#define STM32_PWR_BOOST TRUE
#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0)
#define STM32_PWR_CR3 (PWR_CR3_EIWF)
#define STM32_PWR_CR4 (0U)
+#define STM32_PWR_PUCRA (0U)
+#define STM32_PWR_PDCRA (0U)
+#define STM32_PWR_PUCRB (0U)
+#define STM32_PWR_PDCRB (0U)
+#define STM32_PWR_PUCRC (0U)
+#define STM32_PWR_PDCRC (0U)
+#define STM32_PWR_PUCRD (0U)
+#define STM32_PWR_PDCRD (0U)
+#define STM32_PWR_PUCRE (0U)
+#define STM32_PWR_PDCRE (0U)
+#define STM32_PWR_PUCRF (0U)
+#define STM32_PWR_PDCRF (0U)
+#define STM32_PWR_PUCRG (0U)
+#define STM32_PWR_PDCRG (0U)
#define STM32_HSI16_ENABLED TRUE
#define STM32_HSI48_ENABLED TRUE
#define STM32_HSE_ENABLED FALSE
diff --git a/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/mcuconf.h
index 117e920e3b..5710e2cb45 100644
--- a/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/mcuconf.h
+++ b/platforms/chibios/boards/GENERIC_STM32_G474XE/configs/mcuconf.h
@@ -42,9 +42,24 @@
*/
#define STM32_NO_INIT FALSE
#define STM32_VOS STM32_VOS_RANGE1
+#define STM32_PWR_BOOST TRUE
#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0)
#define STM32_PWR_CR3 (PWR_CR3_EIWF)
#define STM32_PWR_CR4 (0U)
+#define STM32_PWR_PUCRA (0U)
+#define STM32_PWR_PDCRA (0U)
+#define STM32_PWR_PUCRB (0U)
+#define STM32_PWR_PDCRB (0U)
+#define STM32_PWR_PUCRC (0U)
+#define STM32_PWR_PDCRC (0U)
+#define STM32_PWR_PUCRD (0U)
+#define STM32_PWR_PDCRD (0U)
+#define STM32_PWR_PUCRE (0U)
+#define STM32_PWR_PDCRE (0U)
+#define STM32_PWR_PUCRF (0U)
+#define STM32_PWR_PDCRF (0U)
+#define STM32_PWR_PUCRG (0U)
+#define STM32_PWR_PDCRG (0U)
#define STM32_HSI16_ENABLED TRUE
#define STM32_HSI48_ENABLED TRUE
#define STM32_HSE_ENABLED FALSE
diff --git a/platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.c b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.c
new file mode 100644
index 0000000000..e38a7e0054
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.c
@@ -0,0 +1,82 @@
+/*
+ Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd
+
+ 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"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void wb32_gpio_init(void) {
+
+#if WB32_HAS_GPIOA
+ rccEnableAPB1(RCC_APB1ENR_GPIOAEN);
+#endif
+
+#if WB32_HAS_GPIOB
+ rccEnableAPB1(RCC_APB1ENR_GPIOBEN);
+#endif
+
+#if WB32_HAS_GPIOC
+ rccEnableAPB1(RCC_APB1ENR_GPIOCEN);
+#endif
+
+#if WB32_HAS_GPIOD
+ rccEnableAPB1(RCC_APB1ENR_GPIODEN);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+/*
+ * Early initialization code.
+ * This initialization must be performed just after stack setup and before
+ * any other initialization.
+ */
+void __early_init(void) {
+
+ wb32_clock_init();
+ wb32_gpio_init();
+}
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.h b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.h
new file mode 100644
index 0000000000..51dc84db94
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.h
@@ -0,0 +1,56 @@
+#pragma once
+/*
+ Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd
+
+ 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 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define WB32F3G71x9
+#if !defined(WB32F3G71xx)
+ #define WB32F3G71xx
+#endif
+
+/*===========================================================================*/
+/* 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/boards/GENERIC_WB32_F3G71XX/board/board.mk b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.mk
new file mode 100644
index 0000000000..842e335905
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/board/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(BOARD_PATH)/board/board.c
+
+# Required include directories
+BOARDINC = $(BOARD_PATH)/board
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/bootloader_defs.h b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/bootloader_defs.h
new file mode 100644
index 0000000000..c929d2ad03
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/bootloader_defs.h
@@ -0,0 +1,12 @@
+/* Address for jumping to bootloader on WB32 chips. */
+/* It is chip dependent, the correct number can be looked up here:
+ * http://www.westberrytech.com/down/mcu/data/WB32F3G71xx_rm.pdf
+ */
+#ifndef WB32_BOOTLOADER_ADDRESS
+# undef STM32_BOOTLOADER_ADDRESS
+# define WB32_BOOTLOADER_ADDRESS 0x1FFFE000
+# define STM32_BOOTLOADER_ADDRESS WB32_BOOTLOADER_ADDRESS
+#else
+# undef STM32_BOOTLOADER_ADDRESS
+# define STM32_BOOTLOADER_ADDRESS WB32_BOOTLOADER_ADDRESS
+#endif
diff --git a/quantum/api/api_sysex.h b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/chconf.h
index eb0a18848d..e4afddb6a5 100644
--- a/quantum/api/api_sysex.h
+++ b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/chconf.h
@@ -1,4 +1,4 @@
-/* Copyright 2016 Jack Humbert
+/* 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
@@ -14,12 +14,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#pragma once
-
-#include "api.h"
+/*
+ * This file was auto-generated by:
+ * `qmk chibios-confmigrate -i platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/chconf.h -r platforms/chibios/boards/common/configs/chconf.h`
+ */
-#define API_SYSEX_MAX_SIZE 32
+#pragma once
-void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t* bytes, uint16_t length);
+#define CH_CFG_ST_TIMEDELTA 0
-#define SEND_BYTES(mt, dt, b, l) send_bytes_sysex(mt, dt, b, l)
+#include_next <chconf.h> \ No newline at end of file
diff --git a/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/config.h b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/config.h
new file mode 100644
index 0000000000..9fdc825669
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/config.h
@@ -0,0 +1,20 @@
+/* Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
+# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
+#endif
diff --git a/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/mcuconf.h
new file mode 100644
index 0000000000..7c1fdaf57d
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_WB32_F3G71XX/configs/mcuconf.h
@@ -0,0 +1,168 @@
+/*
+ Copyright (C) 2021 Westberry Technology (ChangZhou) Corp., Ltd
+
+ 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 WB32F3G71xx_MCUCONF TRUE
+
+/*
+ * WB32F3G71 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.
+ *
+ */
+
+/**
+ * @name Internal clock sources
+ * @{
+ */
+#define WB32_HSECLK 12000000
+#define WB32_LSECLK 32768
+
+/*
+ * HAL driver system settings.
+ */
+#define WB32_NO_INIT FALSE
+#define WB32_MHSI_ENABLED TRUE
+#define WB32_FHSI_ENABLED FALSE
+#define WB32_LSI_ENABLED FALSE
+#define WB32_HSE_ENABLED TRUE
+#define WB32_LSE_ENABLED FALSE
+#define WB32_PLL_ENABLED TRUE
+#define WB32_MAINCLKSRC WB32_MAINCLKSRC_PLL
+#define WB32_PLLSRC WB32_PLLSRC_HSE
+#define WB32_PLLDIV_VALUE 2
+#define WB32_PLLMUL_VALUE 12 //The allowed range is 12,16,20,24.
+#define WB32_HPRE 1
+#define WB32_PPRE1 1
+#define WB32_PPRE2 1
+#define WB32_USBPRE WB32_USBPRE_DIV1P5
+
+/*
+ * EXTI driver system settings.
+ */
+#define WB32_IRQ_EXTI0_PRIORITY 6
+#define WB32_IRQ_EXTI1_PRIORITY 6
+#define WB32_IRQ_EXTI2_PRIORITY 6
+#define WB32_IRQ_EXTI3_PRIORITY 6
+#define WB32_IRQ_EXTI4_PRIORITY 6
+#define WB32_IRQ_EXTI5_9_PRIORITY 6
+#define WB32_IRQ_EXTI10_15_PRIORITY 6
+#define WB32_IRQ_EXTI16_PRIORITY 6
+#define WB32_IRQ_EXTI17_PRIORITY 6
+#define WB32_IRQ_EXTI18_PRIORITY 6
+#define WB32_IRQ_EXTI19_PRIORITY 6
+
+/*
+ * GPT driver system settings.
+ */
+#define WB32_TIM_MAX_CHANNELS 4
+#define WB32_GPT_USE_TIM1 FALSE
+#define WB32_GPT_USE_TIM2 FALSE
+#define WB32_GPT_USE_TIM3 FALSE
+#define WB32_GPT_USE_TIM4 FALSE
+#define WB32_GPT_TIM1_IRQ_PRIORITY 7
+#define WB32_GPT_TIM2_IRQ_PRIORITY 7
+#define WB32_GPT_TIM3_IRQ_PRIORITY 7
+#define WB32_GPT_TIM4_IRQ_PRIORITY 7
+
+/*
+ * ICU driver system settings.
+ */
+#define WB32_ICU_USE_TIM1 FALSE
+#define WB32_ICU_USE_TIM2 FALSE
+#define WB32_ICU_USE_TIM3 FALSE
+#define WB32_ICU_USE_TIM4 FALSE
+#define WB32_ICU_TIM1_IRQ_PRIORITY 7
+#define WB32_ICU_TIM2_IRQ_PRIORITY 7
+#define WB32_ICU_TIM3_IRQ_PRIORITY 7
+#define WB32_ICU_TIM4_IRQ_PRIORITY 7
+
+/*
+ * PWM driver system settings.
+ */
+#define WB32_PWM_USE_ADVANCED FALSE
+#define WB32_PWM_USE_TIM1 FALSE
+#define WB32_PWM_USE_TIM2 FALSE
+#define WB32_PWM_USE_TIM3 FALSE
+#define WB32_PWM_USE_TIM4 FALSE
+#define WB32_PWM_TIM1_IRQ_PRIORITY 7
+#define WB32_PWM_TIM2_IRQ_PRIORITY 7
+#define WB32_PWM_TIM3_IRQ_PRIORITY 7
+#define WB32_PWM_TIM4_IRQ_PRIORITY 7
+
+/*
+ * I2C driver system settings.
+ */
+#define WB32_I2C_USE_I2C1 FALSE
+#define WB32_I2C_USE_I2C2 FALSE
+#define WB32_I2C_BUSY_TIMEOUT 50
+#define WB32_I2C_I2C1_IRQ_PRIORITY 5
+#define WB32_I2C_I2C2_IRQ_PRIORITY 5
+
+/*
+ * SERIAL driver system settings.
+ */
+#define WB32_SERIAL_USE_UART1 FALSE
+#define WB32_SERIAL_USE_UART2 FALSE
+#define WB32_SERIAL_USE_UART3 FALSE
+#define WB32_SERIAL_USART1_PRIORITY 12
+#define WB32_SERIAL_USART2_PRIORITY 12
+#define WB32_SERIAL_USART3_PRIORITY 12
+
+/*
+ * SPI driver system settings.
+ */
+#define WB32_SPI_USE_QSPI FALSE
+#define WB32_SPI_USE_SPIM2 FALSE
+#define WB32_SPI_USE_SPIS1 FALSE
+#define WB32_SPI_USE_SPIS2 FALSE
+#define WB32_SPI_QSPI_IRQ_PRIORITY 10
+#define WB32_SPI_SPIM2_IRQ_PRIORITY 10
+#define WB32_SPI_SPIS1_IRQ_PRIORITY 10
+#define WB32_SPI_SPIS2_IRQ_PRIORITY 10
+
+/*
+ * ST driver system settings.
+ */
+#define WB32_ST_IRQ_PRIORITY 8
+#define WB32_ST_USE_TIMER 2
+
+/*
+ * UART driver system settings.
+ */
+#define WB32_UART_USE_UART1 FALSE
+#define WB32_UART_USE_UART2 FALSE
+#define WB32_UART_USE_UART3 FALSE
+#define WB32_UART_UART1_IRQ_PRIORITY 12
+#define WB32_UART_UART2_IRQ_PRIORITY 12
+#define WB32_UART_UART3_IRQ_PRIORITY 12
+
+/*
+ * USB driver system settings.
+ */
+#define WB32_USB_USE_USB1 TRUE
+#define WB32_USB_USB1_IRQ_PRIORITY 13
+#define WB32_USB_HOST_WAKEUP_DURATION 10
+
+
+#endif /* MCUCONF_H */
diff --git a/platforms/chibios/boards/QMK_PROTON_C/configs/chconf.h b/platforms/chibios/boards/QMK_PROTON_C/configs/chconf.h
index a1cbf68086..f812332960 100644
--- a/platforms/chibios/boards/QMK_PROTON_C/configs/chconf.h
+++ b/platforms/chibios/boards/QMK_PROTON_C/configs/chconf.h
@@ -40,7 +40,7 @@
/**
* @brief System time counter resolution.
- * @note Allowed values are 16 or 32 bits.
+ * @note Allowed values are 16, 32 or 64 bits.
*/
#if !defined(CH_CFG_ST_RESOLUTION)
#define CH_CFG_ST_RESOLUTION 32
diff --git a/platforms/chibios/boards/QMK_PROTON_C/configs/config.h b/platforms/chibios/boards/QMK_PROTON_C/configs/config.h
index a73f0c0b47..fa1a73c354 100644
--- a/platforms/chibios/boards/QMK_PROTON_C/configs/config.h
+++ b/platforms/chibios/boards/QMK_PROTON_C/configs/config.h
@@ -18,3 +18,12 @@
#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
#endif
+
+#ifdef CONVERT_TO_PROTON_C
+# ifndef I2C1_SDA_PIN
+# define I2C1_SDA_PIN D1
+# endif
+# ifndef I2C1_SCL_PIN
+# define I2C1_SCL_PIN D0
+# endif
+#endif
diff --git a/platforms/chibios/boards/SIPEED_LONGAN_NANO/board/board.mk b/platforms/chibios/boards/SIPEED_LONGAN_NANO/board/board.mk
new file mode 100644
index 0000000000..960fc26786
--- /dev/null
+++ b/platforms/chibios/boards/SIPEED_LONGAN_NANO/board/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = ${CHIBIOS_CONTRIB}/os/hal/boards/SIPEED_LONGAN_NANO/board.c
+
+# Required include directories
+BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/SIPEED_LONGAN_NANO
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/quantum/visualizer/visualizer_keyframes.c b/platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/chconf.h
index 8f6a7e15a4..6e5adb0fe1 100644
--- a/quantum/visualizer/visualizer_keyframes.c
+++ b/platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/chconf.h
@@ -1,4 +1,4 @@
-/* Copyright 2017 Fred Sundvik
+/* Copyright 2021 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,10 +14,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "visualizer_keyframes.h"
+/* To compile the ChibiOS syscall stubs with picolibc
+ * the _reent struct has to be defined. */
+#if !defined(_FROM_ASM_) && defined(USE_PICOLIBC)
+struct _reent;
+#endif
-bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- return false;
-}
+#include_next <chconf.h> \ No newline at end of file
diff --git a/platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/mcuconf.h b/platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/mcuconf.h
new file mode 100644
index 0000000000..ab086567e5
--- /dev/null
+++ b/platforms/chibios/boards/SIPEED_LONGAN_NANO/configs/mcuconf.h
@@ -0,0 +1,302 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+ ChibiOS - Copyright (C) 2021 Stefan Kerkmann
+
+ 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.
+*/
+
+#pragma once
+
+#define GD32VF103_MCUCONF
+#define GD32VF103CB
+
+/*
+ * GD32VF103 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:
+ * 0...15 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...3 Lowest...Highest.
+ */
+
+/*
+ * HAL driver system settings.
+*/
+
+#if defined(OVERCLOCK_120MHZ)
+/* (8MHz / 2) * 30 = 120MHz Sysclock */
+#define GD32_ALLOW_120MHZ_SYSCLK
+#define GD32_PLLMF_VALUE 30
+#define GD32_USBFSPSC GD32_USBFSPSC_DIV2P5
+#else
+/* (8MHz / 2) * 24 = 96MHz Sysclock */
+#define GD32_PLLMF_VALUE 24
+#define GD32_USBFSPSC GD32_USBFSPSC_DIV2
+#endif
+
+#define GD32_NO_INIT FALSE
+#define GD32_IRC8M_ENABLED TRUE
+#define GD32_IRC40K_ENABLED FALSE
+#define GD32_HXTAL_ENABLED TRUE
+#define GD32_LXTAL_ENABLED FALSE
+#define GD32_SCS GD32_SCS_PLL
+#define GD32_PLLSEL GD32_PLLSEL_PREDV0
+#define GD32_PREDV0SEL GD32_PREDV0SEL_HXTAL
+#define GD32_PREDV0_VALUE 2
+#define GD32_PREDV1_VALUE 2
+#define GD32_PLL1MF_VALUE 14
+#define GD32_PLL2MF_VALUE 13
+#define GD32_AHBPSC GD32_AHBPSC_DIV1
+#define GD32_APB1PSC GD32_APB1PSC_DIV2
+#define GD32_APB2PSC GD32_APB2PSC_DIV1
+#define GD32_ADCPSC GD32_ADCPSC_DIV16
+#define GD32_USB_CLOCK_REQUIRED TRUE
+#define GD32_I2S_CLOCK_REQUIRED FALSE
+#define GD32_CKOUT0SEL GD32_CKOUT0SEL_NOCLOCK
+#define GD32_RTCSRC GD32_RTCSRC_NOCLOCK
+#define GD32_PVD_ENABLE FALSE
+#define GD32_LVDT GD32_LVDT_LEV0
+
+/*
+ * ECLIC system settings.
+ */
+#define ECLIC_TRIGGER_DEFAULT ECLIC_POSTIVE_EDGE_TRIGGER
+#define ECLIC_DMA_TRIGGER ECLIC_TRIGGER_DEFAULT
+
+/*
+ * IRQ system settings.
+ */
+#define GD32_IRQ_EXTI0_PRIORITY 6
+#define GD32_IRQ_EXTI1_PRIORITY 6
+#define GD32_IRQ_EXTI2_PRIORITY 6
+#define GD32_IRQ_EXTI3_PRIORITY 6
+#define GD32_IRQ_EXTI4_PRIORITY 6
+#define GD32_IRQ_EXTI5_9_PRIORITY 6
+#define GD32_IRQ_EXTI10_15_PRIORITY 6
+#define GD32_IRQ_EXTI0_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_IRQ_EXTI1_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_IRQ_EXTI2_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_IRQ_EXTI3_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_IRQ_EXTI4_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_IRQ_EXTI5_9_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_IRQ_EXTI10_15_TRIGGER ECLIC_TRIGGER_DEFAULT
+
+/*
+ * ADC driver system settings.
+ */
+#define GD32_ADC_USE_ADC0 FALSE
+#define GD32_ADC_ADC0_DMA_PRIORITY 2
+#define GD32_ADC_ADC0_IRQ_PRIORITY 6
+
+/*
+ * CAN driver system settings.
+ */
+#define GD32_CAN_USE_CAN0 FALSE
+#define GD32_CAN_CAN0_IRQ_PRIORITY 11
+#define GD32_CAN_USE_CAN1 FALSE
+#define GD32_CAN_CAN1_IRQ_PRIORITY 11
+#define GD32_CAN_CAN0_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_CAN_CAN1_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+
+/*
+ * CRC driver system settings.
+ */
+#define GD32_CRC_USE_CRC0 FALSE
+#define GD32_CRC_CRC0_DMA_IRQ_PRIORITY 14
+#define GD32_CRC_CRC0_DMA_PRIORITY 2
+#define GD32_CRC_CRC0_DMA_STREAM GD32_DMA_STREAM_ID(0, 0)
+#define CRC_USE_DMA FALSE
+#define CRCSW_USE_CRC1 FALSE
+#define CRCSW_CRC32_TABLE FALSE
+#define CRCSW_CRC16_TABLE FALSE
+#define CRCSW_PROGRAMMABLE FALSE
+
+/*
+ * DAC driver system settings.
+ */
+#define GD32_DAC_USE_DAC_CH1 FALSE
+#define GD32_DAC_USE_DAC_CH2 FALSE
+
+/*
+ * GPT driver system settings.
+ */
+#define GD32_GPT_USE_TIM0 FALSE
+#define GD32_GPT_USE_TIM1 FALSE
+#define GD32_GPT_USE_TIM2 FALSE
+#define GD32_GPT_USE_TIM3 FALSE
+#define GD32_GPT_USE_TIM4 FALSE
+#define GD32_GPT_TIM0_IRQ_PRIORITY 7
+#define GD32_GPT_TIM1_IRQ_PRIORITY 7
+#define GD32_GPT_TIM2_IRQ_PRIORITY 7
+#define GD32_GPT_TIM3_IRQ_PRIORITY 7
+#define GD32_GPT_TIM4_IRQ_PRIORITY 7
+#define GD32_GPT_TIM0_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_GPT_TIM1_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_GPT_TIM2_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_GPT_TIM3_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_GPT_TIM4_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_GPT_TIM5_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_GPT_TIM6_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+
+/*
+ * I2S driver system settings.
+ */
+#define GD32_I2S_USE_SPI1 FALSE
+#define GD32_I2S_USE_SPI2 FALSE
+#define GD32_I2S_SPI1_IRQ_PRIORITY 10
+#define GD32_I2S_SPI2_IRQ_PRIORITY 10
+#define GD32_I2S_SPI1_DMA_PRIORITY 1
+#define GD32_I2S_SPI2_DMA_PRIORITY 1
+#define GD32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure")
+
+/*
+ * I2C driver system settings.
+ */
+#define GD32_I2C_USE_I2C0 FALSE
+#define GD32_I2C_USE_I2C1 FALSE
+#define GD32_I2C_BUSY_TIMEOUT 50
+#define GD32_I2C_I2C0_IRQ_PRIORITY 10
+#define GD32_I2C_I2C1_IRQ_PRIORITY 5
+#define GD32_I2C_I2C0_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_I2C_I2C1_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_I2C_I2C0_DMA_PRIORITY 2
+#define GD32_I2C_I2C1_DMA_PRIORITY 2
+#define GD32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+
+/*
+ * ICU driver system settings.
+ */
+#define GD32_ICU_USE_TIM0 FALSE
+#define GD32_ICU_USE_TIM1 FALSE
+#define GD32_ICU_USE_TIM2 FALSE
+#define GD32_ICU_USE_TIM3 FALSE
+#define GD32_ICU_USE_TIM4 FALSE
+#define GD32_ICU_TIM0_IRQ_PRIORITY 7
+#define GD32_ICU_TIM1_IRQ_PRIORITY 7
+#define GD32_ICU_TIM2_IRQ_PRIORITY 7
+#define GD32_ICU_TIM3_IRQ_PRIORITY 7
+#define GD32_ICU_TIM4_IRQ_PRIORITY 7
+#define GD32_ICU_TIM0_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_ICU_TIM1_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_ICU_TIM2_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_ICU_TIM3_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_ICU_TIM4_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+
+/*
+ * PWM driver system settings.
+ */
+#define GD32_PWM_USE_ADVANCED FALSE
+#define GD32_PWM_USE_TIM0 FALSE
+#define GD32_PWM_USE_TIM1 FALSE
+#define GD32_PWM_USE_TIM2 FALSE
+#define GD32_PWM_USE_TIM3 FALSE
+#define GD32_PWM_USE_TIM4 FALSE
+#define GD32_PWM_TIM0_IRQ_PRIORITY 10
+#define GD32_PWM_TIM1_IRQ_PRIORITY 10
+#define GD32_PWM_TIM2_IRQ_PRIORITY 10
+#define GD32_PWM_TIM3_IRQ_PRIORITY 10
+#define GD32_PWM_TIM4_IRQ_PRIORITY 10
+#define GD32_PWM_TIM0_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_PWM_TIM1_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_PWM_TIM2_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_PWM_TIM3_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_PWM_TIM4_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+
+/*
+ * RTC driver system settings.
+ */
+#define GD32_RTC_IRQ_PRIORITY 15
+#define GD32_RTC_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+
+/*
+ * SERIAL driver system settings.
+ */
+#define GD32_SERIAL_USE_USART0 FALSE
+#define GD32_SERIAL_USE_USART1 FALSE
+#define GD32_SERIAL_USE_USART2 FALSE
+#define GD32_SERIAL_USE_UART3 FALSE
+#define GD32_SERIAL_USE_UART4 FALSE
+#define GD32_SERIAL_USART0_PRIORITY 10
+#define GD32_SERIAL_USART1_PRIORITY 10
+#define GD32_SERIAL_USART2_PRIORITY 10
+#define GD32_SERIAL_UART3_PRIORITY 10
+#define GD32_SERIAL_UART4_PRIORITY 10
+#define GD32_SERIAL_USART0_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_SERIAL_USART1_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_SERIAL_USART2_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_SERIAL_UART3_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_SERIAL_UART4_TRIGGER ECLIC_TRIGGER_DEFAULT
+
+/*
+ * SPI driver system settings.
+ */
+#define GD32_SPI_USE_SPI0 FALSE
+#define GD32_SPI_USE_SPI1 FALSE
+#define GD32_SPI_USE_SPI2 FALSE
+#define GD32_SPI_SPI0_DMA_PRIORITY 1
+#define GD32_SPI_SPI1_DMA_PRIORITY 1
+#define GD32_SPI_SPI2_DMA_PRIORITY 1
+#define GD32_SPI_SPI0_IRQ_PRIORITY 10
+#define GD32_SPI_SPI1_IRQ_PRIORITY 10
+#define GD32_SPI_SPI2_IRQ_PRIORITY 10
+#define GD32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+
+/*
+ * ST driver system settings.
+ */
+#define GD32_ST_IRQ_PRIORITY 10
+#define GD32_ST_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_ST_USE_TIMER 1
+
+/*
+ * UART driver system settings.
+ */
+#define GD32_UART_USE_USART0 FALSE
+#define GD32_UART_USE_USART1 FALSE
+#define GD32_UART_USE_USART2 FALSE
+#define GD32_UART_USE_UART3 FALSE
+#define GD32_UART_USE_UART4 FALSE
+#define GD32_UART_USART0_IRQ_PRIORITY 10
+#define GD32_UART_USART1_IRQ_PRIORITY 10
+#define GD32_UART_USART2_IRQ_PRIORITY 10
+#define GD32_UART_UART3_IRQ_PRIORITY 10
+#define GD32_UART_UART4_IRQ_PRIORITY 10
+#define GD32_UART_USART0_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_UART_USART1_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_UART_USART2_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_UART_UART3_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_UART_UART4_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_UART_USART0_DMA_PRIORITY 3
+#define GD32_UART_USART1_DMA_PRIORITY 3
+#define GD32_UART_USART2_DMA_PRIORITY 3
+#define GD32_UART_UART3_DMA_PRIORITY 3
+#define GD32_UART_UART4_DMA_PRIORITY 3
+#define GD32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+
+/*
+ * USB driver system settings.
+ */
+#define GD32_USB_USE_USBFS TRUE
+#define GD32_USB_USBFS_IRQ_PRIORITY 10
+#define GD32_USB_USBFS_IRQ_TRIGGER ECLIC_TRIGGER_DEFAULT
+#define GD32_USB_USBFS_RX_FIFO_SIZE 256
+
+/*
+ * WDG driver system settings.
+ */
+#define GD32_WDG_USE_FWDGT FALSE
diff --git a/platforms/chibios/boards/common/configs/chconf.h b/platforms/chibios/boards/common/configs/chconf.h
index 44327a82d7..18ad609ca1 100644
--- a/platforms/chibios/boards/common/configs/chconf.h
+++ b/platforms/chibios/boards/common/configs/chconf.h
@@ -40,7 +40,7 @@
/**
* @brief System time counter resolution.
- * @note Allowed values are 16 or 32 bits.
+ * @note Allowed values are 16, 32 or 64 bits.
*/
#if !defined(CH_CFG_ST_RESOLUTION)
#define CH_CFG_ST_RESOLUTION 32
diff --git a/platforms/chibios/boards/common/ld/STM32F401xC.ld b/platforms/chibios/boards/common/ld/STM32F401xC.ld
new file mode 100644
index 0000000000..8fae66cec9
--- /dev/null
+++ b/platforms/chibios/boards/common/ld/STM32F401xC.ld
@@ -0,0 +1,85 @@
+/*
+ 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.
+*/
+
+/*
+ * STM32F401xC memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 16k /* Sector 0 - Init code as ROM bootloader assumes application starts here */
+ flash1 (rx) : org = 0x08004000, len = 16k /* Sector 1 - Emulated eeprom */
+ flash2 (rx) : org = 0x08008000, len = 256k - 32k /* Sector 2..6 - Rest of firmware */
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 64k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash2);
+REGION_ALIAS("XTORS_FLASH_LMA", flash2);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash2);
+REGION_ALIAS("TEXT_FLASH_LMA", flash2);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash2);
+REGION_ALIAS("RODATA_FLASH_LMA", flash2);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash2);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash2);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash2);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/platforms/chibios/boards/common/ld/STM32F401xE.ld b/platforms/chibios/boards/common/ld/STM32F401xE.ld
new file mode 100644
index 0000000000..69af7ed71e
--- /dev/null
+++ b/platforms/chibios/boards/common/ld/STM32F401xE.ld
@@ -0,0 +1,85 @@
+/*
+ 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.
+*/
+
+/*
+ * STM32F401xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 16k /* Sector 0 - Init code as ROM bootloader assumes application starts here */
+ flash1 (rx) : org = 0x08004000, len = 16k /* Sector 1 - Emulated eeprom */
+ flash2 (rx) : org = 0x08008000, len = 512k - 32k /* Sector 2..7 - Rest of firmware */
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 96k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash2);
+REGION_ALIAS("XTORS_FLASH_LMA", flash2);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash2);
+REGION_ALIAS("TEXT_FLASH_LMA", flash2);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash2);
+REGION_ALIAS("RODATA_FLASH_LMA", flash2);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash2);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash2);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash2);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/platforms/chibios/boards/common/ld/STM32F405xG.ld b/platforms/chibios/boards/common/ld/STM32F405xG.ld
new file mode 100644
index 0000000000..b7d0baa210
--- /dev/null
+++ b/platforms/chibios/boards/common/ld/STM32F405xG.ld
@@ -0,0 +1,86 @@
+/*
+ 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.
+*/
+
+/*
+ * STM32F405xG memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 16k /* Sector 0 - Init code as ROM bootloader assumes application starts here */
+ flash1 (rx) : org = 0x08004000, len = 16k /* Sector 1 - Emulated eeprom */
+ flash2 (rx) : org = 0x08008000, len = 1M - 32k /* Sector 2..6 - Rest of firmware */
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20000000, len = 112k /* SRAM1 */
+ ram2 (wx) : org = 0x2001C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 64k /* CCM SRAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash2);
+REGION_ALIAS("XTORS_FLASH_LMA", flash2);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash2);
+REGION_ALIAS("TEXT_FLASH_LMA", flash2);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash2);
+REGION_ALIAS("RODATA_FLASH_LMA", flash2);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash2);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash2);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash2);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/platforms/chibios/boards/common/ld/STM32F411xE.ld b/platforms/chibios/boards/common/ld/STM32F411xE.ld
new file mode 100644
index 0000000000..aea8084b51
--- /dev/null
+++ b/platforms/chibios/boards/common/ld/STM32F411xE.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F411xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 16k /* Sector 0 - Init code as ROM bootloader assumes application starts here */
+ flash1 (rx) : org = 0x08004000, len = 16k /* Sector 1 - Emulated eeprom */
+ flash2 (rx) : org = 0x08008000, len = 512k - 32k /* Sector 2..7 - Rest of firmware */
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash2);
+REGION_ALIAS("XTORS_FLASH_LMA", flash2);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash2);
+REGION_ALIAS("TEXT_FLASH_LMA", flash2);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash2);
+REGION_ALIAS("RODATA_FLASH_LMA", flash2);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash2);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash2);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash2);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/tmk_core/common/chibios/bootloader.c b/platforms/chibios/bootloader.c
index f9514ee5f3..5cadadeeeb 100644
--- a/tmk_core/common/chibios/bootloader.c
+++ b/platforms/chibios/bootloader.c
@@ -95,6 +95,28 @@ void enter_bootloader_mode_if_requested(void) {
}
}
+#elif defined(GD32VF103)
+
+# define DBGMCU_KEY_UNLOCK 0x4B5A6978
+# define DBGMCU_CMD_RESET 0x1
+
+__IO uint32_t *DBGMCU_KEY = (uint32_t *)DBGMCU_BASE + 0x0CU;
+__IO uint32_t *DBGMCU_CMD = (uint32_t *)DBGMCU_BASE + 0x08U;
+
+__attribute__((weak)) void bootloader_jump(void) {
+ /* The MTIMER unit of the GD32VF103 doesn't have the MSFRST
+ * register to generate a software reset request.
+ * BUT instead two undocumented registers in the debug peripheral
+ * that allow issueing a software reset. WHO would need the MSFRST
+ * register anyway? Source:
+ * https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h */
+ *DBGMCU_KEY = DBGMCU_KEY_UNLOCK;
+ *DBGMCU_CMD = DBGMCU_CMD_RESET;
+}
+
+void enter_bootloader_mode_if_requested(void) { /* Jumping to bootloader is not possible from user code. */
+}
+
#elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS
/* Kinetis */
diff --git a/platforms/chibios/chibios_config.h b/platforms/chibios/chibios_config.h
new file mode 100644
index 0000000000..4e35736606
--- /dev/null
+++ b/platforms/chibios/chibios_config.h
@@ -0,0 +1,90 @@
+/* Copyright 2019
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#ifndef USB_VBUS_PIN
+# define SPLIT_USB_DETECT // Force this on when dedicated pin is not used
+#endif
+
+// STM32 compatibility
+#if defined(MCU_STM32)
+# define CPU_CLOCK STM32_SYSCLK
+
+# if defined(STM32F1XX)
+# define USE_GPIOV1
+# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_STM32_ALTERNATE_OPENDRAIN
+# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_STM32_ALTERNATE_PUSHPULL
+# else
+# define PAL_OUTPUT_TYPE_OPENDRAIN PAL_STM32_OTYPE_OPENDRAIN
+# define PAL_OUTPUT_TYPE_PUSHPULL PAL_STM32_OTYPE_PUSHPULL
+# define PAL_OUTPUT_SPEED_HIGHEST PAL_STM32_OSPEED_HIGHEST
+# define PAL_PUPDR_FLOATING PAL_STM32_PUPDR_FLOATING
+# endif
+
+# if defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32L1XX)
+# define USE_I2CV1
+# endif
+#endif
+
+// GD32 compatibility
+#if defined(MCU_GD32V)
+# define CPU_CLOCK GD32_SYSCLK
+
+# if defined(GD32VF103)
+# define USE_GPIOV1
+# define USE_I2CV1
+# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_GD32_ALTERNATE_OPENDRAIN
+# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_GD32_ALTERNATE_PUSHPULL
+# endif
+#endif
+
+// WB32 compatibility
+#if defined(MCU_WB32)
+# define CPU_CLOCK WB32_MAINCLK
+
+# if defined(WB32F3G71xx)
+# define PAL_OUTPUT_TYPE_OPENDRAIN PAL_WB32_OTYPE_OPENDRAIN
+# define PAL_OUTPUT_TYPE_PUSHPULL PAL_WB32_OTYPE_PUSHPULL
+# define PAL_OUTPUT_SPEED_HIGHEST PAL_WB32_OSPEED_HIGH
+# define PAL_PUPDR_FLOATING PAL_WB32_PUPDR_FLOATING
+# endif
+#endif
+
+#if defined(GD32VF103)
+/* This chip has the same API as STM32F103, but uses different names for literally the same thing.
+ * As of 4.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake
+ * we just redefine the GD32 names. */
+# include "gd32v_compatibility.h"
+#endif
+
+// teensy compatibility
+#if defined(MCU_KINETIS)
+# define CPU_CLOCK KINETIS_SYSCLK_FREQUENCY
+
+# if defined(K20x) || defined(KL2x)
+# define USE_I2CV1
+# define USE_I2CV1_CONTRIB // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed
+# define USE_GPIOV1
+# endif
+#endif
+
+#if defined(HT32)
+# define CPU_CLOCK HT32_CK_SYS_FREQUENCY
+# define PAL_MODE_ALTERNATE PAL_HT32_MODE_AF
+# define PAL_OUTPUT_TYPE_OPENDRAIN (PAL_HT32_MODE_OD | PAL_HT32_MODE_DIR)
+# define PAL_OUTPUT_TYPE_PUSHPULL PAL_HT32_MODE_DIR
+# define PAL_OUTPUT_SPEED_HIGHEST 0
+#endif
diff --git a/platforms/chibios/drivers/analog.c b/platforms/chibios/drivers/analog.c
index 8c476fcac2..eb437665f1 100644
--- a/platforms/chibios/drivers/analog.c
+++ b/platforms/chibios/drivers/analog.c
@@ -38,7 +38,7 @@
// Otherwise assume V3
#if defined(STM32F0XX) || defined(STM32L0XX)
# define USE_ADCV1
-#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX)
+#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(GD32VF103)
# define USE_ADCV2
#endif
@@ -75,7 +75,7 @@
/* User configurable ADC options */
#ifndef ADC_COUNT
-# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX)
+# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX) || defined(GD32VF103)
# define ADC_COUNT 1
# elif defined(STM32F3XX)
# define ADC_COUNT 4
@@ -122,8 +122,8 @@ static ADCConversionGroup adcConversionGroup = {
.cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION,
.smpr = ADC_SAMPLING_RATE,
#elif defined(USE_ADCV2)
-# if !defined(STM32F1XX)
- .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
+# if !defined(STM32F1XX) && !defined(GD32VF103)
+ .cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
# endif
.smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE),
.smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE),
@@ -220,7 +220,7 @@ __attribute__((weak)) adc_mux pinToMux(pin_t pin) {
case F9: return TO_MUX( ADC_CHANNEL_IN7, 2 );
case F10: return TO_MUX( ADC_CHANNEL_IN8, 2 );
# endif
-#elif defined(STM32F1XX)
+#elif defined(STM32F1XX) || defined(GD32VF103)
case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 );
case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 );
case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 );
diff --git a/quantum/audio/driver_chibios_dac.h b/platforms/chibios/drivers/audio_dac.h
index 07cd622ead..07cd622ead 100644
--- a/quantum/audio/driver_chibios_dac.h
+++ b/platforms/chibios/drivers/audio_dac.h
diff --git a/quantum/audio/driver_chibios_dac_additive.c b/platforms/chibios/drivers/audio_dac_additive.c
index db304adb87..db304adb87 100644
--- a/quantum/audio/driver_chibios_dac_additive.c
+++ b/platforms/chibios/drivers/audio_dac_additive.c
diff --git a/quantum/audio/driver_chibios_dac_basic.c b/platforms/chibios/drivers/audio_dac_basic.c
index fac6513506..fac6513506 100644
--- a/quantum/audio/driver_chibios_dac_basic.c
+++ b/platforms/chibios/drivers/audio_dac_basic.c
diff --git a/quantum/audio/driver_chibios_pwm.h b/platforms/chibios/drivers/audio_pwm.h
index 86cab916e1..86cab916e1 100644
--- a/quantum/audio/driver_chibios_pwm.h
+++ b/platforms/chibios/drivers/audio_pwm.h
diff --git a/quantum/audio/driver_chibios_pwm_hardware.c b/platforms/chibios/drivers/audio_pwm_hardware.c
index 3c7d89b290..cd40019ee7 100644
--- a/quantum/audio/driver_chibios_pwm_hardware.c
+++ b/platforms/chibios/drivers/audio_pwm_hardware.c
@@ -109,9 +109,9 @@ void audio_driver_initialize(void) {
// connect the AUDIO_PIN to the PWM hardware
#if defined(USE_GPIOV1) // STM32F103C8
- palSetLineMode(AUDIO_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+ palSetLineMode(AUDIO_PIN, PAL_MODE_ALTERNATE_PUSHPULL);
#else // GPIOv2 (or GPIOv3 for f4xx, which is the same/compatible at this command)
- palSetLineMode(AUDIO_PIN, PAL_STM32_MODE_ALTERNATE | PAL_STM32_ALTERNATE(AUDIO_PWM_PAL_MODE));
+ palSetLineMode(AUDIO_PIN, PAL_MODE_ALTERNATE(AUDIO_PWM_PAL_MODE));
#endif
gptStart(&AUDIO_STATE_TIMER, &gptCFG);
diff --git a/quantum/audio/driver_chibios_pwm_software.c b/platforms/chibios/drivers/audio_pwm_software.c
index 15c3e98b6a..15c3e98b6a 100644
--- a/quantum/audio/driver_chibios_pwm_software.c
+++ b/platforms/chibios/drivers/audio_pwm_software.c
diff --git a/platforms/chibios/drivers/i2c_master.c b/platforms/chibios/drivers/i2c_master.c
index fc4bb2ab37..43591d56f8 100644
--- a/platforms/chibios/drivers/i2c_master.c
+++ b/platforms/chibios/drivers/i2c_master.c
@@ -38,6 +38,9 @@ static const I2CConfig i2cconfig = {
I2C1_OPMODE,
I2C1_CLOCK_SPEED,
I2C1_DUTY_CYCLE,
+#elif defined(WB32F3G71xx)
+ I2C1_OPMODE,
+ I2C1_CLOCK_SPEED,
#else
// This configures the I2C clock to 400khz assuming a 72Mhz clock
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
@@ -63,16 +66,16 @@ __attribute__((weak)) void i2c_init(void) {
is_initialised = true;
// 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);
+ palSetLineMode(I2C1_SCL_PIN, PAL_MODE_INPUT);
+ palSetLineMode(I2C1_SDA_PIN, 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);
+ palSetLineMode(I2C1_SCL_PIN, I2C1_SCL_PAL_MODE);
+ palSetLineMode(I2C1_SDA_PIN, 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);
+ palSetLineMode(I2C1_SCL_PIN, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_OUTPUT_TYPE_OPENDRAIN);
+ palSetLineMode(I2C1_SDA_PIN, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_OUTPUT_TYPE_OPENDRAIN);
#endif
}
}
@@ -102,7 +105,7 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,
i2cStart(&I2C_DRIVER, &i2cconfig);
uint8_t complete_packet[length + 1];
- for (uint8_t i = 0; i < length; i++) {
+ for (uint16_t i = 0; i < length; i++) {
complete_packet[i + 1] = data[i];
}
complete_packet[0] = regaddr;
@@ -111,6 +114,21 @@ i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data,
return chibios_to_qmk(&status);
}
+i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
+ i2c_address = devaddr;
+ i2cStart(&I2C_DRIVER, &i2cconfig);
+
+ uint8_t complete_packet[length + 2];
+ for (uint16_t i = 0; i < length; i++) {
+ complete_packet[i + 2] = data[i];
+ }
+ complete_packet[0] = regaddr >> 8;
+ complete_packet[1] = regaddr & 0xFF;
+
+ msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 2, 0, 0, TIME_MS2I(timeout));
+ return chibios_to_qmk(&status);
+}
+
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
i2c_address = devaddr;
i2cStart(&I2C_DRIVER, &i2cconfig);
@@ -118,4 +136,12 @@ i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16
return chibios_to_qmk(&status);
}
+i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
+ i2c_address = devaddr;
+ i2cStart(&I2C_DRIVER, &i2cconfig);
+ uint8_t register_packet[2] = {regaddr >> 8, regaddr & 0xFF};
+ msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), register_packet, 2, data, length, TIME_MS2I(timeout));
+ return chibios_to_qmk(&status);
+}
+
void i2c_stop(void) { i2cStop(&I2C_DRIVER); }
diff --git a/platforms/chibios/drivers/i2c_master.h b/platforms/chibios/drivers/i2c_master.h
index c68109acbd..5f082e9d1e 100644
--- a/platforms/chibios/drivers/i2c_master.h
+++ b/platforms/chibios/drivers/i2c_master.h
@@ -27,24 +27,11 @@
#include <ch.h>
#include <hal.h>
-#ifdef I2C1_BANK
-# define I2C1_SCL_BANK I2C1_BANK
-# define I2C1_SDA_BANK I2C1_BANK
+#ifndef I2C1_SCL_PIN
+# define I2C1_SCL_PIN B6
#endif
-
-#ifndef I2C1_SCL_BANK
-# define I2C1_SCL_BANK GPIOB
-#endif
-
-#ifndef I2C1_SDA_BANK
-# define I2C1_SDA_BANK GPIOB
-#endif
-
-#ifndef I2C1_SCL
-# define I2C1_SCL 6
-#endif
-#ifndef I2C1_SDA
-# define I2C1_SDA 7
+#ifndef I2C1_SDA_PIN
+# define I2C1_SDA_PIN B7
#endif
#ifdef USE_I2CV1
@@ -83,10 +70,10 @@
#ifdef USE_GPIOV1
# ifndef I2C1_SCL_PAL_MODE
-# define I2C1_SCL_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
+# define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN
# endif
# ifndef I2C1_SDA_PAL_MODE
-# define I2C1_SDA_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
+# define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN
# endif
#else
// The default PAL alternate modes are used to signal that the pins are used for I2C
@@ -109,5 +96,7 @@ i2c_status_t i2c_start(uint8_t address);
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_writeReg16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
+i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
void i2c_stop(void);
diff --git a/platforms/chibios/drivers/ps2/ps2_io.c b/platforms/chibios/drivers/ps2/ps2_io.c
new file mode 100644
index 0000000000..906d85d848
--- /dev/null
+++ b/platforms/chibios/drivers/ps2/ps2_io.c
@@ -0,0 +1,55 @@
+#include <stdbool.h>
+#include "ps2_io.h"
+
+// chibiOS headers
+#include "ch.h"
+#include "hal.h"
+
+/* Check port settings for clock and data line */
+#if !(defined(PS2_CLOCK_PIN))
+# error "PS/2 clock setting is required in config.h"
+#endif
+
+#if !(defined(PS2_DATA_PIN))
+# error "PS/2 data setting is required in config.h"
+#endif
+
+/*
+ * Clock
+ */
+void clock_init(void) {}
+
+void clock_lo(void) {
+ palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
+ palWriteLine(PS2_CLOCK_PIN, PAL_LOW);
+}
+
+void clock_hi(void) {
+ palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
+ palWriteLine(PS2_CLOCK_PIN, PAL_HIGH);
+}
+
+bool clock_in(void) {
+ palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_INPUT);
+ return palReadLine(PS2_CLOCK_PIN);
+}
+
+/*
+ * Data
+ */
+void data_init(void) {}
+
+void data_lo(void) {
+ palSetLineMode(PS2_DATA_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
+ palWriteLine(PS2_DATA_PIN, PAL_LOW);
+}
+
+void data_hi(void) {
+ palSetLineMode(PS2_DATA_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
+ palWriteLine(PS2_DATA_PIN, PAL_HIGH);
+}
+
+bool data_in(void) {
+ palSetLineMode(PS2_DATA_PIN, PAL_MODE_INPUT);
+ return palReadLine(PS2_DATA_PIN);
+}
diff --git a/platforms/chibios/drivers/serial.c b/platforms/chibios/drivers/serial.c
index f54fbcee4e..ef6f0aa8d5 100644
--- a/platforms/chibios/drivers/serial.c
+++ b/platforms/chibios/drivers/serial.c
@@ -19,7 +19,7 @@
# error "chSysPolledDelayX method not supported on this platform"
#else
# undef wait_us
-# define wait_us(x) chSysPolledDelayX(US2RTC(STM32_SYSCLK, x))
+# define wait_us(x) chSysPolledDelayX(US2RTC(CPU_CLOCK, x))
#endif
#ifndef SELECT_SOFT_SERIAL_SPEED
diff --git a/platforms/chibios/drivers/serial_usart.c b/platforms/chibios/drivers/serial_usart.c
index ea4473791c..124e4be685 100644
--- a/platforms/chibios/drivers/serial_usart.c
+++ b/platforms/chibios/drivers/serial_usart.c
@@ -104,9 +104,9 @@ static inline bool receive(uint8_t* destination, const size_t size) {
__attribute__((weak)) void usart_init(void) {
# if defined(MCU_STM32)
# if defined(USE_GPIOV1)
- palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
+ palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_OPENDRAIN);
# else
- palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
+ palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_OUTPUT_TYPE_OPENDRAIN);
# endif
# if defined(USART_REMAP)
@@ -125,11 +125,11 @@ __attribute__((weak)) void usart_init(void) {
__attribute__((weak)) void usart_init(void) {
# if defined(MCU_STM32)
# if defined(USE_GPIOV1)
- palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+ palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_PUSHPULL);
palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT);
# else
- palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
- palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_RX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
+ palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
+ palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_RX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
# endif
# if defined(USART_REMAP)
diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c
index 28ddcbb2ba..dde0bb0597 100644
--- a/platforms/chibios/drivers/spi_master.c
+++ b/platforms/chibios/drivers/spi_master.c
@@ -42,9 +42,9 @@ __attribute__((weak)) void spi_init(void) {
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_PAL_MODE);
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_PAL_MODE);
#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_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
+ palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
+ palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
#endif
}
}
@@ -54,6 +54,7 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
return false;
}
+#ifndef WB32F3G71xx
uint16_t roundedDivisor = 2;
while (roundedDivisor < divisor) {
roundedDivisor <<= 1;
@@ -62,6 +63,7 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
if (roundedDivisor < 2 || roundedDivisor > 256) {
return false;
}
+#endif
#if defined(K20x) || defined(KL2x)
spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1);
@@ -110,6 +112,62 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
spiConfig.tar0 |= SPIx_CTARn_BR(8);
break;
}
+
+#elif defined(HT32)
+ spiConfig.cr0 = SPI_CR0_SELOEN;
+ spiConfig.cr1 = SPI_CR1_MODE | 8; // 8 bits and in master mode
+
+ if (lsbFirst) {
+ spiConfig.cr1 |= SPI_CR1_FIRSTBIT;
+ }
+
+ switch (mode) {
+ case 0:
+ spiConfig.cr1 |= SPI_CR1_FORMAT_MODE0;
+ break;
+ case 1:
+ spiConfig.cr1 |= SPI_CR1_FORMAT_MODE1;
+ break;
+ case 2:
+ spiConfig.cr1 |= SPI_CR1_FORMAT_MODE2;
+ break;
+ case 3:
+ spiConfig.cr1 |= SPI_CR1_FORMAT_MODE3;
+ break;
+ }
+
+ spiConfig.cpr = (roundedDivisor - 1) >> 1;
+
+#elif defined(WB32F3G71xx)
+ if (!lsbFirst) {
+ osalDbgAssert(lsbFirst != FALSE, "unsupported lsbFirst");
+ }
+
+ if (divisor < 1) {
+ return false;
+ }
+
+ spiConfig.SPI_BaudRatePrescaler = (divisor << 2);
+
+ switch (mode) {
+ case 0:
+ spiConfig.SPI_CPHA = SPI_CPHA_1Edge;
+ spiConfig.SPI_CPOL = SPI_CPOL_Low;
+ break;
+ case 1:
+ spiConfig.SPI_CPHA = SPI_CPHA_2Edge;
+ spiConfig.SPI_CPOL = SPI_CPOL_Low;
+ break;
+ case 2:
+ spiConfig.SPI_CPHA = SPI_CPHA_1Edge;
+ spiConfig.SPI_CPOL = SPI_CPOL_High;
+ break;
+ case 3:
+ spiConfig.SPI_CPHA = SPI_CPHA_2Edge;
+ spiConfig.SPI_CPOL = SPI_CPOL_High;
+ break;
+ }
+
#else
spiConfig.cr1 = 0;
diff --git a/platforms/chibios/drivers/spi_master.h b/platforms/chibios/drivers/spi_master.h
index b5a6ef1437..6a3ce481f1 100644
--- a/platforms/chibios/drivers/spi_master.h
+++ b/platforms/chibios/drivers/spi_master.h
@@ -33,7 +33,7 @@
#ifndef SPI_SCK_PAL_MODE
# if defined(USE_GPIOV1)
-# define SPI_SCK_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
+# define SPI_SCK_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
# else
# define SPI_SCK_PAL_MODE 5
# endif
@@ -45,7 +45,7 @@
#ifndef SPI_MOSI_PAL_MODE
# if defined(USE_GPIOV1)
-# define SPI_MOSI_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
+# define SPI_MOSI_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
# else
# define SPI_MOSI_PAL_MODE 5
# endif
@@ -57,7 +57,7 @@
#ifndef SPI_MISO_PAL_MODE
# if defined(USE_GPIOV1)
-# define SPI_MISO_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
+# define SPI_MISO_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
# else
# define SPI_MISO_PAL_MODE 5
# endif
diff --git a/platforms/chibios/drivers/uart.c b/platforms/chibios/drivers/uart.c
index 030335b342..d2ea5d6415 100644
--- a/platforms/chibios/drivers/uart.c
+++ b/platforms/chibios/drivers/uart.c
@@ -18,7 +18,11 @@
#include "quantum.h"
+#if defined(WB32F3G71xx)
+static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_WRDLEN, SD1_STPBIT, SD1_PARITY, SD1_ATFLCT};
+#else
static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_CR1, SD1_CR2, SD1_CR3};
+#endif
void uart_init(uint32_t baud) {
static bool is_initialised = false;
@@ -29,22 +33,26 @@ void uart_init(uint32_t baud) {
serialConfig.speed = baud;
#if defined(USE_GPIOV1)
- palSetLineMode(SD1_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
- palSetLineMode(SD1_RX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
+ palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE_OPENDRAIN);
+ palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE_OPENDRAIN);
#else
- palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
- palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
+ palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_OUTPUT_TYPE_OPENDRAIN);
+ palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_OUTPUT_TYPE_OPENDRAIN);
#endif
sdStart(&SERIAL_DRIVER, &serialConfig);
}
}
-void uart_putchar(uint8_t c) { sdPut(&SERIAL_DRIVER, c); }
+void uart_write(uint8_t data) { sdPut(&SERIAL_DRIVER, c); }
-uint8_t uart_getchar(void) {
+uint8_t uart_read(void) {
msg_t res = sdGet(&SERIAL_DRIVER);
return (uint8_t)res;
}
+void uart_transmit(const uint8_t *data, uint16_t length) { sdWrite(&SERIAL_DRIVER, data, length); }
+
+void uart_receive(uint8_t *data, uint16_t length) { sdRead(&SERIAL_DRIVER, data, length); }
+
bool uart_available(void) { return !sdGetWouldBlock(&SERIAL_DRIVER); }
diff --git a/platforms/chibios/drivers/uart.h b/platforms/chibios/drivers/uart.h
index b4e20e9fd3..603d51037b 100644
--- a/platforms/chibios/drivers/uart.h
+++ b/platforms/chibios/drivers/uart.h
@@ -68,10 +68,30 @@
# define SD1_CR3 0
#endif
+#ifndef SD1_WRDLEN
+# define SD1_WRDLEN 3
+#endif
+
+#ifndef SD1_STPBIT
+# define SD1_STPBIT 0
+#endif
+
+#ifndef SD1_PARITY
+# define SD1_PARITY 0
+#endif
+
+#ifndef SD1_ATFLCT
+# define SD1_ATFLCT 0
+#endif
+
void uart_init(uint32_t baud);
-void uart_putchar(uint8_t c);
+void uart_write(uint8_t data);
+
+uint8_t uart_read(void);
+
+void uart_transmit(const uint8_t *data, uint16_t length);
-uint8_t uart_getchar(void);
+void uart_receive(uint8_t *data, uint16_t length);
bool uart_available(void);
diff --git a/platforms/chibios/drivers/ws2812.c b/platforms/chibios/drivers/ws2812.c
index 0d12e2fb79..7e870661de 100644
--- a/platforms/chibios/drivers/ws2812.c
+++ b/platforms/chibios/drivers/ws2812.c
@@ -6,7 +6,7 @@
/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
#ifndef NOP_FUDGE
-# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
+# if defined(STM32F0XX) || defined(STM32F1XX) || defined(GD32VF103) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
# define NOP_FUDGE 0.4
# else
# error("NOP_FUDGE configuration required")
@@ -22,8 +22,14 @@
# define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_OPENDRAIN
#endif
+// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased
+// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time.
+#ifndef WS2812_RES
+# define WS2812_RES (1000 * WS2812_TRST_US) // Width of the low gap between bits to cause a frame to latch
+#endif
+
#define NUMBER_NOPS 6
-#define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE)
+#define CYCLES_PER_SEC (CPU_CLOCK / NUMBER_NOPS * NOP_FUDGE)
#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC)
#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE)
@@ -40,19 +46,6 @@
} \
} while (0)
-// These are the timing constraints taken mostly from the WS2812 datasheets
-// These are chosen to be conservative and avoid problems rather than for maximum throughput
-
-#define T1H 900 // Width of a 1 bit in ns
-#define T1L (1250 - T1H) // Width of a 1 bit in ns
-
-#define T0H 350 // Width of a 0 bit in ns
-#define T0L (1250 - T0H) // Width of a 0 bit in ns
-
-// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased
-// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time.
-#define RES (1000 * WS2812_TRST_US) // Width of the low gap between bits to cause a frame to latch
-
void sendByte(uint8_t byte) {
// WS2812 protocol wants most significant bits first
for (unsigned char bit = 0; bit < 8; bit++) {
@@ -61,15 +54,15 @@ void sendByte(uint8_t byte) {
if (is_one) {
// 1
writePinHigh(RGB_DI_PIN);
- wait_ns(T1H);
+ wait_ns(WS2812_T1H);
writePinLow(RGB_DI_PIN);
- wait_ns(T1L);
+ wait_ns(WS2812_T1L);
} else {
// 0
writePinHigh(RGB_DI_PIN);
- wait_ns(T0H);
+ wait_ns(WS2812_T0H);
writePinLow(RGB_DI_PIN);
- wait_ns(T0L);
+ wait_ns(WS2812_T0L);
}
}
}
@@ -108,7 +101,7 @@ void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
#endif
}
- wait_ns(RES);
+ wait_ns(WS2812_RES);
chSysUnlock();
}
diff --git a/platforms/chibios/drivers/ws2812_pwm.c b/platforms/chibios/drivers/ws2812_pwm.c
index e6af55b6b3..19ea3cfe8a 100644
--- a/platforms/chibios/drivers/ws2812_pwm.c
+++ b/platforms/chibios/drivers/ws2812_pwm.c
@@ -5,7 +5,9 @@
/* Adapted from https://github.com/joewa/WS2812-LED-Driver_ChibiOS/ */
#ifdef RGBW
-# error "RGBW not supported"
+# define WS2812_CHANNELS 4
+#else
+# define WS2812_CHANNELS 3
#endif
#ifndef WS2812_PWM_DRIVER
@@ -40,15 +42,15 @@
// Default Push Pull
#ifndef WS2812_EXTERNAL_PULLUP
# if defined(USE_GPIOV1)
-# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
+# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE_PUSHPULL
# else
-# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING
+# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST | PAL_PUPDR_FLOATING
# endif
#else
# if defined(USE_GPIOV1)
-# define WS2812_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
+# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE_OPENDRAIN
# else
-# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING
+# define WS2812_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_PWM_PAL_MODE) | PAL_OUTPUT_TYPE_OPENDRAIN | PAL_OUTPUT_SPEED_HIGHEST | PAL_PUPDR_FLOATING
# endif
#endif
@@ -59,7 +61,7 @@
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
-#define WS2812_PWM_FREQUENCY (STM32_SYSCLK / 2) /**< Clock frequency of PWM, must be valid with respect to system clock! */
+#define WS2812_PWM_FREQUENCY (CPU_CLOCK / 2) /**< Clock frequency of PWM, must be valid with respect to system clock! */
#define WS2812_PWM_PERIOD (WS2812_PWM_FREQUENCY / WS2812_PWM_TARGET_PERIOD) /**< Clock period in ticks. 1 / 800kHz = 1.25 uS (as per datasheet) */
/**
@@ -68,8 +70,9 @@
* The reset period for each frame is defined in WS2812_TRST_US.
* Calculate the number of zeroes to add at the end assuming 1.25 uS/bit:
*/
-#define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / 1250)
-#define WS2812_COLOR_BIT_N (RGBLED_NUM * 24) /**< Number of data bits */
+#define WS2812_COLOR_BITS (WS2812_CHANNELS * 8)
+#define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / WS2812_TIMING)
+#define WS2812_COLOR_BIT_N (RGBLED_NUM * WS2812_COLOR_BITS) /**< Number of data bits */
#define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */
/**
@@ -114,7 +117,7 @@
*
* @return The bit index
*/
-#define WS2812_BIT(led, byte, bit) (24 * (led) + 8 * (byte) + (7 - (bit)))
+#define WS2812_BIT(led, byte, bit) (WS2812_COLOR_BITS * (led) + 8 * (byte) + (7 - (bit)))
#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
/**
@@ -228,6 +231,20 @@
# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 0, (bit))
#endif
+#ifdef RGBW
+/**
+ * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given white bit
+ *
+ * @note The white byte is the last byte in the color packet
+ *
+ * @param[in] led: The led index [0, @ref WS2812_LED_N)
+ * @param[in] bit: The bit index [0, 7]
+ *
+ * @return The bit index
+ */
+# define WS2812_WHITE_BIT(led, bit) WS2812_BIT((led), 3, (bit))
+#endif
+
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
static uint32_t ws2812_frame_buffer[WS2812_BIT_N + 1]; /**< Buffer for a frame */
@@ -296,6 +313,17 @@ void ws2812_write_led(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b) {
ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
}
}
+void ws2812_write_led_rgbw(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
+ // Write color to frame buffer
+ for (uint8_t bit = 0; bit < 8; bit++) {
+ ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
+ ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
+ ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
+#ifdef RGBW
+ ws2812_frame_buffer[WS2812_WHITE_BIT(led_number, bit)] = ((w >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
+#endif
+ }
+}
// Setleds for standard RGB
void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {
@@ -306,6 +334,10 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {
}
for (uint16_t i = 0; i < leds; i++) {
+#ifdef RGBW
+ ws2812_write_led_rgbw(i, ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w);
+#else
ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b);
+#endif
}
}
diff --git a/platforms/chibios/drivers/ws2812_spi.c b/platforms/chibios/drivers/ws2812_spi.c
index fe14b478ab..ba471e0b8e 100644
--- a/platforms/chibios/drivers/ws2812_spi.c
+++ b/platforms/chibios/drivers/ws2812_spi.c
@@ -3,10 +3,6 @@
/* Adapted from https://github.com/gamazeps/ws2812b-chibios-SPIDMA/ */
-#ifdef RGBW
-# error "RGBW not supported"
-#endif
-
// Define the spi your LEDs are plugged to here
#ifndef WS2812_SPI
# define WS2812_SPI SPID1
@@ -24,15 +20,15 @@
// Default Push Pull
#ifndef WS2812_EXTERNAL_PULLUP
# if defined(USE_GPIOV1)
-# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
+# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE_PUSHPULL
# else
-# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL
+# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL
# endif
#else
# if defined(USE_GPIOV1)
-# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
+# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE_OPENDRAIN
# else
-# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN
+# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_OUTPUT_TYPE_OPENDRAIN
# endif
#endif
@@ -68,16 +64,20 @@
#endif
#if defined(USE_GPIOV1)
-# define WS2812_SCK_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
+# define WS2812_SCK_OUTPUT_MODE PAL_MODE_ALTERNATE_PUSHPULL
#else
-# define WS2812_SCK_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL
+# define WS2812_SCK_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_SCK_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL
#endif
#define BYTES_FOR_LED_BYTE 4
-#define NB_COLORS 3
-#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS)
+#ifdef RGBW
+# define WS2812_CHANNELS 4
+#else
+# define WS2812_CHANNELS 3
+#endif
+#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * WS2812_CHANNELS)
#define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM)
-#define RESET_SIZE (1000 * WS2812_TRST_US / (2 * 1250))
+#define RESET_SIZE (1000 * WS2812_TRST_US / (2 * WS2812_TIMING))
#define PREAMBLE_SIZE 4
static uint8_t txbuf[PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE] = {0};
@@ -116,6 +116,9 @@ static void set_led_color_rgb(LED_TYPE color, int pos) {
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j);
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.r, j);
#endif
+#ifdef RGBW
+ for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 4 + j] = get_protocol_eq(color.w, j);
+#endif
}
void ws2812_init(void) {
diff --git a/platforms/chibios/drivers/wt_rgb_backlight.c b/platforms/chibios/drivers/wt_rgb_backlight.c
index 82b1fb2fb3..cc34a90c75 100644
--- a/platforms/chibios/drivers/wt_rgb_backlight.c
+++ b/platforms/chibios/drivers/wt_rgb_backlight.c
@@ -68,7 +68,7 @@ LED_TYPE g_ws2812_leds[WS2812_LED_TOTAL];
#include "progmem.h"
#include "quantum/color.h"
-#include "tmk_core/common/eeprom.h"
+#include "eeprom.h"
#include "via.h" // uses EEPROM address, lighting value IDs
#define RGB_BACKLIGHT_CONFIG_EEPROM_ADDR (VIA_EEPROM_CUSTOM_CONFIG_ADDR)
@@ -158,7 +158,7 @@ uint32_t g_any_key_hit = 0;
// ADDR_2 is not needed. it is here as a dummy
#define ISSI_ADDR_1 0x50
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -239,7 +239,7 @@ const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
#define ISSI_ADDR_1 0x50
#define ISSI_ADDR_2 0x52
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -382,7 +382,7 @@ const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
// set to 0 for write, 1 for read (as per I2C protocol)
#define ISSI_ADDR_1 0x74
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -414,7 +414,7 @@ const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
#define ISSI_ADDR_2 0x76 // 11101[10] <- SDA
#define ISSI_ADDR_3 0x75 // 11101[01] <- SCL
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -541,7 +541,7 @@ const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
#define ISSI_ADDR_1 0x74
#define ISSI_ADDR_2 0x76
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -622,7 +622,7 @@ const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
#define ISSI_ADDR_1 0x74
#define ISSI_ADDR_2 0x77
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
@@ -709,7 +709,7 @@ const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
#define ISSI_ADDR_1 0x74
#define ISSI_ADDR_2
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
{0, C1_9, C3_10, C4_10}, // LB1
{0, C1_10, C2_10, C4_11}, // LB2
{0, C1_11, C2_11, C3_11}, // LB3
@@ -729,7 +729,7 @@ const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
#define ISSI_ADDR_1 0x74
#define ISSI_ADDR_2 0x76
-const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
+const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/platforms/chibios/eeprom_stm32.c
index 1fdf8c1e29..acc6a48516 100644
--- a/tmk_core/common/chibios/eeprom_stm32.c
+++ b/platforms/chibios/eeprom_stm32.c
@@ -620,48 +620,11 @@ uint16_t EEPROM_ReadDataWord(uint16_t Address) {
}
/*****************************************************************************
- * Wrap library in AVR style functions.
+ * Bind to eeprom_driver.c
*******************************************************************************/
-uint8_t eeprom_read_byte(const uint8_t *Address) { return EEPROM_ReadDataByte((const uintptr_t)Address); }
+void eeprom_driver_init(void) { EEPROM_Init(); }
-void eeprom_write_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); }
-
-void eeprom_update_byte(uint8_t *Address, uint8_t Value) { EEPROM_WriteDataByte((uintptr_t)Address, Value); }
-
-uint16_t eeprom_read_word(const uint16_t *Address) { return EEPROM_ReadDataWord((const uintptr_t)Address); }
-
-void eeprom_write_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); }
-
-void eeprom_update_word(uint16_t *Address, uint16_t Value) { EEPROM_WriteDataWord((uintptr_t)Address, Value); }
-
-uint32_t eeprom_read_dword(const uint32_t *Address) {
- const uint16_t p = (const uintptr_t)Address;
- /* Check word alignment */
- if (p % 2) {
- /* Not aligned */
- return (uint32_t)EEPROM_ReadDataByte(p) | (uint32_t)(EEPROM_ReadDataWord(p + 1) << 8) | (uint32_t)(EEPROM_ReadDataByte(p + 3) << 24);
- } else {
- /* Aligned */
- return EEPROM_ReadDataWord(p) | (EEPROM_ReadDataWord(p + 2) << 16);
- }
-}
-
-void eeprom_write_dword(uint32_t *Address, uint32_t Value) {
- uint16_t p = (const uintptr_t)Address;
- /* Check word alignment */
- if (p % 2) {
- /* Not aligned */
- EEPROM_WriteDataByte(p, (uint8_t)Value);
- EEPROM_WriteDataWord(p + 1, (uint16_t)(Value >> 8));
- EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24));
- } else {
- /* Aligned */
- EEPROM_WriteDataWord(p, (uint16_t)Value);
- EEPROM_WriteDataWord(p + 2, (uint16_t)(Value >> 16));
- }
-}
-
-void eeprom_update_dword(uint32_t *Address, uint32_t Value) { eeprom_write_dword(Address, Value); }
+void eeprom_driver_erase(void) { EEPROM_Erase(); }
void eeprom_read_block(void *buf, const void *addr, size_t len) {
const uint8_t *src = (const uint8_t *)addr;
@@ -670,14 +633,14 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {
/* Check word alignment */
if (len && (uintptr_t)src % 2) {
/* Read the unaligned first byte */
- *dest++ = eeprom_read_byte(src++);
+ *dest++ = EEPROM_ReadDataByte((const uintptr_t)src++);
--len;
}
uint16_t value;
bool aligned = ((uintptr_t)dest % 2 == 0);
while (len > 1) {
- value = eeprom_read_word((uint16_t *)src);
+ value = EEPROM_ReadDataWord((const uintptr_t)((uint16_t *)src));
if (aligned) {
*(uint16_t *)dest = value;
dest += 2;
@@ -689,7 +652,7 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {
len -= 2;
}
if (len) {
- *dest = eeprom_read_byte(src);
+ *dest = EEPROM_ReadDataByte((const uintptr_t)src);
}
}
@@ -700,7 +663,7 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
/* Check word alignment */
if (len && (uintptr_t)dest % 2) {
/* Write the unaligned first byte */
- eeprom_write_byte(dest++, *src++);
+ EEPROM_WriteDataByte((uintptr_t)dest++, *src++);
--len;
}
@@ -712,15 +675,13 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
} else {
value = *(uint8_t *)src | (*(uint8_t *)(src + 1) << 8);
}
- eeprom_write_word((uint16_t *)dest, value);
+ EEPROM_WriteDataWord((uintptr_t)((uint16_t *)dest), value);
dest += 2;
src += 2;
len -= 2;
}
if (len) {
- eeprom_write_byte(dest, *src);
+ EEPROM_WriteDataByte((uintptr_t)dest, *src);
}
}
-
-void eeprom_update_block(const void *buf, void *addr, size_t len) { eeprom_write_block(buf, addr, len); }
diff --git a/tmk_core/common/chibios/eeprom_stm32.h b/platforms/chibios/eeprom_stm32.h
index 8fcfb556b8..8fcfb556b8 100644
--- a/tmk_core/common/chibios/eeprom_stm32.h
+++ b/platforms/chibios/eeprom_stm32.h
diff --git a/tmk_core/common/chibios/eeprom_stm32_defs.h b/platforms/chibios/eeprom_stm32_defs.h
index 22b4ab858e..66904f247f 100644
--- a/tmk_core/common/chibios/eeprom_stm32_defs.h
+++ b/platforms/chibios/eeprom_stm32_defs.h
@@ -18,7 +18,7 @@
#include <hal.h>
#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT)
-# if defined(STM32F103xB) || defined(STM32F042x6)
+# if defined(STM32F103xB) || defined(STM32F042x6) || defined(GD32VF103C8) || defined(GD32VF103CB)
# ifndef FEE_PAGE_SIZE
# define FEE_PAGE_SIZE 0x400 // Page size = 1KByte
# endif
@@ -32,25 +32,38 @@
# ifndef FEE_PAGE_COUNT
# define FEE_PAGE_COUNT 4 // How many pages are used
# endif
+# elif defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xG) || defined(STM32F411xE)
+# ifndef FEE_PAGE_SIZE
+# define FEE_PAGE_SIZE 0x4000 // Page size = 16KByte
+# endif
+# ifndef FEE_PAGE_COUNT
+# define FEE_PAGE_COUNT 1 // How many pages are used
+# endif
# endif
#endif
#if !defined(FEE_MCU_FLASH_SIZE)
# if defined(STM32F042x6)
# define FEE_MCU_FLASH_SIZE 32 // Size in Kb
-# elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB)
+# elif defined(GD32VF103C8)
+# define FEE_MCU_FLASH_SIZE 64 // Size in Kb
+# elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) || defined(GD32VF103CB)
# define FEE_MCU_FLASH_SIZE 128 // Size in Kb
-# elif defined(STM32F303xC)
+# elif defined(STM32F303xC) || defined(STM32F401xC)
# define FEE_MCU_FLASH_SIZE 256 // Size in Kb
-# elif defined(STM32F103xE)
+# elif defined(STM32F103xE) || defined(STM32F401xE) || defined(STM32F411xE)
# define FEE_MCU_FLASH_SIZE 512 // Size in Kb
+# elif defined(STM32F405xG)
+# define FEE_MCU_FLASH_SIZE 1024 // Size in Kb
# endif
#endif
/* Start of the emulated eeprom */
#if !defined(FEE_PAGE_BASE_ADDRESS)
-# if 0
-/* TODO: Add support for F4 */
+# if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xG) || defined(STM32F411xE)
+# ifndef FEE_PAGE_BASE_ADDRESS
+# define FEE_PAGE_BASE_ADDRESS 0x08004000 // bodge to force 2nd 16k page
+# endif
# else
# ifndef FEE_FLASH_BASE
# define FEE_FLASH_BASE 0x8000000
diff --git a/tmk_core/common/chibios/eeprom_teensy.c b/platforms/chibios/eeprom_teensy.c
index 4aaf665269..97da6f9e14 100644
--- a/tmk_core/common/chibios/eeprom_teensy.c
+++ b/platforms/chibios/eeprom_teensy.c
@@ -39,7 +39,126 @@
* SOFTWARE.
*/
-#if defined(K20x) /* chip selection */
+#define SMC_PMSTAT_RUN ((uint8_t)0x01)
+#define SMC_PMSTAT_HSRUN ((uint8_t)0x80)
+
+#define F_CPU KINETIS_SYSCLK_FREQUENCY
+
+static inline int kinetis_hsrun_disable(void) {
+#if defined(MK66F18)
+ if (SMC->PMSTAT == SMC_PMSTAT_HSRUN) {
+// First, reduce the CPU clock speed, but do not change
+// the peripheral speed (F_BUS). Serial1 & Serial2 baud
+// rates will be impacted, but most other peripherals
+// will continue functioning at the same speed.
+# if F_CPU == 256000000 && F_BUS == 64000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // TODO: TEST
+# elif F_CPU == 256000000 && F_BUS == 128000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // TODO: TEST
+# elif F_CPU == 240000000 && F_BUS == 60000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
+# elif F_CPU == 240000000 && F_BUS == 80000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
+# elif F_CPU == 240000000 && F_BUS == 120000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
+# elif F_CPU == 216000000 && F_BUS == 54000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
+# elif F_CPU == 216000000 && F_BUS == 72000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
+# elif F_CPU == 216000000 && F_BUS == 108000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
+# elif F_CPU == 192000000 && F_BUS == 48000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
+# elif F_CPU == 192000000 && F_BUS == 64000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
+# elif F_CPU == 192000000 && F_BUS == 96000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
+# elif F_CPU == 180000000 && F_BUS == 60000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
+# elif F_CPU == 180000000 && F_BUS == 90000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
+# elif F_CPU == 168000000 && F_BUS == 56000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok
+# elif F_CPU == 144000000 && F_BUS == 48000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok
+# elif F_CPU == 144000000 && F_BUS == 72000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 5); // ok
+# elif F_CPU == 120000000 && F_BUS == 60000000
+ SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1 - 1) | SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2 - 1) |
+# if defined(MK66F18)
+ SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3 - 1) |
+# endif
+ SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4 - 1);
+# else
+ return 0;
+# endif
+ // Then turn off HSRUN mode
+ SMC->PMCTRL = SMC_PMCTRL_RUNM_SET(0);
+ while (SMC->PMSTAT == SMC_PMSTAT_HSRUN)
+ ; // wait
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+static inline int kinetis_hsrun_enable(void) {
+#if defined(MK66F18)
+ if (SMC->PMSTAT == SMC_PMSTAT_RUN) {
+ // Turn HSRUN mode on
+ SMC->PMCTRL = SMC_PMCTRL_RUNM_SET(3);
+ while (SMC->PMSTAT != SMC_PMSTAT_HSRUN) {
+ ;
+ } // wait
+// Then configure clock for full speed
+# if F_CPU == 256000000 && F_BUS == 64000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
+# elif F_CPU == 256000000 && F_BUS == 128000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
+# elif F_CPU == 240000000 && F_BUS == 60000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
+# elif F_CPU == 240000000 && F_BUS == 80000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);
+# elif F_CPU == 240000000 && F_BUS == 120000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
+# elif F_CPU == 216000000 && F_BUS == 54000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
+# elif F_CPU == 216000000 && F_BUS == 72000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);
+# elif F_CPU == 216000000 && F_BUS == 108000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
+# elif F_CPU == 192000000 && F_BUS == 48000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 6);
+# elif F_CPU == 192000000 && F_BUS == 64000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6);
+# elif F_CPU == 192000000 && F_BUS == 96000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6);
+# elif F_CPU == 180000000 && F_BUS == 60000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6);
+# elif F_CPU == 180000000 && F_BUS == 90000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6);
+# elif F_CPU == 168000000 && F_BUS == 56000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 5);
+# elif F_CPU == 144000000 && F_BUS == 48000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 4);
+# elif F_CPU == 144000000 && F_BUS == 72000000
+ SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 4);
+# elif F_CPU == 120000000 && F_BUS == 60000000
+ SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1 - 1) | SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2 - 1) |
+# if defined(MK66F18)
+ SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3 - 1) |
+# endif
+ SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4 - 1);
+# else
+ return 0;
+# endif
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+#if defined(K20x) || defined(MK66F18) /* chip selection */
/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
// The EEPROM is really RAM with a hardware-based backup system to
@@ -69,22 +188,34 @@
//
# define HANDLE_UNALIGNED_WRITES
+# if defined(K20x)
+# define EEPROM_MAX 2048
+# define EEPARTITION 0x03 // all 32K dataflash for EEPROM, none for Data
+# define EEESPLIT 0x30 // must be 0x30 on these chips
+# elif defined(MK66F18)
+# define EEPROM_MAX 4096
+# define EEPARTITION 0x05 // 128K dataflash for EEPROM, 128K for Data
+# define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal
+# endif
+
// Minimum EEPROM Endurance
// ------------------------
-# if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
-# define EEESIZE 0x33
+# if (EEPROM_SIZE == 4096)
+# define EEESIZE 0x02
+# elif (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
+# define EEESIZE 0x03
# elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
-# define EEESIZE 0x34
+# define EEESIZE 0x04
# elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
-# define EEESIZE 0x35
+# define EEESIZE 0x05
# elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
-# define EEESIZE 0x36
+# define EEESIZE 0x06
# elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
-# define EEESIZE 0x37
+# define EEESIZE 0x07
# elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
-# define EEESIZE 0x38
+# define EEESIZE 0x08
# elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
-# define EEESIZE 0x39
+# define EEESIZE 0x09
# endif
/** \brief eeprom initialization
@@ -97,15 +228,21 @@ void eeprom_initialize(void) {
uint8_t status;
if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
+
// FlexRAM is configured as traditional RAM
// We need to reconfigure for EEPROM usage
- FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
- FTFL->FCCOB4 = EEESIZE; // EEPROM Size
- FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
+ kinetis_hsrun_disable();
+ FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
+ FTFL->FCCOB3 = 0;
+ FTFL->FCCOB4 = EEESPLIT | EEESIZE;
+ FTFL->FCCOB5 = EEPARTITION;
__disable_irq();
// do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
__enable_irq();
+ kinetis_hsrun_enable();
status = FTFL->FSTAT;
if (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL)) {
FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL));
@@ -114,11 +251,11 @@ void eeprom_initialize(void) {
}
// wait for eeprom to become ready (is this really necessary?)
while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
- if (++count > 20000) break;
+ if (++count > 200000) break;
}
}
-# define FlexRAM ((uint8_t *)0x14000000)
+# define FlexRAM ((volatile uint8_t *)0x14000000)
/** \brief eeprom read byte
*
@@ -195,8 +332,12 @@ void eeprom_write_byte(uint8_t *addr, uint8_t value) {
if (offset >= EEPROM_SIZE) return;
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
if (FlexRAM[offset] != value) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
FlexRAM[offset] = value;
flexram_wait();
+ kinetis_hsrun_enable();
}
}
@@ -213,18 +354,30 @@ void eeprom_write_word(uint16_t *addr, uint16_t value) {
if ((offset & 1) == 0) {
# endif
if (*(uint16_t *)(&FlexRAM[offset]) != value) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset]) = value;
flexram_wait();
+ kinetis_hsrun_enable();
}
# ifdef HANDLE_UNALIGNED_WRITES
} else {
if (FlexRAM[offset] != value) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
FlexRAM[offset] = value;
flexram_wait();
+ kinetis_hsrun_enable();
}
if (FlexRAM[offset + 1] != (value >> 8)) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
FlexRAM[offset + 1] = value >> 8;
flexram_wait();
+ kinetis_hsrun_enable();
}
}
# endif
@@ -244,33 +397,57 @@ void eeprom_write_dword(uint32_t *addr, uint32_t value) {
case 0:
# endif
if (*(uint32_t *)(&FlexRAM[offset]) != value) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
*(uint32_t *)(&FlexRAM[offset]) = value;
flexram_wait();
+ kinetis_hsrun_enable();
}
return;
# ifdef HANDLE_UNALIGNED_WRITES
case 2:
if (*(uint16_t *)(&FlexRAM[offset]) != value) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset]) = value;
flexram_wait();
+ kinetis_hsrun_enable();
}
if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
flexram_wait();
+ kinetis_hsrun_enable();
}
return;
default:
if (FlexRAM[offset] != value) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
FlexRAM[offset] = value;
flexram_wait();
+ kinetis_hsrun_enable();
}
if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
flexram_wait();
+ kinetis_hsrun_enable();
}
if (FlexRAM[offset + 3] != (value >> 24)) {
+ kinetis_hsrun_disable();
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
FlexRAM[offset + 3] = value >> 24;
flexram_wait();
+ kinetis_hsrun_enable();
}
}
# endif
@@ -288,6 +465,7 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
+ kinetis_hsrun_disable();
while (len > 0) {
uint32_t lsb = offset & 3;
if (lsb == 0 && len >= 4) {
@@ -298,6 +476,8 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
val32 |= (*src++ << 16);
val32 |= (*src++ << 24);
if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
*(uint32_t *)(&FlexRAM[offset]) = val32;
flexram_wait();
}
@@ -309,6 +489,8 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
val16 = *src++;
val16 |= (*src++ << 8);
if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset]) = val16;
flexram_wait();
}
@@ -318,6 +500,8 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
// write 8 bits
uint8_t val8 = *src++;
if (FlexRAM[offset] != val8) {
+ uint8_t stat = FTFL->FSTAT & 0x70;
+ if (stat) FTFL->FSTAT = stat;
FlexRAM[offset] = val8;
flexram_wait();
}
@@ -325,6 +509,7 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
len--;
}
}
+ kinetis_hsrun_enable();
}
/*
diff --git a/platforms/chibios/flash.mk b/platforms/chibios/flash.mk
index c0b32c2f2b..6ee53172d2 100644
--- a/platforms/chibios/flash.mk
+++ b/platforms/chibios/flash.mk
@@ -23,6 +23,20 @@ define EXEC_DFU_UTIL
$(DFU_UTIL) $(DFU_ARGS) -D $(BUILD_DIR)/$(TARGET).bin
endef
+
+define EXEC_WB32_DFU_UPDATER
+ if ! wb32-dfu-updater_cli -l | grep -q "Found DFU"; then \
+ printf "$(MSG_BOOTLOADER_NOT_FOUND_QUICK_RETRY)" ;\
+ sleep $(BOOTLOADER_RETRY_TIME) ;\
+ while ! wb32-dfu-updater_cli -l | grep -q "Found DFU"; do \
+ printf "." ;\
+ sleep $(BOOTLOADER_RETRY_TIME) ;\
+ done ;\
+ printf "\n" ;\
+ fi
+ wb32-dfu-updater_cli -D $(BUILD_DIR)/$(TARGET).bin
+endef
+
dfu-util: $(BUILD_DIR)/$(TARGET).bin cpfirmware sizeafter
$(call EXEC_DFU_UTIL)
@@ -82,6 +96,10 @@ else ifeq ($(strip $(MCU_FAMILY)),MIMXRT1062)
$(UNSYNC_OUTPUT_CMD) && $(call EXEC_TEENSY)
else ifeq ($(strip $(MCU_FAMILY)),STM32)
$(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
+else ifeq ($(strip $(MCU_FAMILY)),WB32)
+ $(UNSYNC_OUTPUT_CMD) && $(call EXEC_WB32_DFU_UPDATER)
+else ifeq ($(strip $(MCU_FAMILY)),GD32V)
+ $(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
else
$(PRINT_OK); $(SILENT) || printf "$(MSG_FLASH_BOOTLOADER)"
endif
diff --git a/tmk_core/common/chibios/flash_stm32.c b/platforms/chibios/flash_stm32.c
index 6b80ff71c3..72c41b8b78 100644
--- a/tmk_core/common/chibios/flash_stm32.c
+++ b/platforms/chibios/flash_stm32.c
@@ -19,10 +19,38 @@
#include <hal.h>
#include "flash_stm32.h"
-#if defined(EEPROM_EMU_STM32F103xB)
+#if defined(STM32F1XX)
# define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
#endif
+#if defined(MCU_GD32V)
+/* GigaDevice GD32VF103 is a STM32F103 clone at heart. */
+# include "gd32v_compatibility.h"
+#endif
+
+#if defined(STM32F4XX)
+# define FLASH_SR_PGERR (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR)
+
+# define FLASH_KEY1 0x45670123U
+# define FLASH_KEY2 0xCDEF89ABU
+
+static uint8_t ADDR2PAGE(uint32_t Page_Address) {
+ switch (Page_Address) {
+ case 0x08000000 ... 0x08003FFF:
+ return 0;
+ case 0x08004000 ... 0x08007FFF:
+ return 1;
+ case 0x08008000 ... 0x0800BFFF:
+ return 2;
+ case 0x0800C000 ... 0x0800FFFF:
+ return 3;
+ }
+
+ // TODO: bad times...
+ return 7;
+}
+#endif
+
/* Delay definition */
#define EraseTimeout ((uint32_t)0x00000FFF)
#define ProgramTimeout ((uint32_t)0x0000001F)
@@ -53,7 +81,9 @@ FLASH_Status FLASH_GetStatus(void) {
if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP;
+#if defined(FLASH_OBR_OPTERR)
if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT;
+#endif
return FLASH_COMPLETE;
}
@@ -95,15 +125,24 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
if (status == FLASH_COMPLETE) {
/* if the previous operation is completed, proceed to erase the page */
+#if defined(FLASH_CR_SNB)
+ FLASH->CR &= ~FLASH_CR_SNB;
+ FLASH->CR |= FLASH_CR_SER | (ADDR2PAGE(Page_Address) << FLASH_CR_SNB_Pos);
+#else
FLASH->CR |= FLASH_CR_PER;
FLASH->AR = Page_Address;
+#endif
FLASH->CR |= FLASH_CR_STRT;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if (status != FLASH_TIMEOUT) {
- /* if the erase operation is completed, disable the PER Bit */
+ /* if the erase operation is completed, disable the configured Bits */
+#if defined(FLASH_CR_SNB)
+ FLASH->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB);
+#else
FLASH->CR &= ~FLASH_CR_PER;
+#endif
}
FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
}
@@ -126,6 +165,11 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
status = FLASH_WaitForLastOperation(ProgramTimeout);
if (status == FLASH_COMPLETE) {
/* if the previous operation is completed, proceed to program the new data */
+
+#if defined(FLASH_CR_PSIZE)
+ FLASH->CR &= ~FLASH_CR_PSIZE;
+ FLASH->CR |= FLASH_CR_PSIZE_0;
+#endif
FLASH->CR |= FLASH_CR_PG;
*(__IO uint16_t*)Address = Data;
/* Wait for last operation to be completed */
diff --git a/tmk_core/common/chibios/flash_stm32.h b/platforms/chibios/flash_stm32.h
index 6c66642ec5..6c66642ec5 100644
--- a/tmk_core/common/chibios/flash_stm32.h
+++ b/platforms/chibios/flash_stm32.h
diff --git a/platforms/chibios/gd32v_compatibility.h b/platforms/chibios/gd32v_compatibility.h
new file mode 100644
index 0000000000..f4dcfd8c55
--- /dev/null
+++ b/platforms/chibios/gd32v_compatibility.h
@@ -0,0 +1,120 @@
+/* Copyright 2021 QMK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+/* GD32VF103 has the same API as STM32F103, but uses different names for literally the same thing.
+ * As of 23.7.2021 QMK is tailored to use STM32 defines/names, for compatibility sake
+ * we just redefine the GD32 names. */
+
+/* Close your eyes kids. */
+#define MCU_STM32
+
+/* AFIO redefines */
+#define MAPR PCF0
+#define AFIO_MAPR_USART1_REMAP AFIO_PCF0_USART0_REMAP
+#define AFIO_MAPR_USART2_REMAP AFIO_PCF0_USART1_REMAP
+#define AFIO_MAPR_USART3_REMAP_PARTIALREMAP AFIO_PCF0_USART2_REMAP_PARTIALREMAP
+#define AFIO_MAPR_USART3_REMAP_FULLREMAP AFIO_PCF0_USART2_REMAP_FULLREMAP
+
+/* DMA redefines. */
+#define STM32_DMA_STREAM(stream) GD32_DMA_STREAM(stream)
+#define STM32_DMA_STREAM_ID(peripheral, channel) GD32_DMA_STREAM_ID(peripheral - 1, channel - 1)
+#define STM32_DMA_CR_DIR_M2P GD32_DMA_CTL_DIR_M2P
+#define STM32_DMA_CR_PSIZE_WORD GD32_DMA_CTL_PWIDTH_WORD
+#define STM32_DMA_CR_MSIZE_WORD GD32_DMA_CTL_MWIDTH_WORD
+#define STM32_DMA_CR_MINC GD32_DMA_CTL_MNAGA
+#define STM32_DMA_CR_CIRC GD32_DMA_CTL_CMEN
+#define STM32_DMA_CR_PL GD32_DMA_CTL_PRIO
+#define STM32_DMA_CR_CHSEL GD32_DMA_CTL_CHSEL
+#define cr1 ctl0
+#define cr2 ctl1
+#define cr3 ctl2
+#define dier dmainten
+
+/* ADC redefines */
+#if HAL_USE_ADC
+# define STM32_ADC_USE_ADC1 GD32_ADC_USE_ADC0
+
+# define smpr1 sampt0
+# define smpr2 sampt1
+# define sqr1 rsq0
+# define sqr2 rsq1
+# define sqr3 rsq2
+
+# define ADC_SMPR2_SMP_AN0 ADC_SAMPT1_SMP_SPT0
+# define ADC_SMPR2_SMP_AN1 ADC_SAMPT1_SMP_SPT1
+# define ADC_SMPR2_SMP_AN2 ADC_SAMPT1_SMP_SPT2
+# define ADC_SMPR2_SMP_AN3 ADC_SAMPT1_SMP_SPT3
+# define ADC_SMPR2_SMP_AN4 ADC_SAMPT1_SMP_SPT4
+# define ADC_SMPR2_SMP_AN5 ADC_SAMPT1_SMP_SPT5
+# define ADC_SMPR2_SMP_AN6 ADC_SAMPT1_SMP_SPT6
+# define ADC_SMPR2_SMP_AN7 ADC_SAMPT1_SMP_SPT7
+# define ADC_SMPR2_SMP_AN8 ADC_SAMPT1_SMP_SPT8
+# define ADC_SMPR2_SMP_AN9 ADC_SAMPT1_SMP_SPT9
+
+# define ADC_SMPR1_SMP_AN10 ADC_SAMPT0_SMP_SPT10
+# define ADC_SMPR1_SMP_AN11 ADC_SAMPT0_SMP_SPT11
+# define ADC_SMPR1_SMP_AN12 ADC_SAMPT0_SMP_SPT12
+# define ADC_SMPR1_SMP_AN13 ADC_SAMPT0_SMP_SPT13
+# define ADC_SMPR1_SMP_AN14 ADC_SAMPT0_SMP_SPT14
+# define ADC_SMPR1_SMP_AN15 ADC_SAMPT0_SMP_SPT15
+
+# define ADC_SQR3_SQ1_N ADC_RSQ2_RSQ1_N
+#endif
+
+/* FLASH redefines */
+#if defined(EEPROM_ENABLE)
+# define SR STAT
+# define FLASH_SR_BSY FLASH_STAT_BUSY
+# define FLASH_SR_PGERR FLASH_STAT_PGERR
+# define FLASH_SR_EOP FLASH_STAT_ENDF
+# define FLASH_SR_WRPRTERR FLASH_STAT_WPERR
+# define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
+# define FLASH_OBR_OPTERR FLASH_OBSTAT_OBERR
+# define AR ADDR
+# define CR CTL
+# define FLASH_CR_PER FLASH_CTL_PER
+# define FLASH_CR_STRT FLASH_CTL_START
+# define FLASH_CR_LOCK FLASH_CTL_LK
+# define FLASH_CR_PG FLASH_CTL_PG
+# define KEYR KEY
+#endif
+
+/* Serial USART redefines. */
+#if HAL_USE_SERIAL
+# if !defined(SERIAL_USART_CR1)
+# define SERIAL_USART_CR1 (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL) // parity enable, odd parity, 9 bit length
+# endif
+# if !defined(SERIAL_USART_CR2)
+# define SERIAL_USART_CR2 (USART_CTL1_STB_1) // 2 stop bits
+# endif
+# if !defined(SERIAL_USART_CR3)
+# define SERIAL_USART_CR3 0x0
+# endif
+# define USART_CR3_HDSEL USART_CTL2_HDEN
+# define CCR CHCV
+#endif
+
+/* SPI redefines. */
+#if HAL_USE_SPI
+# define SPI_CR1_LSBFIRST SPI_CTL0_LF
+# define SPI_CR1_CPHA SPI_CTL0_CKPH
+# define SPI_CR1_CPOL SPI_CTL0_CKPL
+# define SPI_CR1_BR_0 SPI_CTL0_PSC_0
+# define SPI_CR1_BR_1 SPI_CTL0_PSC_1
+# define SPI_CR1_BR_2 SPI_CTL0_PSC_2
+#endif
diff --git a/tmk_core/common/chibios/gpio.h b/platforms/chibios/gpio.h
index 4d057f1cab..4d057f1cab 100644
--- a/tmk_core/common/chibios/gpio.h
+++ b/platforms/chibios/gpio.h
diff --git a/tmk_core/common/chibios/pin_defs.h b/platforms/chibios/pin_defs.h
index c03f8de0c2..c03f8de0c2 100644
--- a/tmk_core/common/chibios/pin_defs.h
+++ b/platforms/chibios/pin_defs.h
diff --git a/tmk_core/common/chibios/platform.c b/platforms/chibios/platform.c
index d4a229f278..d4a229f278 100644
--- a/tmk_core/common/chibios/platform.c
+++ b/platforms/chibios/platform.c
diff --git a/tmk_core/chibios.mk b/platforms/chibios/platform.mk
index 18839710be..45e3377882 100644
--- a/tmk_core/chibios.mk
+++ b/platforms/chibios/platform.mk
@@ -27,29 +27,76 @@ endif
OPT_OS = chibios
CHIBIOS = $(TOP_DIR)/lib/chibios
CHIBIOS_CONTRIB = $(TOP_DIR)/lib/chibios-contrib
-# Startup files. Try a few different locations, for compability with old versions and
-# for things hardware in the contrib repository
-STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
-ifeq ("$(wildcard $(STARTUP_MK))","")
- STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
- ifeq ("$(wildcard $(STARTUP_MK))","")
- STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
- endif
+
+#
+# Startup, Port and Platform support selection
+##############################################################################
+
+ifeq ($(strip $(MCU)), risc-v)
+ # RISC-V Support
+ # As of 7.4.2021 there is only one supported RISC-V platform in Chibios-Contrib,
+ # therefore all required settings are hard-coded
+ STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ PORT_V = $(CHIBIOS_CONTRIB)/os/common/ports/RISCV-ECLIC/compilers/GCC/mk/port.mk
+ RULESPATH = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC
+ PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/GD/GD32VF103/platform.mk
+else
+ # ARM Support
+ CHIBIOS_PORT ?=
+ ifeq ("$(CHIBIOS_PORT)","")
+ CHIBIOS_PORT = ARMv$(ARMV)-M
+ endif
+
+ # Startup files. Try a few different locations, for compability with old versions and
+ # for things hardware in the contrib repository
+ STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ ifeq ("$(wildcard $(STARTUP_MK))","")
+ STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ ifeq ("$(wildcard $(STARTUP_MK))","")
+ STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ endif
+ endif
+
+ # Port files. Try a few different locations, for compability with old versions and
+ # for things hardware in the contrib repository
+ PORT_V = $(CHIBIOS)/os/common/ports/$(CHIBIOS_PORT)/compilers/GCC/mk/port.mk
+ ifeq ("$(wildcard $(PORT_V))","")
+ PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
+ ifeq ("$(wildcard $(PORT_V))","")
+ PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
+ endif
+ endif
+
+ # Rules location. Try a few different locations, for compability with old versions and
+ # for things hardware in the contrib repository
+ RULESPATH = $(CHIBIOS)/os/common/ports/$(CHIBIOS_PORT)/compilers/GCC
+ ifeq ("$(wildcard $(RULESPATH)/rules.mk)","")
+ RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
+ ifeq ("$(wildcard $(RULESPATH)/rules.mk)","")
+ RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
+ endif
+ endif
endif
-include $(STARTUP_MK)
-# HAL-OSAL files (optional).
-include $(CHIBIOS)/os/hal/hal.mk
ifeq ("$(PLATFORM_NAME)","")
- PLATFORM_NAME = platform
+ PLATFORM_NAME = platform
endif
-PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
ifeq ("$(wildcard $(PLATFORM_MK))","")
-PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
+ PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
+ ifeq ("$(wildcard $(PLATFORM_MK))","")
+ PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
+ endif
endif
+
+include $(STARTUP_MK)
+include $(PORT_V)
include $(PLATFORM_MK)
+#
+# Board support selection.
+##############################################################################
+
BOARD_MK :=
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/boards/$(BOARD)/board.mk)","")
@@ -77,17 +124,27 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/board/board
endif
ifeq ("$(wildcard $(BOARD_MK))","")
- BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk
- ifeq ("$(wildcard $(BOARD_MK))","")
- BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk
- endif
+ BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk
+ ifeq ("$(wildcard $(BOARD_MK))","")
+ BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk
+ endif
endif
-# Bootloader address
+include $(BOARD_MK)
+
+#
+# Bootloader selection.
+##############################################################################
+
+# Set bootloader address if supplied.
ifdef STM32_BOOTLOADER_ADDRESS
OPT_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)
endif
+ifdef WB32_BOOTLOADER_ADDRESS
+ OPT_DEFS += -DWB32_BOOTLOADER_ADDRESS=$(WB32_BOOTLOADER_ADDRESS)
+endif
+
# Work out if we need to set up the include for the bootloader definitions
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/bootloader_defs.h)","")
OPT_DEFS += -include $(KEYBOARD_PATH_5)/bootloader_defs.h
@@ -113,6 +170,10 @@ else ifneq ("$(wildcard $(BOARD_PATH)/configs/bootloader_defs.h)","")
OPT_DEFS += -include $(BOARD_PATH)/configs/bootloader_defs.h
endif
+#
+# ChibiOS config selection.
+##############################################################################
+
# Work out the config file directories
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/chconf.h)","")
CHCONFDIR = $(KEYBOARD_PATH_5)
@@ -130,6 +191,10 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/boards/chibios/common/configs/chcon
CHCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs
endif
+#
+# HAL config selection.
+##############################################################################
+
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/halconf.h)","")
HALCONFDIR = $(KEYBOARD_PATH_5)
else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/halconf.h)","")
@@ -146,40 +211,10 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/common/configs/halco
HALCONFDIR = $(TOP_DIR)/platforms/chibios/boards/common/configs
endif
-# HAL-OSAL files (optional).
-include $(CHIBIOS)/os/hal/hal.mk
-
-ifeq ("$(PLATFORM_NAME)","")
- PLATFORM_NAME = platform
-endif
-
-PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
-ifeq ("$(wildcard $(PLATFORM_MK))","")
-PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
-endif
-include $(PLATFORM_MK)
-
-
-include $(BOARD_MK)
--include $(CHIBIOS)/os/hal/osal/rt/osal.mk # ChibiOS <= 19.x
--include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk # ChibiOS >= 20.x
-# RTOS files (optional).
-include $(CHIBIOS)/os/rt/rt.mk
-# Compability with old version
-PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
-ifeq ("$(wildcard $(PORT_V))","")
-PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
-endif
-include $(PORT_V)
-# Other files (optional).
-include $(CHIBIOS)/os/hal/lib/streams/streams.mk
-
-RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
-ifeq ("$(wildcard $(RULESPATH)/rules.mk)","")
-RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
-endif
+#
+# Linker script selection.
+##############################################################################
-# Define linker script file here
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld)","")
LDSCRIPT = $(KEYBOARD_PATH_5)/ld/$(MCU_LDSCRIPT).ld
else ifneq ("$(wildcard $(KEYBOARD_PATH_4)/ld/$(MCU_LDSCRIPT).ld)","")
@@ -202,22 +237,36 @@ else
LDSCRIPT = $(STARTUPLD)/$(MCU_LDSCRIPT).ld
endif
-CHIBISRC = $(STARTUPSRC) \
- $(KERNSRC) \
- $(PORTSRC) \
- $(OSALSRC) \
- $(HALSRC) \
- $(PLATFORMSRC) \
- $(BOARDSRC) \
- $(STREAMSSRC) \
- $(CHIBIOS)/os/various/syscalls.c \
- $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \
- $(PLATFORM_COMMON_DIR)/wait.c
+#
+# Include ChibiOS makefiles.
+##############################################################################
+
+# HAL-OSAL files (optional).
+include $(CHIBIOS)/os/hal/hal.mk
+-include $(CHIBIOS)/os/hal/osal/rt/osal.mk # ChibiOS <= 19.x
+-include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk # ChibiOS >= 20.x
+# RTOS files (optional).
+include $(CHIBIOS)/os/rt/rt.mk
+# Other files (optional).
+include $(CHIBIOS)/os/hal/lib/streams/streams.mk
+
+PLATFORM_SRC = \
+ $(STARTUPSRC) \
+ $(KERNSRC) \
+ $(PORTSRC) \
+ $(OSALSRC) \
+ $(HALSRC) \
+ $(PLATFORMSRC) \
+ $(BOARDSRC) \
+ $(STREAMSSRC) \
+ $(CHIBIOS)/os/various/syscalls.c \
+ $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \
+ $(PLATFORM_COMMON_DIR)/wait.c
# Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise.
QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM)
-CHIBISRC := $(patsubst $(TOP_DIR)/%,%,$(CHIBISRC))
+PLATFORM_SRC := $(patsubst $(TOP_DIR)/%,%,$(PLATFORM_SRC))
EXTRAINCDIRS += $(CHIBIOS)/os/license $(CHIBIOS)/os/oslib/include \
$(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs \
@@ -247,9 +296,9 @@ else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/boards/$(BOARD)/configs/hal
endif
ifeq ($(strip $(USE_CHIBIOS_CONTRIB)),yes)
- include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
- CHIBISRC += $(PLATFORMSRC_CONTRIB) $(HALSRC_CONTRIB)
- EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various
+ include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
+ PLATFORM_SRC += $(PLATFORMSRC_CONTRIB) $(HALSRC_CONTRIB)
+ EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various
endif
#
@@ -267,61 +316,123 @@ ifneq ("$(wildcard $(BOARD_PATH)/configs/post_config.h)","")
endif
##############################################################################
-# Compiler settings
+# Compiler and Linker configuration
#
-CC = arm-none-eabi-gcc
-OBJCOPY = arm-none-eabi-objcopy
-OBJDUMP = arm-none-eabi-objdump
-SIZE = arm-none-eabi-size
-AR = arm-none-eabi-ar
-NM = arm-none-eabi-nm
-HEX = $(OBJCOPY) -O $(FORMAT)
-EEP =
-BIN = $(OBJCOPY) -O binary
-
-THUMBFLAGS = -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb -DTHUMB
-
-COMPILEFLAGS += -fomit-frame-pointer
-COMPILEFLAGS += -falign-functions=16
-COMPILEFLAGS += -ffunction-sections
-COMPILEFLAGS += -fdata-sections
-COMPILEFLAGS += -fno-common
-COMPILEFLAGS += -fshort-wchar
-COMPILEFLAGS += $(THUMBFLAGS)
-
-# FPU options default (Cortex-M4 and Cortex-M7 single precision).
-USE_FPU_OPT ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
-
-# FPU-related options
-USE_FPU ?= no
-ifneq ($(USE_FPU),no)
- COMPILEFLAGS += $(USE_FPU_OPT)
- OPT_DEFS += -DCORTEX_USE_FPU=TRUE
+
+# Use defined stack sizes of the main thread in linker scripts
+SHARED_LDSYMBOLS = -Wl,--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
+
+# Shared Compiler flags for all toolchains
+SHARED_CFLAGS = -fomit-frame-pointer \
+ -ffunction-sections \
+ -fdata-sections \
+ -fno-common \
+ -fshort-wchar
+
+# Shared Linker flags for all toolchains
+SHARED_LDFLAGS = -T $(LDSCRIPT) \
+ -Wl,--gc-sections \
+ -nostartfiles
+
+ifeq ($(strip $(MCU)), risc-v)
+ # RISC-V toolchain specific configuration
+ # Find suitable GCC compiler
+ ifeq ($(strip $(TOOLCHAIN)),)
+ ifneq ($(shell which riscv32-unknown-elf-gcc 2>/dev/null),)
+ TOOLCHAIN = riscv32-unknown-elf-
+ else
+ ifneq ($(shell which riscv64-unknown-elf-gcc 2>/dev/null),)
+ TOOLCHAIN = riscv64-unknown-elf-
+ else
+ $(error "No RISC-V toolchain found. Can't find riscv32-unknown-elf-gcc or riscv64-unknown-elf-gcc found in your systems PATH variable. Please install a valid toolchain and make it accessible!")
+ endif
+ endif
+ endif
+
+ # Default to compiling with picolibc for RISC-V targets if available, which
+ # is available by default on distributions based on Debian 11+.
+ ifeq ($(shell $(TOOLCHAIN)gcc --specs=picolibc.specs -E - 2>/dev/null >/dev/null </dev/null ; echo $$?),0)
+ # Toolchain specific Compiler flags Note that we still link with our own
+ # linker script by providing it via the -T flag in SHARED_LDFLAGS.
+ TOOLCHAIN_CFLAGS = --specs=picolibc.specs
+
+ # picolibc internally uses __heap_start and __heap_end instead of the
+ # defacto chibios linker script standard __heap_base__ and __heap_end__
+ # therefore we introduce these symbols as an alias.
+ TOOLCHAIN_LDSYMBOLS = -Wl,--defsym=__heap_start=__heap_base__,--defsym=__heap_end=__heap_end__
+
+ # Tell QMK that we are compiling with picolibc.
+ OPT_DEFS += -DUSE_PICOLIBC
+ endif
+
+ # MCU architecture flags
+ MCUFLAGS = -march=$(MCU_ARCH) \
+ -mabi=$(MCU_ABI) \
+ -mcmodel=$(MCU_CMODEL) \
+ -mstrict-align
else
- OPT_DEFS += -DCORTEX_USE_FPU=FALSE
+ # ARM toolchain specific configuration
+ TOOLCHAIN ?= arm-none-eabi-
+
+ # Toolchain specific Linker flags
+ TOOLCHAIN_LDFLAGS = -Wl,--no-wchar-size-warning \
+ --specs=nano.specs
+
+ # MCU architecture flags
+ MCUFLAGS = -mcpu=$(MCU) \
+ -mthumb -DTHUMB_PRESENT \
+ -mno-thumb-interwork -DTHUMB_NO_INTERWORKING \
+ -mno-unaligned-access
+
+ # Some ARM cores like the M4 and M7 have floating point units which can be enabled
+ USE_FPU ?= no
+
+ ifneq ($(USE_FPU),no)
+ OPT_DEFS += -DCORTEX_USE_FPU=TRUE
+
+ # Default is single precision floats
+ USE_FPU_OPT ?= -mfloat-abi=hard \
+ -mfpu=fpv4-sp-d16 \
+ -fsingle-precision-constant
+
+ MCUFLAGS += $(USE_FPU_OPT)
+ else
+ OPT_DEFS += -DCORTEX_USE_FPU=FALSE
+ endif
endif
-CFLAGS += $(COMPILEFLAGS)
+# Assembler flags
+ASFLAGS += $(SHARED_ASFLAGS) $(TOOLCHAIN_ASFLAGS)
-ASFLAGS += $(THUMBFLAGS)
+# C Compiler flags
+CFLAGS += $(SHARED_CFLAGS) $(TOOLCHAIN_CFLAGS)
-CXXFLAGS += $(COMPILEFLAGS)
-CXXFLAGS += -fno-rtti
+# C++ Compiler flags
+CXXFLAGS += $(CFLAGS) $(SHARED_CXXFLAGS) $(TOOLCHAIN_CXXFLAGS) -fno-rtti
-LDFLAGS +=-Wl,--gc-sections
-LDFLAGS +=-Wl,--no-wchar-size-warning
-LDFLAGS += -mno-thumb-interwork -mthumb
-LDSYMBOLS =,--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)
-LDSYMBOLS :=$(LDSYMBOLS),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
-LDFLAGS += -Wl,--script=$(LDSCRIPT)$(LDSYMBOLS)
-LDFLAGS += --specs=nano.specs
+# Linker flags
+LDFLAGS += $(SHARED_LDFLAGS) $(SHARED_LDSYMBOLS) $(TOOLCHAIN_LDFLAGS) $(TOOLCHAIN_LDSYMBOLS) $(MCUFLAGS)
+# Tell QMK that we are hosting it on ChibiOS.
OPT_DEFS += -DPROTOCOL_CHIBIOS
# Workaround to stop ChibiOS from complaining about new GCC -- it's been fixed for 7/8/9 already
OPT_DEFS += -DPORT_IGNORE_GCC_VERSION_CHECK=1
-MCUFLAGS = -mcpu=$(MCU)
+# Construct GCC toolchain
+CC = $(CC_PREFIX) $(TOOLCHAIN)gcc
+OBJCOPY = $(TOOLCHAIN)objcopy
+OBJDUMP = $(TOOLCHAIN)objdump
+SIZE = $(TOOLCHAIN)size
+AR = $(TOOLCHAIN)ar
+NM = $(TOOLCHAIN)nm
+HEX = $(OBJCOPY) -O $(FORMAT)
+EEP =
+BIN = $(OBJCOPY) -O binary
+
+##############################################################################
+# Make targets
+#
DEBUG = gdb
diff --git a/tmk_core/common/chibios/platform_deps.h b/platforms/chibios/platform_deps.h
index 8243dcec53..8243dcec53 100644
--- a/tmk_core/common/chibios/platform_deps.h
+++ b/platforms/chibios/platform_deps.h
diff --git a/tmk_core/common/chibios/sleep_led.c b/platforms/chibios/sleep_led.c
index 1c65016a42..477056a454 100644
--- a/tmk_core/common/chibios/sleep_led.c
+++ b/platforms/chibios/sleep_led.c
@@ -65,7 +65,7 @@ void sleep_led_timer_callback(void) {
/* LPTMR clock options */
# define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */
-# define LPTMR_CLOCK_LPO 1 /* 1kHz clock */
+# define LPTMR_CLOCK_LPO 1 /* 1kHz clock */
# define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */
# define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */
@@ -121,7 +121,7 @@ void sleep_led_init(void) {
MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock
# if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
MCG->MC |= MCG_MC_LIRC_DIV2_DIV2;
-# endif /* KL27 */
+# endif /* KL27 */
MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock
// to work in stop mode, also MCG_C1_IREFSTEN
// Divide 4MHz by 2^N (N=6) => 62500 irqs/sec =>
diff --git a/platforms/chibios/suspend.c b/platforms/chibios/suspend.c
new file mode 100644
index 0000000000..9310a99920
--- /dev/null
+++ b/platforms/chibios/suspend.c
@@ -0,0 +1,92 @@
+/* TODO */
+
+#include <ch.h>
+#include <hal.h>
+
+#include "matrix.h"
+#include "action.h"
+#include "action_util.h"
+#include "mousekey.h"
+#include "programmable_button.h"
+#include "host.h"
+#include "suspend.h"
+#include "led.h"
+#include "wait.h"
+
+/** \brief suspend idle
+ *
+ * FIXME: needs doc
+ */
+void suspend_idle(uint8_t time) {
+ // TODO: this is not used anywhere - what units is 'time' in?
+ wait_ms(time);
+}
+
+/** \brief suspend power down
+ *
+ * FIXME: needs doc
+ */
+void suspend_power_down(void) {
+ suspend_power_down_quantum();
+ // on AVR, this enables the watchdog for 15ms (max), and goes to
+ // SLEEP_MODE_PWR_DOWN
+
+ wait_ms(17);
+}
+
+/** \brief suspend wakeup condition
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void matrix_power_up(void) {}
+__attribute__((weak)) void matrix_power_down(void) {}
+bool suspend_wakeup_condition(void) {
+ matrix_power_up();
+ matrix_scan();
+ matrix_power_down();
+ for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
+ if (matrix_get_row(r)) return true;
+ }
+ return false;
+}
+
+/** \brief run user level code immediately after wakeup
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_wakeup_init_user(void) {}
+
+/** \brief run keyboard level code immediately after wakeup
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
+
+/** \brief suspend wakeup condition
+ *
+ * run immediately after wakeup
+ * FIXME: needs doc
+ */
+void suspend_wakeup_init(void) {
+ // clear keyboard state
+ // need to do it manually, because we're running from ISR
+ // and clear_keyboard() calls print
+ // so only clear the variables in memory
+ // the reports will be sent from main.c afterwards
+ // or if the PC asks for GET_REPORT
+ clear_mods();
+ clear_weak_mods();
+ clear_keys();
+#ifdef MOUSEKEY_ENABLE
+ mousekey_clear();
+#endif /* MOUSEKEY_ENABLE */
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ programmable_button_clear();
+#endif /* PROGRAMMABLE_BUTTON_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+ host_system_send(0);
+ host_consumer_send(0);
+#endif /* EXTRAKEY_ENABLE */
+
+ suspend_wakeup_init_quantum();
+}
diff --git a/tmk_core/common/chibios/syscall-fallbacks.c b/platforms/chibios/syscall-fallbacks.c
index 739017ae1d..7150a46326 100644
--- a/tmk_core/common/chibios/syscall-fallbacks.c
+++ b/platforms/chibios/syscall-fallbacks.c
@@ -18,6 +18,13 @@
#include <sys/stat.h>
#include <sys/types.h>
+/* To compile the ChibiOS syscall stubs with picolibc
+ * the _reent struct has to be defined. */
+#if defined(USE_PICOLIBC)
+struct _reent;
+struct timeval;
+#endif
+
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
__attribute__((weak, used)) int _open_r(struct _reent *r, const char *path, int flag, int m) {
diff --git a/tmk_core/common/chibios/timer.c b/platforms/chibios/timer.c
index 9f664e1f79..9f664e1f79 100644
--- a/tmk_core/common/chibios/timer.c
+++ b/platforms/chibios/timer.c
diff --git a/tmk_core/common/chibios/wait.c b/platforms/chibios/wait.c
index 56fd6ffcec..56fd6ffcec 100644
--- a/tmk_core/common/chibios/wait.c
+++ b/platforms/chibios/wait.c
diff --git a/platforms/common.mk b/platforms/common.mk
new file mode 100644
index 0000000000..f7a0fc7028
--- /dev/null
+++ b/platforms/common.mk
@@ -0,0 +1,12 @@
+PLATFORM_COMMON_DIR = $(PLATFORM_PATH)/$(PLATFORM_KEY)
+
+TMK_COMMON_SRC += \
+ $(PLATFORM_COMMON_DIR)/platform.c \
+ $(PLATFORM_COMMON_DIR)/suspend.c \
+ $(PLATFORM_COMMON_DIR)/timer.c \
+ $(PLATFORM_COMMON_DIR)/bootloader.c \
+
+# Search Path
+VPATH += $(PLATFORM_PATH)
+VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)
+VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)
diff --git a/tmk_core/common/eeprom.h b/platforms/eeprom.h
index f5b3f0ad53..f5b3f0ad53 100644
--- a/tmk_core/common/eeprom.h
+++ b/platforms/eeprom.h
diff --git a/tmk_core/common/gpio.h b/platforms/gpio.h
index b47f6f8e43..b47f6f8e43 100644
--- a/tmk_core/common/gpio.h
+++ b/platforms/gpio.h
diff --git a/tmk_core/common/pin_defs.h b/platforms/pin_defs.h
index ea730138f2..ea730138f2 100644
--- a/tmk_core/common/pin_defs.h
+++ b/platforms/pin_defs.h
diff --git a/tmk_core/common/progmem.h b/platforms/progmem.h
index a70d8e299f..3a7a169682 100644
--- a/tmk_core/common/progmem.h
+++ b/platforms/progmem.h
@@ -5,7 +5,6 @@
#else
# include <string.h>
# define PROGMEM
-# define __flash
# define PSTR(x) x
# define PGM_P const char*
# define memcpy_P(dest, src, n) memcpy(dest, src, n)
diff --git a/tmk_core/common/sleep_led.h b/platforms/sleep_led.h
index 38f80a660d..38f80a660d 100644
--- a/tmk_core/common/sleep_led.h
+++ b/platforms/sleep_led.h
diff --git a/tmk_core/common/suspend.h b/platforms/suspend.h
index 95845e4b63..081735f90e 100644
--- a/tmk_core/common/suspend.h
+++ b/platforms/suspend.h
@@ -10,8 +10,10 @@ void suspend_wakeup_init(void);
void suspend_wakeup_init_user(void);
void suspend_wakeup_init_kb(void);
+void suspend_wakeup_init_quantum(void);
void suspend_power_down_user(void);
void suspend_power_down_kb(void);
+void suspend_power_down_quantum(void);
#ifndef USB_SUSPEND_WAKEUP_DELAY
# define USB_SUSPEND_WAKEUP_DELAY 0
diff --git a/tmk_core/common/test/_wait.h b/platforms/test/_wait.h
index 4e22f593b7..4e22f593b7 100644
--- a/tmk_core/common/test/_wait.h
+++ b/platforms/test/_wait.h
diff --git a/tmk_core/common/test/bootloader.c b/platforms/test/bootloader.c
index 5155d9ff04..5155d9ff04 100644
--- a/tmk_core/common/test/bootloader.c
+++ b/platforms/test/bootloader.c
diff --git a/tmk_core/common/test/eeprom.c b/platforms/test/eeprom.c
index 5c8e69dae3..5c8e69dae3 100644
--- a/tmk_core/common/test/eeprom.c
+++ b/platforms/test/eeprom.c
diff --git a/tmk_core/common/test/eeprom_stm32_tests.cpp b/platforms/test/eeprom_stm32_tests.cpp
index 5bc8d87900..5bc8d87900 100644
--- a/tmk_core/common/test/eeprom_stm32_tests.cpp
+++ b/platforms/test/eeprom_stm32_tests.cpp
diff --git a/tmk_core/common/test/flash_stm32_mock.c b/platforms/test/flash_stm32_mock.c
index 222a004bc7..222a004bc7 100644
--- a/tmk_core/common/test/flash_stm32_mock.c
+++ b/platforms/test/flash_stm32_mock.c
diff --git a/tmk_core/common/test/hal.h b/platforms/test/hal.h
index 2d268ad54c..2d268ad54c 100644
--- a/tmk_core/common/test/hal.h
+++ b/platforms/test/hal.h
diff --git a/tmk_core/common/test/platform.c b/platforms/test/platform.c
index 8ddceeda8f..8ddceeda8f 100644
--- a/tmk_core/common/test/platform.c
+++ b/platforms/test/platform.c
diff --git a/tmk_core/common/test/platform.h b/platforms/test/platform.h
index f296d1d535..f296d1d535 100644
--- a/tmk_core/common/test/platform.h
+++ b/platforms/test/platform.h
diff --git a/tmk_core/native.mk b/platforms/test/platform.mk
index f609fd0e6f..eb2424ec5c 100644
--- a/tmk_core/native.mk
+++ b/platforms/test/platform.mk
@@ -1,7 +1,7 @@
SYSTEM_TYPE := $(shell gcc -dumpmachine)
GCC_VERSION := $(shell gcc --version 2>/dev/null)
-CC = gcc
+CC = $(CC_PREFIX) gcc
OBJCOPY =
OBJDUMP =
SIZE =
diff --git a/tmk_core/common/test/platform_deps.h b/platforms/test/platform_deps.h
index f296d1d535..f296d1d535 100644
--- a/tmk_core/common/test/platform_deps.h
+++ b/platforms/test/platform_deps.h
diff --git a/tmk_core/common/test/rules.mk b/platforms/test/rules.mk
index 48632a095b..66b853d8ee 100644
--- a/tmk_core/common/test/rules.mk
+++ b/platforms/test/rules.mk
@@ -11,13 +11,14 @@ eeprom_stm32_large_DEFS := $(eeprom_stm32_DEFS) \
-DFEE_PAGE_COUNT=16
eeprom_stm32_INC := \
- $(TMK_PATH)/common/chibios/
+ $(PLATFORM_PATH)/chibios/
eeprom_stm32_tiny_INC := $(eeprom_stm32_INC)
eeprom_stm32_large_INC := $(eeprom_stm32_INC)
eeprom_stm32_SRC := \
- $(TMK_PATH)/common/test/eeprom_stm32_tests.cpp \
- $(TMK_PATH)/common/test/flash_stm32_mock.c \
- $(TMK_PATH)/common/chibios/eeprom_stm32.c
+ $(TOP_DIR)/drivers/eeprom/eeprom_driver.c \
+ $(PLATFORM_PATH)/$(PLATFORM_KEY)/eeprom_stm32_tests.cpp \
+ $(PLATFORM_PATH)/$(PLATFORM_KEY)/flash_stm32_mock.c \
+ $(PLATFORM_PATH)/chibios/eeprom_stm32.c
eeprom_stm32_tiny_SRC := $(eeprom_stm32_SRC)
eeprom_stm32_large_SRC := $(eeprom_stm32_SRC)
diff --git a/tmk_core/common/test/suspend.c b/platforms/test/suspend.c
index 76b705967b..76b705967b 100644
--- a/tmk_core/common/test/suspend.c
+++ b/platforms/test/suspend.c
diff --git a/tmk_core/common/test/testlist.mk b/platforms/test/testlist.mk
index 51a9638bb9..51a9638bb9 100644
--- a/tmk_core/common/test/testlist.mk
+++ b/platforms/test/testlist.mk
diff --git a/tmk_core/common/test/timer.c b/platforms/test/timer.c
index 61c3a00201..61c3a00201 100644
--- a/tmk_core/common/test/timer.c
+++ b/platforms/test/timer.c
diff --git a/tmk_core/common/timer.h b/platforms/timer.h
index 02e39e79e7..02e39e79e7 100644
--- a/tmk_core/common/timer.h
+++ b/platforms/timer.h
diff --git a/tmk_core/common/wait.h b/platforms/wait.h
index cf7180fb07..cf7180fb07 100644
--- a/tmk_core/common/wait.h
+++ b/platforms/wait.h
diff --git a/tmk_core/common/webusb.c b/platforms/webusb.c
index bc349e6afa..bc349e6afa 100644
--- a/tmk_core/common/webusb.c
+++ b/platforms/webusb.c
diff --git a/tmk_core/common/webusb.h b/platforms/webusb.h
index 7bec7c50e1..7bec7c50e1 100644
--- a/tmk_core/common/webusb.h
+++ b/platforms/webusb.h
diff --git a/quantum/action.c b/quantum/action.c
index 0946b0ca1a..a6568f8b38 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keycode.h"
#include "keyboard.h"
#include "mousekey.h"
+#include "programmable_button.h"
#include "command.h"
#include "led.h"
#include "action_layer.h"
@@ -26,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action_util.h"
#include "action.h"
#include "wait.h"
+#include "keycode_config.h"
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
@@ -43,10 +45,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
int tp_buttons;
-#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY)
+#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
int retro_tapping_counter = 0;
#endif
+#if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+# include "process_auto_shift.h"
+#endif
+
#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; }
#endif
@@ -67,7 +73,7 @@ void action_exec(keyevent_t event) {
dprint("EVENT: ");
debug_event(event);
dprintln();
-#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY)
+#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
retro_tapping_counter++;
#endif
}
@@ -86,22 +92,29 @@ void action_exec(keyevent_t event) {
keyrecord_t record = {.event = event};
#ifndef NO_ACTION_ONESHOT
+ if (!keymap_config.oneshot_disable) {
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
- if (has_oneshot_layer_timed_out()) {
- clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
- }
- if (has_oneshot_mods_timed_out()) {
- clear_oneshot_mods();
- }
+ if (has_oneshot_layer_timed_out()) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ }
+ if (has_oneshot_mods_timed_out()) {
+ clear_oneshot_mods();
+ }
# ifdef SWAP_HANDS_ENABLE
- if (has_oneshot_swaphands_timed_out()) {
- clear_oneshot_swaphands();
- }
+ if (has_oneshot_swaphands_timed_out()) {
+ clear_oneshot_swaphands();
+ }
# endif
# endif
+ }
#endif
#ifndef NO_ACTION_TAPPING
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ if (event.pressed) {
+ retroshift_poll_time(&event);
+ }
+# endif
if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) {
action_tapping_process(record);
}
@@ -194,7 +207,7 @@ void process_record(keyrecord_t *record) {
if (!process_record_quantum(record)) {
#ifndef NO_ACTION_ONESHOT
- if (is_oneshot_layer_active() && record->event.pressed) {
+ if (is_oneshot_layer_active() && record->event.pressed && !keymap_config.oneshot_disable) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
}
#endif
@@ -259,7 +272,7 @@ void process_action(keyrecord_t *record, action_t action) {
# ifdef SWAP_HANDS_ENABLE
&& !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)
# endif
- ) {
+ && !keymap_config.oneshot_disable) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
do_release_oneshot = !is_oneshot_layer_active();
}
@@ -273,8 +286,8 @@ void process_action(keyrecord_t *record, action_t action) {
if (event.pressed) {
if (mods) {
if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
- // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
- // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT).
+ // e.g. LSFT(KC_LEFT_GUI): we don't want the LSFT to be weak as it would make it useless.
+ // This also makes LSFT(KC_LEFT_GUI) behave exactly the same as LGUI(KC_LEFT_SHIFT).
// Same applies for some keys like KC_MEH which are declared as MEH(KC_NO).
add_mods(mods);
} else {
@@ -303,41 +316,68 @@ void process_action(keyrecord_t *record, action_t action) {
# ifndef NO_ACTION_ONESHOT
case MODS_ONESHOT:
// Oneshot modifier
- if (event.pressed) {
- if (tap_count == 0) {
- dprint("MODS_TAP: Oneshot: 0\n");
- register_mods(mods | get_oneshot_mods());
- } else if (tap_count == 1) {
- dprint("MODS_TAP: Oneshot: start\n");
- set_oneshot_mods(mods | get_oneshot_mods());
-# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
- } else if (tap_count == ONESHOT_TAP_TOGGLE) {
- dprint("MODS_TAP: Toggling oneshot");
- clear_oneshot_mods();
- set_oneshot_locked_mods(mods);
- register_mods(mods);
-# endif
+ if (keymap_config.oneshot_disable) {
+ if (event.pressed) {
+ if (mods) {
+ if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
+ // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
+ // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT).
+ // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO).
+ add_mods(mods);
+ } else {
+ add_weak_mods(mods);
+ }
+ send_keyboard_report();
+ }
+ register_code(action.key.code);
} else {
- register_mods(mods | get_oneshot_mods());
+ unregister_code(action.key.code);
+ if (mods) {
+ if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
+ del_mods(mods);
+ } else {
+ del_weak_mods(mods);
+ }
+ send_keyboard_report();
+ }
}
} else {
- if (tap_count == 0) {
- clear_oneshot_mods();
- unregister_mods(mods);
- } else if (tap_count == 1) {
- // Retain Oneshot mods
+ if (event.pressed) {
+ if (tap_count == 0) {
+ dprint("MODS_TAP: Oneshot: 0\n");
+ register_mods(mods | get_oneshot_mods());
+ } else if (tap_count == 1) {
+ dprint("MODS_TAP: Oneshot: start\n");
+ set_oneshot_mods(mods | get_oneshot_mods());
# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
- if (mods & get_mods()) {
- clear_oneshot_locked_mods();
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ dprint("MODS_TAP: Toggling oneshot");
clear_oneshot_mods();
- unregister_mods(mods);
- }
- } else if (tap_count == ONESHOT_TAP_TOGGLE) {
- // Toggle Oneshot Layer
+ set_oneshot_locked_mods(mods);
+ register_mods(mods);
# endif
+ } else {
+ register_mods(mods | get_oneshot_mods());
+ }
} else {
- clear_oneshot_mods();
- unregister_mods(mods);
+ if (tap_count == 0) {
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ } else if (tap_count == 1) {
+ // Retain Oneshot mods
+# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ if (mods & get_mods()) {
+ clear_oneshot_locked_mods();
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ }
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ // Toggle Oneshot Layer
+# endif
+ } else {
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ }
}
}
break;
@@ -379,7 +419,7 @@ void process_action(keyrecord_t *record, action_t action) {
} else {
if (tap_count > 0) {
dprint("MODS_TAP: Tap: unregister_code\n");
- if (action.layer_tap.code == KC_CAPS) {
+ if (action.layer_tap.code == KC_CAPS_LOCK) {
wait_ms(TAP_HOLD_CAPS_DELAY);
} else {
wait_ms(TAP_CODE_DELAY);
@@ -522,39 +562,47 @@ void process_action(keyrecord_t *record, action_t action) {
# ifndef NO_ACTION_ONESHOT
case OP_ONESHOT:
// Oneshot modifier
-# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
- do_release_oneshot = false;
- if (event.pressed) {
- del_mods(get_oneshot_locked_mods());
- if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
- reset_oneshot_layer();
- layer_off(action.layer_tap.val);
- break;
- } else if (tap_count < ONESHOT_TAP_TOGGLE) {
+ if (keymap_config.oneshot_disable) {
+ if (event.pressed) {
layer_on(action.layer_tap.val);
- set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ } else {
+ layer_off(action.layer_tap.val);
}
} else {
- add_mods(get_oneshot_locked_mods());
- if (tap_count >= ONESHOT_TAP_TOGGLE) {
- reset_oneshot_layer();
- clear_oneshot_locked_mods();
- set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
+# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ do_release_oneshot = false;
+ if (event.pressed) {
+ del_mods(get_oneshot_locked_mods());
+ if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
+ reset_oneshot_layer();
+ layer_off(action.layer_tap.val);
+ break;
+ } else if (tap_count < ONESHOT_TAP_TOGGLE) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ }
} else {
- clear_oneshot_layer_state(ONESHOT_PRESSED);
+ add_mods(get_oneshot_locked_mods());
+ if (tap_count >= ONESHOT_TAP_TOGGLE) {
+ reset_oneshot_layer();
+ clear_oneshot_locked_mods();
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ }
}
- }
# else
- if (event.pressed) {
- layer_on(action.layer_tap.val);
- set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
- } else {
- clear_oneshot_layer_state(ONESHOT_PRESSED);
- if (tap_count > 1) {
- clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ if (event.pressed) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ if (tap_count > 1) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ }
}
- }
# endif
+ }
break;
# endif
default:
@@ -570,7 +618,7 @@ void process_action(keyrecord_t *record, action_t action) {
} else {
if (tap_count > 0) {
dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
- if (action.layer_tap.code == KC_CAPS) {
+ if (action.layer_tap.code == KC_CAPS_LOCK) {
wait_ms(TAP_HOLD_CAPS_DELAY);
} else {
wait_ms(TAP_CODE_DELAY);
@@ -691,7 +739,7 @@ void process_action(keyrecord_t *record, action_t action) {
#endif
#ifndef NO_ACTION_TAPPING
-# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY)
+# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
if (!is_tap_action(action)) {
retro_tapping_counter = 0;
} else {
@@ -708,7 +756,11 @@ void process_action(keyrecord_t *record, action_t action) {
get_retro_tapping(get_event_keycode(record->event, false), record) &&
# endif
retro_tapping_counter == 2) {
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ process_auto_shift(action.layer_tap.code, record);
+# else
tap_code(action.layer_tap.code);
+# endif
}
retro_tapping_counter = 0;
}
@@ -747,44 +799,45 @@ void register_code(uint8_t code) {
return;
}
#ifdef LOCKING_SUPPORT_ENABLE
- else if (KC_LOCKING_CAPS == code) {
+ else if (KC_LOCKING_CAPS_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
// Resync: ignore if caps lock already is on
if (host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK)) return;
# endif
- add_key(KC_CAPSLOCK);
+ add_key(KC_CAPS_LOCK);
send_keyboard_report();
wait_ms(100);
- del_key(KC_CAPSLOCK);
+ del_key(KC_CAPS_LOCK);
send_keyboard_report();
}
- else if (KC_LOCKING_NUM == code) {
+ else if (KC_LOCKING_NUM_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
if (host_keyboard_leds() & (1 << USB_LED_NUM_LOCK)) return;
# endif
- add_key(KC_NUMLOCK);
+ add_key(KC_NUM_LOCK);
send_keyboard_report();
wait_ms(100);
- del_key(KC_NUMLOCK);
+ del_key(KC_NUM_LOCK);
send_keyboard_report();
}
- else if (KC_LOCKING_SCROLL == code) {
+ else if (KC_LOCKING_SCROLL_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
if (host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK)) return;
# endif
- add_key(KC_SCROLLLOCK);
+ add_key(KC_SCROLL_LOCK);
send_keyboard_report();
wait_ms(100);
- del_key(KC_SCROLLLOCK);
+ del_key(KC_SCROLL_LOCK);
send_keyboard_report();
}
#endif
- else if IS_KEY (code) {
- // TODO: should push command_proc out of this block?
- if (command_proc(code)) return;
+ else if
+ IS_KEY(code) {
+ // TODO: should push command_proc out of this block?
+ if (command_proc(code)) return;
#ifndef NO_ACTION_ONESHOT
/* TODO: remove
@@ -801,33 +854,35 @@ void register_code(uint8_t code) {
} else
*/
#endif
- {
- // Force a new key press if the key is already pressed
- // without this, keys with the same keycode, but different
- // modifiers will be reported incorrectly, see issue #1708
- if (is_key_pressed(keyboard_report, code)) {
- del_key(code);
+ {
+ // Force a new key press if the key is already pressed
+ // without this, keys with the same keycode, but different
+ // modifiers will be reported incorrectly, see issue #1708
+ if (is_key_pressed(keyboard_report, code)) {
+ del_key(code);
+ send_keyboard_report();
+ }
+ add_key(code);
send_keyboard_report();
}
- add_key(code);
+ }
+ else if
+ IS_MOD(code) {
+ add_mods(MOD_BIT(code));
send_keyboard_report();
}
- } else if IS_MOD (code) {
- add_mods(MOD_BIT(code));
- send_keyboard_report();
- }
#ifdef EXTRAKEY_ENABLE
- else if IS_SYSTEM (code) {
- host_system_send(KEYCODE2SYSTEM(code));
- } else if IS_CONSUMER (code) {
- host_consumer_send(KEYCODE2CONSUMER(code));
- }
+ else if
+ IS_SYSTEM(code) { host_system_send(KEYCODE2SYSTEM(code)); }
+ else if
+ IS_CONSUMER(code) { host_consumer_send(KEYCODE2CONSUMER(code)); }
#endif
#ifdef MOUSEKEY_ENABLE
- else if IS_MOUSEKEY (code) {
- mousekey_on(code);
- mousekey_send();
- }
+ else if
+ IS_MOUSEKEY(code) {
+ mousekey_on(code);
+ mousekey_send();
+ }
#endif
}
@@ -840,54 +895,58 @@ void unregister_code(uint8_t code) {
return;
}
#ifdef LOCKING_SUPPORT_ENABLE
- else if (KC_LOCKING_CAPS == code) {
+ else if (KC_LOCKING_CAPS_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
// Resync: ignore if caps lock already is off
if (!(host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK))) return;
# endif
- add_key(KC_CAPSLOCK);
+ add_key(KC_CAPS_LOCK);
send_keyboard_report();
- del_key(KC_CAPSLOCK);
+ del_key(KC_CAPS_LOCK);
send_keyboard_report();
}
- else if (KC_LOCKING_NUM == code) {
+ else if (KC_LOCKING_NUM_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
if (!(host_keyboard_leds() & (1 << USB_LED_NUM_LOCK))) return;
# endif
- add_key(KC_NUMLOCK);
+ add_key(KC_NUM_LOCK);
send_keyboard_report();
- del_key(KC_NUMLOCK);
+ del_key(KC_NUM_LOCK);
send_keyboard_report();
}
- else if (KC_LOCKING_SCROLL == code) {
+ else if (KC_LOCKING_SCROLL_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
if (!(host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK))) return;
# endif
- add_key(KC_SCROLLLOCK);
+ add_key(KC_SCROLL_LOCK);
send_keyboard_report();
- del_key(KC_SCROLLLOCK);
+ del_key(KC_SCROLL_LOCK);
send_keyboard_report();
}
#endif
- else if IS_KEY (code) {
- del_key(code);
- send_keyboard_report();
- } else if IS_MOD (code) {
- del_mods(MOD_BIT(code));
- send_keyboard_report();
- } else if IS_SYSTEM (code) {
- host_system_send(0);
- } else if IS_CONSUMER (code) {
- host_consumer_send(0);
- }
+ else if
+ IS_KEY(code) {
+ del_key(code);
+ send_keyboard_report();
+ }
+ else if
+ IS_MOD(code) {
+ del_mods(MOD_BIT(code));
+ send_keyboard_report();
+ }
+ else if
+ IS_SYSTEM(code) { host_system_send(0); }
+ else if
+ IS_CONSUMER(code) { host_consumer_send(0); }
#ifdef MOUSEKEY_ENABLE
- else if IS_MOUSEKEY (code) {
- mousekey_off(code);
- mousekey_send();
- }
+ else if
+ IS_MOUSEKEY(code) {
+ mousekey_off(code);
+ mousekey_send();
+ }
#endif
}
@@ -906,9 +965,9 @@ void tap_code_delay(uint8_t code, uint16_t delay) {
/** \brief Tap a keycode with the default delay.
*
- * \param code The basic keycode to tap. If `code` is `KC_CAPS`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
+ * \param code The basic keycode to tap. If `code` is `KC_CAPS_LOCK`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
*/
-void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); }
+void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS_LOCK ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); }
/** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately.
*
@@ -989,6 +1048,10 @@ void clear_keyboard_but_mods_and_keys() {
mousekey_clear();
mousekey_send();
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ programmable_button_clear();
+ programmable_button_send();
+#endif
}
/** \brief Utilities for actions. (FIXME: Needs better description)
@@ -1029,7 +1092,7 @@ bool is_tap_action(action_t action) {
case ACT_LAYER_TAP:
case ACT_LAYER_TAP_EXT:
switch (action.layer_tap.code) {
- case KC_NO ... KC_RGUI:
+ case KC_NO ... KC_RIGHT_GUI:
case OP_TAP_TOGGLE:
case OP_ONESHOT:
return true;
@@ -1037,7 +1100,7 @@ bool is_tap_action(action_t action) {
return false;
case ACT_SWAP_HANDS:
switch (action.swap.code) {
- case KC_NO ... KC_RGUI:
+ case KC_NO ... KC_RIGHT_GUI:
case OP_SH_TAP_TOGGLE:
return true;
}
diff --git a/quantum/action.h b/quantum/action.h
index 8a357ded87..b562f18c5b 100644
--- a/quantum/action.h
+++ b/quantum/action.h
@@ -88,7 +88,7 @@ extern bool disable_action_cache;
/* Code for handling one-handed key modifiers. */
#ifdef SWAP_HANDS_ENABLE
-extern bool swap_hands;
+extern bool swap_hands;
extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS];
# if (MATRIX_COLS <= 8)
typedef uint8_t swap_state_row_t;
diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c
index 36839f9faf..d2c93f85e3 100644
--- a/quantum/action_tapping.c
+++ b/quantum/action_tapping.c
@@ -18,18 +18,20 @@
# define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
# define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
# define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
-#ifndef COMBO_ENABLE
-# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)))
-#else
-# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode)
-#endif
+# ifndef COMBO_ENABLE
+# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)))
+# else
+# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode)
+# endif
+
+uint16_t g_tapping_term = TAPPING_TERM;
-__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; }
+__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return g_tapping_term; }
# ifdef TAPPING_TERM_PER_KEY
# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_record_keycode(&tapping_key, false), &tapping_key))
# else
-# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
+# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < g_tapping_term)
# endif
# ifdef TAPPING_FORCE_HOLD_PER_KEY
@@ -44,6 +46,10 @@ __attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *re
__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; }
# endif
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+# include "process_auto_shift.h"
+# endif
+
static keyrecord_t tapping_key = {};
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
static uint8_t waiting_buffer_head = 0;
@@ -107,12 +113,29 @@ void action_tapping_process(keyrecord_t record) {
/* return true when key event is processed or consumed. */
bool process_tapping(keyrecord_t *keyp) {
keyevent_t event = keyp->event;
+# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(TAPPING_TERM_PER_KEY) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(TAPPING_FORCE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
+ uint16_t tapping_keycode = get_record_keycode(&tapping_key, false);
+# endif
// if tapping
if (IS_TAPPING_PRESSED()) {
- if (WITHIN_TAPPING_TERM(event)) {
+ // clang-format off
+ if (WITHIN_TAPPING_TERM(event)
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ || (
+# ifdef RETRO_TAPPING_PER_KEY
+ get_retro_tapping(tapping_keycode, keyp) &&
+# endif
+ (RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16(event.time, tapping_key.event.time) < (RETRO_SHIFT + 0)
+ )
+# endif
+ ) {
+ // clang-format on
if (tapping_key.tap.count == 0) {
if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ retroshift_swap_times();
+# endif
// first tap!
debug("Tapping: First tap(0->1).\n");
tapping_key.tap.count = 1;
@@ -128,22 +151,70 @@ bool process_tapping(keyrecord_t *keyp) {
* This can register the key before settlement of tapping,
* useful for long TAPPING_TERM but may prevent fast typing.
*/
-# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY)
- else if (((
+ // clang-format off
+# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
+ else if (
+ (
+ (
+ (
# ifdef TAPPING_TERM_PER_KEY
- get_tapping_term(get_record_keycode(&tapping_key, false), keyp)
+ get_tapping_term(tapping_keycode, keyp)
# else
- TAPPING_TERM
+ g_tapping_term
# endif
- >= 500)
+ >= 500
+ )
# ifdef PERMISSIVE_HOLD_PER_KEY
- || get_permissive_hold(get_record_keycode(&tapping_key, false), keyp)
+ || get_permissive_hold(tapping_keycode, keyp)
# elif defined(PERMISSIVE_HOLD)
- || true
+ || true
+# endif
+ ) && IS_RELEASED(event) && waiting_buffer_typed(event)
+ )
+ // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
+ // unnecessarily and fixes them for Layer Taps.
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ || (
+# ifdef RETRO_TAPPING_PER_KEY
+ get_retro_tapping(tapping_keycode, keyp) &&
+# endif
+ (
+ // Rolled over the two keys.
+ (
+ (
+ false
+# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
+ || (
+ IS_LT(tapping_keycode)
+# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
+ && get_hold_on_other_key_press(tapping_keycode, keyp)
+# endif
+ )
+# endif
+# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
+ || (
+ IS_MT(tapping_keycode)
+# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
+ && !get_ignore_mod_tap_interrupt(tapping_keycode, keyp)
+# endif
+ )
+# endif
+ ) && tapping_key.tap.interrupted == true
+ )
+ // Makes Retro Shift ignore [IGNORE_MOD_TAP_INTERRUPT's
+ // effects on nested taps for MTs and the default
+ // behavior of LTs] below TAPPING_TERM or RETRO_SHIFT.
+ || (
+ IS_RETRO(tapping_keycode)
+ && (event.key.col != tapping_key.event.key.col || event.key.row != tapping_key.event.key.row)
+ && IS_RELEASED(event) && waiting_buffer_typed(event)
+ )
+ )
+ )
# endif
- ) &&
- IS_RELEASED(event) && waiting_buffer_typed(event)) {
+ ) {
+ // clang-format on
debug("Tapping: End. No tap. Interfered by typing key\n");
process_record(&tapping_key);
tapping_key = (keyrecord_t){};
@@ -181,7 +252,7 @@ bool process_tapping(keyrecord_t *keyp) {
tapping_key.tap.interrupted = true;
# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
- if (get_hold_on_other_key_press(get_record_keycode(&tapping_key, false), keyp))
+ if (get_hold_on_other_key_press(tapping_keycode, keyp))
# endif
{
debug("Tapping: End. No tap. Interfered by pressed key\n");
@@ -212,11 +283,15 @@ bool process_tapping(keyrecord_t *keyp) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last tap(>1).\n");
// unregister key
- process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false,
-#ifdef COMBO_ENABLE
- .keycode = tapping_key.keycode,
-#endif
- });
+ process_record(&(keyrecord_t){
+ .tap = tapping_key.tap,
+ .event.key = tapping_key.event.key,
+ .event.time = event.time,
+ .event.pressed = false,
+# ifdef COMBO_ENABLE
+ .keycode = tapping_key.keycode,
+# endif
+ });
} else {
debug("Tapping: Start while last tap(1).\n");
}
@@ -254,11 +329,15 @@ bool process_tapping(keyrecord_t *keyp) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
// unregister key
- process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false,
-#ifdef COMBO_ENABLE
- .keycode = tapping_key.keycode,
-#endif
- });
+ process_record(&(keyrecord_t){
+ .tap = tapping_key.tap,
+ .event.key = tapping_key.event.key,
+ .event.time = event.time,
+ .event.pressed = false,
+# ifdef COMBO_ENABLE
+ .keycode = tapping_key.keycode,
+# endif
+ });
} else {
debug("Tapping: Start while last timeout tap(1).\n");
}
@@ -276,14 +355,25 @@ bool process_tapping(keyrecord_t *keyp) {
}
}
} else if (IS_TAPPING_RELEASED()) {
- if (WITHIN_TAPPING_TERM(event)) {
+ // clang-format off
+ if (WITHIN_TAPPING_TERM(event)
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ || (
+# ifdef RETRO_TAPPING_PER_KEY
+ get_retro_tapping(tapping_keycode, keyp) &&
+# endif
+ (RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16(event.time, tapping_key.event.time) < (RETRO_SHIFT + 0)
+ )
+# endif
+ ) {
+ // clang-format on
if (event.pressed) {
if (IS_TAPPING_RECORD(keyp)) {
//# ifndef TAPPING_FORCE_HOLD
# if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY)
if (
# ifdef TAPPING_FORCE_HOLD_PER_KEY
- !get_tapping_force_hold(get_record_keycode(&tapping_key, false), keyp) &&
+ !get_tapping_force_hold(tapping_keycode, keyp) &&
# endif
!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
// sequential tap.
diff --git a/quantum/action_tapping.h b/quantum/action_tapping.h
index 7de8049c7f..b2feb6850c 100644
--- a/quantum/action_tapping.h
+++ b/quantum/action_tapping.h
@@ -33,10 +33,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache);
uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache);
void action_tapping_process(keyrecord_t record);
+#endif
uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record);
bool get_permissive_hold(uint16_t keycode, keyrecord_t *record);
bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record);
bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record);
bool get_retro_tapping(uint16_t keycode, keyrecord_t *record);
+
+#ifdef DYNAMIC_TAPPING_TERM_ENABLE
+extern uint16_t g_tapping_term;
#endif
diff --git a/quantum/action_util.c b/quantum/action_util.c
index 9a85bd5040..78e02aec18 100644
--- a/quantum/action_util.c
+++ b/quantum/action_util.c
@@ -170,7 +170,7 @@ void reset_oneshot_layer(void) {
void clear_oneshot_layer_state(oneshot_fullfillment_t state) {
uint8_t start_state = oneshot_layer_data;
oneshot_layer_data &= ~state;
- if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) {
+ if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) && !keymap_config.oneshot_disable) {
layer_off(get_oneshot_layer());
reset_oneshot_layer();
}
@@ -189,6 +189,7 @@ void oneshot_set(bool active) {
if (keymap_config.oneshot_disable != active) {
keymap_config.oneshot_disable = active;
eeconfig_update_keymap(keymap_config.raw);
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
dprintf("Oneshot: active: %d\n", active);
}
}
diff --git a/quantum/api.c b/quantum/api.c
deleted file mode 100644
index 1685744589..0000000000
--- a/quantum/api.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Copyright 2016 Jack Humbert
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "api.h"
-#include "quantum.h"
-
-void dword_to_bytes(uint32_t dword, uint8_t* bytes) {
- bytes[0] = (dword >> 24) & 0xFF;
- bytes[1] = (dword >> 16) & 0xFF;
- bytes[2] = (dword >> 8) & 0xFF;
- bytes[3] = (dword >> 0) & 0xFF;
-}
-
-uint32_t bytes_to_dword(uint8_t* bytes, uint8_t index) { return ((uint32_t)bytes[index + 0] << 24) | ((uint32_t)bytes[index + 1] << 16) | ((uint32_t)bytes[index + 2] << 8) | (uint32_t)bytes[index + 3]; }
-
-__attribute__((weak)) bool process_api_quantum(uint8_t length, uint8_t* data) { return process_api_keyboard(length, data); }
-
-__attribute__((weak)) bool process_api_keyboard(uint8_t length, uint8_t* data) { return process_api_user(length, data); }
-
-__attribute__((weak)) bool process_api_user(uint8_t length, uint8_t* data) { return true; }
-
-void process_api(uint16_t length, uint8_t* data) {
- // SEND_STRING("\nRX: ");
- // for (uint8_t i = 0; i < length; i++) {
- // send_byte(data[i]);
- // SEND_STRING(" ");
- // }
- if (!process_api_quantum(length, data)) return;
-
- switch (data[0]) {
- case MT_SET_DATA:
- switch (data[1]) {
- case DT_DEFAULT_LAYER: {
- eeconfig_update_default_layer(data[2]);
- default_layer_set((uint32_t)(data[2]));
- break;
- }
- case DT_KEYMAP_OPTIONS: {
- eeconfig_update_keymap(data[2]);
- break;
- }
- case DT_RGBLIGHT: {
-#ifdef RGBLIGHT_ENABLE
- uint32_t rgblight = bytes_to_dword(data, 2);
- eeconfig_update_rgblight(rgblight);
-#endif
- break;
- }
- }
- case MT_GET_DATA:
- switch (data[1]) {
- case DT_HANDSHAKE: {
- MT_GET_DATA_ACK(DT_HANDSHAKE, NULL, 0);
- break;
- }
- case DT_DEBUG: {
- uint8_t debug_bytes[1] = {eeprom_read_byte(EECONFIG_DEBUG)};
- MT_GET_DATA_ACK(DT_DEBUG, debug_bytes, 1);
- break;
- }
- case DT_DEFAULT_LAYER: {
- uint8_t default_bytes[1] = {eeprom_read_byte(EECONFIG_DEFAULT_LAYER)};
- MT_GET_DATA_ACK(DT_DEFAULT_LAYER, default_bytes, 1);
- break;
- }
- case DT_CURRENT_LAYER: {
- uint8_t layer_state_bytes[4];
- dword_to_bytes(layer_state, layer_state_bytes);
- MT_GET_DATA_ACK(DT_CURRENT_LAYER, layer_state_bytes, 4);
- break;
- }
- case DT_AUDIO: {
-#ifdef AUDIO_ENABLE
- uint8_t audio_bytes[1] = {eeprom_read_byte(EECONFIG_AUDIO)};
- MT_GET_DATA_ACK(DT_AUDIO, audio_bytes, 1);
-#else
- MT_GET_DATA_ACK(DT_AUDIO, NULL, 0);
-#endif
- break;
- }
- case DT_BACKLIGHT: {
-#ifdef BACKLIGHT_ENABLE
- uint8_t backlight_bytes[1] = {eeprom_read_byte(EECONFIG_BACKLIGHT)};
- MT_GET_DATA_ACK(DT_BACKLIGHT, backlight_bytes, 1);
-#else
- MT_GET_DATA_ACK(DT_BACKLIGHT, NULL, 0);
-#endif
- break;
- }
- case DT_RGBLIGHT: {
-#ifdef RGBLIGHT_ENABLE
- uint8_t rgblight_bytes[4];
- dword_to_bytes(eeconfig_read_rgblight(), rgblight_bytes);
- MT_GET_DATA_ACK(DT_RGBLIGHT, rgblight_bytes, 4);
-#else
- MT_GET_DATA_ACK(DT_RGBLIGHT, NULL, 0);
-#endif
- break;
- }
- case DT_KEYMAP_OPTIONS: {
- uint8_t keymap_bytes[1] = {eeconfig_read_keymap()};
- MT_GET_DATA_ACK(DT_KEYMAP_OPTIONS, keymap_bytes, 1);
- break;
- }
- case DT_KEYMAP_SIZE: {
- uint8_t keymap_size[2] = {MATRIX_ROWS, MATRIX_COLS};
- MT_GET_DATA_ACK(DT_KEYMAP_SIZE, keymap_size, 2);
- break;
- }
- // This may be too much
- // case DT_KEYMAP: {
- // uint8_t keymap_data[MATRIX_ROWS * MATRIX_COLS * 4 + 3];
- // keymap_data[0] = data[2];
- // keymap_data[1] = MATRIX_ROWS;
- // keymap_data[2] = MATRIX_COLS;
- // for (int i = 0; i < MATRIX_ROWS; i++) {
- // for (int j = 0; j < MATRIX_COLS; j++) {
- // keymap_data[3 + (i*MATRIX_COLS*2) + (j*2)] = pgm_read_word(&keymaps[data[2]][i][j]) >> 8;
- // keymap_data[3 + (i*MATRIX_COLS*2) + (j*2) + 1] = pgm_read_word(&keymaps[data[2]][i][j]) & 0xFF;
- // }
- // }
- // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, MATRIX_ROWS * MATRIX_COLS * 4 + 3);
- // // uint8_t keymap_data[5];
- // // keymap_data[0] = data[2];
- // // keymap_data[1] = data[3];
- // // keymap_data[2] = data[4];
- // // keymap_data[3] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) >> 8;
- // // keymap_data[4] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) & 0xFF;
-
- // // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, 5);
- // break;
- // }
- default:
- break;
- }
- break;
- case MT_SET_DATA_ACK:
- case MT_GET_DATA_ACK:
- break;
- case MT_SEND_DATA:
- break;
- case MT_SEND_DATA_ACK:
- break;
- case MT_EXE_ACTION:
- break;
- case MT_EXE_ACTION_ACK:
- break;
- case MT_TYPE_ERROR:
- break;
- default:; // command not recognised
- SEND_BYTES(MT_TYPE_ERROR, DT_NONE, data, length);
- break;
-
- // #ifdef RGBLIGHT_ENABLE
- // case 0x27: ; // RGB LED functions
- // switch (*data++) {
- // case 0x00: ; // Update HSV
- // rgblight_sethsv((data[0] << 8 | data[1]) % 360, data[2], data[3]);
- // break;
- // case 0x01: ; // Update RGB
- // break;
- // case 0x02: ; // Update mode
- // rgblight_mode(data[0]);
- // break;
- // }
- // break;
- // #endif
- }
-}
diff --git a/quantum/api.h b/quantum/api.h
deleted file mode 100644
index 0a30e9d6cc..0000000000
--- a/quantum/api.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright 2016 Jack Humbert
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#ifdef __AVR__
-# include "lufa.h"
-#endif
-
-enum MESSAGE_TYPE {
- MT_GET_DATA = 0x10, // Get data from keyboard
- MT_GET_DATA_ACK = 0x11, // returned data to process (ACK)
- MT_SET_DATA = 0x20, // Set data on keyboard
- MT_SET_DATA_ACK = 0x21, // returned data to confirm (ACK)
- MT_SEND_DATA = 0x30, // Sending data/action from keyboard
- MT_SEND_DATA_ACK = 0x31, // returned data/action confirmation (ACK)
- MT_EXE_ACTION = 0x40, // executing actions on keyboard
- MT_EXE_ACTION_ACK = 0x41, // return confirmation/value (ACK)
- MT_TYPE_ERROR = 0x80 // type not recognised (ACK)
-};
-
-enum DATA_TYPE { DT_NONE = 0x00, DT_HANDSHAKE, DT_DEFAULT_LAYER, DT_CURRENT_LAYER, DT_KEYMAP_OPTIONS, DT_BACKLIGHT, DT_RGBLIGHT, DT_UNICODE, DT_DEBUG, DT_AUDIO, DT_QUANTUM_ACTION, DT_KEYBOARD_ACTION, DT_USER_ACTION, DT_KEYMAP_SIZE, DT_KEYMAP };
-
-void dword_to_bytes(uint32_t dword, uint8_t* bytes);
-uint32_t bytes_to_dword(uint8_t* bytes, uint8_t index);
-
-#define MT_GET_DATA(data_type, data, length) SEND_BYTES(MT_GET_DATA, data_type, data, length)
-#define MT_GET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_GET_DATA_ACK, data_type, data, length)
-#define MT_SET_DATA(data_type, data, length) SEND_BYTES(MT_SET_DATA, data_type, data, length)
-#define MT_SET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SET_DATA_ACK, data_type, data, length)
-#define MT_SEND_DATA(data_type, data, length) SEND_BYTES(MT_SEND_DATA, data_type, data, length)
-#define MT_SEND_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SEND_DATA_ACK, data_type, data, length)
-#define MT_EXE_ACTION(data_type, data, length) SEND_BYTES(MT_EXE_ACTION, data_type, data, length)
-#define MT_EXE_ACTION_ACK(data_type, data, length) SEND_BYTES(MT_EXE_ACTION_ACK, data_type, data, length)
-
-void process_api(uint16_t length, uint8_t* data);
-
-__attribute__((weak)) bool process_api_quantum(uint8_t length, uint8_t* data);
-
-__attribute__((weak)) bool process_api_keyboard(uint8_t length, uint8_t* data);
-
-__attribute__((weak)) bool process_api_user(uint8_t length, uint8_t* data);
diff --git a/quantum/api/api_sysex.c b/quantum/api/api_sysex.c
deleted file mode 100644
index 07c90cf804..0000000000
--- a/quantum/api/api_sysex.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Copyright 2016 Jack Humbert, Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include "api_sysex.h"
-#include "sysex_tools.h"
-#include "print.h"
-#include "qmk_midi.h"
-
-void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t* bytes, uint16_t length) {
- // SEND_STRING("\nTX: ");
- // for (uint8_t i = 0; i < length; i++) {
- // send_byte(bytes[i]);
- // SEND_STRING(" ");
- // }
- if (length > API_SYSEX_MAX_SIZE) {
- xprintf("Sysex msg too big %d %d %d", message_type, data_type, length);
- return;
- }
-
- // The buffer size required is calculated as the following
- // API_SYSEX_MAX_SIZE is the maximum length
- // In addition to that we have a two byte message header consisting of the message_type and data_type
- // This has to be encoded with an additional overhead of one byte for every starting 7 bytes
- // We just add one extra byte in case it's not divisible by 7
- // Then we have an unencoded header consisting of 4 bytes
- // Plus a one byte terminator
- const unsigned message_header = 2;
- const unsigned unencoded_message = API_SYSEX_MAX_SIZE + message_header;
- const unsigned encoding_overhead = unencoded_message / 7 + 1;
- const unsigned encoded_size = unencoded_message + encoding_overhead;
- const unsigned unencoded_header = 4;
- const unsigned terminator = 1;
- const unsigned buffer_size = encoded_size + unencoded_header + terminator;
- uint8_t buffer[encoded_size + unencoded_header + terminator];
- // The unencoded header
- buffer[0] = 0xF0;
- buffer[1] = 0x00;
- buffer[2] = 0x00;
- buffer[3] = 0x00;
-
- // We copy the message to the end of the array, this way we can do an inplace encoding, using the same
- // buffer for both input and output
- const unsigned message_size = length + message_header;
- uint8_t* unencoded_start = buffer + buffer_size - message_size;
- uint8_t* ptr = unencoded_start;
- *(ptr++) = message_type;
- *(ptr++) = data_type;
- memcpy(ptr, bytes, length);
-
- unsigned encoded_length = sysex_encode(buffer + unencoded_header, unencoded_start, message_size);
- unsigned final_size = unencoded_header + encoded_length + terminator;
- buffer[final_size - 1] = 0xF7;
- midi_send_array(&midi_device, final_size, buffer);
-
- // SEND_STRING("\nTD: ");
- // for (uint8_t i = 0; i < encoded_length + 5; i++) {
- // send_byte(buffer[i]);
- // SEND_STRING(" ");
- // }
-}
diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h
index 56b9158a1a..290d461f5a 100644
--- a/quantum/audio/audio.h
+++ b/quantum/audio/audio.h
@@ -26,17 +26,12 @@
#if defined(__AVR__)
# include <avr/io.h>
-# if defined(AUDIO_DRIVER_PWM)
-# include "driver_avr_pwm.h"
-# endif
#endif
-#if defined(PROTOCOL_CHIBIOS)
-# if defined(AUDIO_DRIVER_PWM)
-# include "driver_chibios_pwm.h"
-# elif defined(AUDIO_DRIVER_DAC)
-# include "driver_chibios_dac.h"
-# endif
+#if defined(AUDIO_DRIVER_PWM)
+# include "audio_pwm.h"
+#elif defined(AUDIO_DRIVER_DAC)
+# include "audio_dac.h"
#endif
typedef union {
diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h
index b54b397e1c..8e80a016aa 100644
--- a/quantum/audio/song_list.h
+++ b/quantum/audio/song_list.h
@@ -20,11 +20,9 @@
#include "musical_notes.h"
-#if __GNUC__ > 5 // don't use for older gcc compilers since check isn't supported.
-# if __has_include("user_song_list.h")
-# include "user_song_list.h"
-# endif // if file exists
-#endif // __GNUC__
+#if __has_include("user_song_list.h")
+# include "user_song_list.h"
+#endif // if file exists
#define NO_SOUND
diff --git a/quantum/backlight/backlight_avr.c b/quantum/backlight/backlight_avr.c
index e47192de34..9c972ae02e 100644
--- a/quantum/backlight/backlight_avr.c
+++ b/quantum/backlight/backlight_avr.c
@@ -199,13 +199,14 @@ static inline void disable_pwm(void) {
// reaches the backlight level, where we turn off the LEDs,
// but also an overflow interrupt when the counter rolls back to 0,
// in which we're going to turn on the LEDs.
-// The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz.
+// The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz,
+// or F_CPU/BACKLIGHT_CUSTOM_RESOLUTION if used.
// Triggered when the counter reaches the OCRx value
ISR(TIMERx_COMPA_vect) { backlight_pins_off(); }
// Triggered when the counter reaches the TOP value
-// this one triggers at F_CPU/65536 =~ 244 Hz
+// this one triggers at F_CPU/ICRx = 16MHz/65536 =~ 244 Hz
ISR(TIMERx_OVF_vect) {
# ifdef BACKLIGHT_BREATHING
if (is_breathing()) {
@@ -220,7 +221,7 @@ ISR(TIMERx_OVF_vect) {
// artifacts (especially while breathing, because breathing_task
// takes many computation cycles).
// so better not turn them on while the counter TOP is very low.
- if (OCRxx > 256) {
+ if (OCRxx > ICRx / 250 + 5) {
backlight_pins_on();
}
}
@@ -231,24 +232,26 @@ ISR(TIMERx_OVF_vect) {
// See http://jared.geek.nz/2013/feb/linear-led-pwm
static uint16_t cie_lightness(uint16_t v) {
- if (v <= 5243) // if below 8% of max
- return v / 9; // same as dividing by 900%
- else {
- uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
- // to get a useful result with integer division, we shift left in the expression above
- // and revert what we've done again after squaring.
- y = y * y * y >> 8;
- if (y > 0xFFFFUL) // prevent overflow
- return 0xFFFFU;
- else
- return (uint16_t)y;
+ if (v <= (uint32_t)ICRx / 12) // If the value is less than or equal to ~8% of max
+ {
+ return v / 9; // Same as dividing by 900%
+ } else {
+ // In the next two lines values are bit-shifted. This is to avoid loosing decimals in integer math.
+ uint32_t y = (((uint32_t)v + (uint32_t)ICRx / 6) << 5) / ((uint32_t)ICRx / 6 + ICRx); // If above 8%, add ~16% of max, and normalize with (max + ~16% max)
+ uint32_t out = (y * y * y * ICRx) >> 15; // Cube it and undo the bit-shifting. (which is now three times as much due to the cubing)
+
+ if (out > ICRx) // Avoid overflows
+ {
+ out = ICRx;
+ }
+ return (uint16_t)out;
}
}
-// rescale the supplied backlight value to be in terms of the value limit
+// rescale the supplied backlight value to be in terms of the value limit // range for val is [0..ICRx]. PWM pin is high while the timer count is below val.
static uint32_t rescale_limit_val(uint32_t val) { return (val * (BACKLIGHT_LIMIT_VAL + 1)) / 256; }
-// range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
+// range for val is [0..ICRx]. PWM pin is high while the timer count is below val.
static inline void set_pwm(uint16_t val) { OCRxx = val; }
void backlight_set(uint8_t level) {
@@ -277,7 +280,7 @@ void backlight_set(uint8_t level) {
#endif
}
// Set the brightness
- set_pwm(cie_lightness(rescale_limit_val(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS)));
+ set_pwm(cie_lightness(rescale_limit_val(ICRx * (uint32_t)level / BACKLIGHT_LEVELS)));
}
void backlight_task(void) {}
@@ -292,6 +295,11 @@ void backlight_task(void) {}
static uint8_t breathing_halt = BREATHING_NO_HALT;
static uint16_t breathing_counter = 0;
+static uint8_t breath_scale_counter = 1;
+/* Run the breathing loop at ~120Hz*/
+const uint8_t breathing_ISR_frequency = 120;
+static uint16_t breathing_freq_scale_factor = 2;
+
# ifdef BACKLIGHT_PWM_TIMER
static bool breathing = false;
@@ -323,9 +331,9 @@ bool is_breathing(void) { return !!(TIMSKx & _BV(TOIEx)); }
do { \
breathing_counter = 0; \
} while (0)
-# define breathing_max() \
- do { \
- breathing_counter = get_breathing_period() * 244 / 2; \
+# define breathing_max() \
+ do { \
+ breathing_counter = get_breathing_period() * breathing_ISR_frequency / 2; \
} while (0)
void breathing_enable(void) {
@@ -369,21 +377,30 @@ void breathing_task(void)
# else
/* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
* about 244 times per second.
+ *
+ * The following ISR runs at F_CPU/ISRx. With a 16MHz clock and default pwm resolution, that means 244Hz
*/
ISR(TIMERx_OVF_vect)
# endif
{
- uint8_t breathing_period = get_breathing_period();
- uint16_t interval = (uint16_t)breathing_period * 244 / BREATHING_STEPS;
+
+ // Only run this ISR at ~120 Hz
+ if (breath_scale_counter++ == breathing_freq_scale_factor) {
+ breath_scale_counter = 1;
+ } else {
+ return;
+ }
+ uint16_t interval = (uint16_t)get_breathing_period() * breathing_ISR_frequency / BREATHING_STEPS;
// resetting after one period to prevent ugly reset at overflow.
- breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
+ breathing_counter = (breathing_counter + 1) % (get_breathing_period() * breathing_ISR_frequency);
uint8_t index = breathing_counter / interval % BREATHING_STEPS;
if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) {
breathing_interrupt_disable();
}
- set_pwm(cie_lightness(rescale_limit_val(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * 0x0101U))));
+ // Set PWM to a brightnessvalue scaled to the configured resolution
+ set_pwm(cie_lightness(rescale_limit_val(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * ICRx / 255))));
}
#endif // BACKLIGHT_BREATHING
@@ -413,16 +430,23 @@ void backlight_init_ports(void) {
"In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]."
"In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)."
*/
-# if BACKLIGHT_ON_STATE == 1
- TCCRxA = _BV(COMxx1) | _BV(WGM11);
-# else
- TCCRxA = _BV(COMxx1) | _BV(COMxx0) | _BV(WGM11);
-# endif
-
- TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
+ TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010;
+ TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
#endif
- // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
+
+#ifdef BACKLIGHT_CUSTOM_RESOLUTION
+# if (BACKLIGHT_CUSTOM_RESOLUTION > 0xFFFF || BACKLIGHT_CUSTOM_RESOLUTION < 1)
+# error "This out of range of the timer capabilities"
+# elif (BACKLIGHT_CUSTOM_RESOLUTION < 0xFF)
+# warning "Resolution lower than 0xFF isn't recommended"
+# endif
+# ifdef BACKLIGHT_BREATHING
+ breathing_freq_scale_factor = F_CPU / BACKLIGHT_CUSTOM_RESOLUTION / 120;
+# endif
+ ICRx = BACKLIGHT_CUSTOM_RESOLUTION;
+#else
ICRx = TIMER_TOP;
+#endif
backlight_init();
#ifdef BACKLIGHT_BREATHING
diff --git a/quantum/backlight/backlight_chibios.c b/quantum/backlight/backlight_chibios.c
index 4d5a69e14e..7c6edd10d6 100644
--- a/quantum/backlight/backlight_chibios.c
+++ b/quantum/backlight/backlight_chibios.c
@@ -8,9 +8,13 @@
# define BACKLIGHT_LIMIT_VAL 255
#endif
-// GPIOV2 && GPIOV3
#ifndef BACKLIGHT_PAL_MODE
-# define BACKLIGHT_PAL_MODE 2
+# if defined(USE_GPIOV1)
+# define BACKLIGHT_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
+# else
+// GPIOV2 && GPIOV3
+# define BACKLIGHT_PAL_MODE 5
+# endif
#endif
// GENERIC
@@ -70,7 +74,7 @@ static uint32_t rescale_limit_val(uint32_t val) {
void backlight_init_ports(void) {
#ifdef USE_GPIOV1
- palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+ palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), BACKLIGHT_PAL_MODE);
#else
palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_ALTERNATE(BACKLIGHT_PAL_MODE));
#endif
diff --git a/quantum/config_common.h b/quantum/config_common.h
index 661609ef2a..d93477b27e 100644
--- a/quantum/config_common.h
+++ b/quantum/config_common.h
@@ -24,7 +24,4 @@
#define COL2ROW 0
#define ROW2COL 1
-// Deprecated alias - avoid using
-#define KEYMAP LAYOUT
-
#include "song_list.h"
diff --git a/quantum/debounce/asym_eager_defer_pk.c b/quantum/debounce/asym_eager_defer_pk.c
index 24380dc5e5..81f39383c4 100644
--- a/quantum/debounce/asym_eager_defer_pk.c
+++ b/quantum/debounce/asym_eager_defer_pk.c
@@ -46,17 +46,17 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
#define ROW_SHIFTER ((matrix_row_t)1)
typedef struct {
- bool pressed : 1;
+ bool pressed : 1;
uint8_t time : 7;
} debounce_counter_t;
#if DEBOUNCE > 0
static debounce_counter_t *debounce_counters;
-static fast_timer_t last_time;
-static bool counters_need_update;
-static bool matrix_need_update;
+static fast_timer_t last_time;
+static bool counters_need_update;
+static bool matrix_need_update;
-#define DEBOUNCE_ELAPSED 0
+# define DEBOUNCE_ELAPSED 0
static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
@@ -64,7 +64,7 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
// we use num_rows rather than MATRIX_ROWS to support split keyboards
void debounce_init(uint8_t num_rows) {
debounce_counters = malloc(num_rows * MATRIX_COLS * sizeof(debounce_counter_t));
- int i = 0;
+ int i = 0;
for (uint8_t r = 0; r < num_rows; r++) {
for (uint8_t c = 0; c < MATRIX_COLS; c++) {
debounce_counters[i++].time = DEBOUNCE_ELAPSED;
@@ -81,10 +81,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
bool updated_last = false;
if (counters_need_update) {
- fast_timer_t now = timer_read_fast();
+ fast_timer_t now = timer_read_fast();
fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
- last_time = now;
+ last_time = now;
updated_last = true;
if (elapsed_time > UINT8_MAX) {
elapsed_time = UINT8_MAX;
@@ -108,7 +108,7 @@ static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[],
debounce_counter_t *debounce_pointer = debounce_counters;
counters_need_update = false;
- matrix_need_update = false;
+ matrix_need_update = false;
for (uint8_t row = 0; row < num_rows; row++) {
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
@@ -146,8 +146,8 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
if (delta & col_mask) {
if (debounce_pointer->time == DEBOUNCE_ELAPSED) {
debounce_pointer->pressed = (raw[row] & col_mask);
- debounce_pointer->time = DEBOUNCE;
- counters_need_update = true;
+ debounce_pointer->time = DEBOUNCE;
+ counters_need_update = true;
if (debounce_pointer->pressed) {
// key-down: eager
diff --git a/quantum/debounce/sym_defer_g.c b/quantum/debounce/sym_defer_g.c
index fbefd55ede..9155eb914c 100644
--- a/quantum/debounce/sym_defer_g.c
+++ b/quantum/debounce/sym_defer_g.c
@@ -25,7 +25,7 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
#endif
#if DEBOUNCE > 0
-static bool debouncing = false;
+static bool debouncing = false;
static fast_timer_t debouncing_time;
void debounce_init(uint8_t num_rows) {}
diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c
index 626a9be841..1b698ba347 100644
--- a/quantum/debounce/sym_defer_pk.c
+++ b/quantum/debounce/sym_defer_pk.c
@@ -49,7 +49,7 @@ static debounce_counter_t *debounce_counters;
static fast_timer_t last_time;
static bool counters_need_update;
-#define DEBOUNCE_ELAPSED 0
+# define DEBOUNCE_ELAPSED 0
static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
@@ -74,10 +74,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
bool updated_last = false;
if (counters_need_update) {
- fast_timer_t now = timer_read_fast();
+ fast_timer_t now = timer_read_fast();
fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
- last_time = now;
+ last_time = now;
updated_last = true;
if (elapsed_time > UINT8_MAX) {
elapsed_time = UINT8_MAX;
diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c
index 15a3242e68..9da000ea9a 100644
--- a/quantum/debounce/sym_eager_pk.c
+++ b/quantum/debounce/sym_eager_pk.c
@@ -50,7 +50,7 @@ static fast_timer_t last_time;
static bool counters_need_update;
static bool matrix_need_update;
-#define DEBOUNCE_ELAPSED 0
+# define DEBOUNCE_ELAPSED 0
static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
@@ -75,10 +75,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
bool updated_last = false;
if (counters_need_update) {
- fast_timer_t now = timer_read_fast();
+ fast_timer_t now = timer_read_fast();
fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
- last_time = now;
+ last_time = now;
updated_last = true;
if (elapsed_time > UINT8_MAX) {
elapsed_time = UINT8_MAX;
@@ -107,7 +107,7 @@ static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
if (*debounce_pointer != DEBOUNCE_ELAPSED) {
if (*debounce_pointer <= elapsed_time) {
- *debounce_pointer = DEBOUNCE_ELAPSED;
+ *debounce_pointer = DEBOUNCE_ELAPSED;
matrix_need_update = true;
} else {
*debounce_pointer -= elapsed_time;
diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c
index 2ad592c5a6..eda92a263b 100644
--- a/quantum/debounce/sym_eager_pr.c
+++ b/quantum/debounce/sym_eager_pr.c
@@ -49,7 +49,7 @@ static debounce_counter_t *debounce_counters;
static fast_timer_t last_time;
static bool counters_need_update;
-#define DEBOUNCE_ELAPSED 0
+# define DEBOUNCE_ELAPSED 0
static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
@@ -71,10 +71,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
bool updated_last = false;
if (counters_need_update) {
- fast_timer_t now = timer_read_fast();
+ fast_timer_t now = timer_read_fast();
fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
- last_time = now;
+ last_time = now;
updated_last = true;
if (elapsed_time > UINT8_MAX) {
elapsed_time = UINT8_MAX;
@@ -102,7 +102,7 @@ static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
for (uint8_t row = 0; row < num_rows; row++) {
if (*debounce_pointer != DEBOUNCE_ELAPSED) {
if (*debounce_pointer <= elapsed_time) {
- *debounce_pointer = DEBOUNCE_ELAPSED;
+ *debounce_pointer = DEBOUNCE_ELAPSED;
matrix_need_update = true;
} else {
*debounce_pointer -= elapsed_time;
diff --git a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
index fe374c3dfa..44b4fe1956 100644
--- a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
+++ b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 1ms delay */
{1, {{0, 1, UP}}, {}},
@@ -43,7 +44,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 2ms delay */
{2, {{0, 1, UP}}, {}},
@@ -58,7 +60,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 3ms delay */
{3, {{0, 1, UP}}, {}},
@@ -73,7 +76,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyShort4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 4ms delay */
{4, {{0, 1, UP}}, {}},
@@ -88,7 +92,8 @@ TEST_F(DebounceTest, OneKeyShort4) {
}
TEST_F(DebounceTest, OneKeyShort5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 5ms delay */
@@ -102,7 +107,8 @@ TEST_F(DebounceTest, OneKeyShort5) {
}
TEST_F(DebounceTest, OneKeyShort6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 6ms delay */
@@ -116,7 +122,8 @@ TEST_F(DebounceTest, OneKeyShort6) {
}
TEST_F(DebounceTest, OneKeyShort7) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 7ms delay */
@@ -130,7 +137,8 @@ TEST_F(DebounceTest, OneKeyShort7) {
}
TEST_F(DebounceTest, OneKeyShort8) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 1ms delay */
{1, {{0, 1, UP}}, {}},
@@ -145,7 +153,8 @@ TEST_F(DebounceTest, OneKeyShort8) {
}
TEST_F(DebounceTest, OneKeyShort9) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 1ms delay */
{1, {{0, 1, UP}}, {}},
@@ -159,7 +168,8 @@ TEST_F(DebounceTest, OneKeyShort9) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -185,7 +195,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Change twice in the same time period */
{1, {{0, 1, UP}}, {}},
@@ -217,7 +228,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{25, {{0, 1, UP}}, {}},
@@ -236,7 +248,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoKeysShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
/* Release key after 2ms delay */
@@ -249,14 +262,14 @@ TEST_F(DebounceTest, TwoKeysShort) {
{10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
/* Press key again after 1ms delay */
{11, {{0, 1, DOWN}}, {{0, 1, DOWN}, {0, 2, UP}}}, /* 5ms+5ms after DOWN at time 0 */
- {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */
+ {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */
});
runEvents();
}
-
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late, immediately release key */
@@ -269,7 +282,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late, immediately release key */
@@ -283,7 +297,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late */
@@ -298,7 +313,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late */
@@ -314,7 +330,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
}
TEST_F(DebounceTest, OneKeyDelayedScan5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{5, {{0, 1, UP}}, {}},
@@ -329,7 +346,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan5) {
}
TEST_F(DebounceTest, OneKeyDelayedScan6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{5, {{0, 1, UP}}, {}},
@@ -345,7 +363,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan6) {
}
TEST_F(DebounceTest, OneKeyDelayedScan7) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{5, {{0, 1, UP}}, {}},
@@ -358,7 +377,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan7) {
}
TEST_F(DebounceTest, OneKeyDelayedScan8) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is a bit late */
diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp
index 1c5e7c9f4e..f9414e571d 100644
--- a/quantum/debounce/tests/debounce_test_common.cpp
+++ b/quantum/debounce/tests/debounce_test_common.cpp
@@ -31,9 +31,7 @@ void set_time(uint32_t t);
void advance_time(uint32_t ms);
}
-void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) {
- events_.insert(events_.end(), events.begin(), events.end());
-}
+void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) { events_.insert(events_.end(), events.begin(), events.end()); }
void DebounceTest::runEvents() {
/* Run the test multiple times, from 1kHz to 10kHz scan rate */
@@ -54,7 +52,7 @@ void DebounceTest::runEvents() {
void DebounceTest::runEventsInternal() {
fast_timer_t previous = 0;
- bool first = true;
+ bool first = true;
/* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */
debounce_init(MATRIX_ROWS);
@@ -80,7 +78,7 @@ void DebounceTest::runEventsInternal() {
}
}
- first = false;
+ first = false;
previous = event.time_;
/* Prepare input matrix */
@@ -98,12 +96,7 @@ void DebounceTest::runEventsInternal() {
/* Check output matrix has expected change events */
for (auto &output : event.outputs_) {
- EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_))
- << "Missing event at " << strTime()
- << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_)
- << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_)
- << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
- << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
+ EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_)) << "Missing event at " << strTime() << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_) << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_) << "\nexpected_matrix:\n" << strMatrix(output_matrix_) << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
}
/* Check output matrix has no other changes */
@@ -133,27 +126,20 @@ void DebounceTest::runDebounce(bool changed) {
debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed);
if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) {
- FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime()
- << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
- << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
+ FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime() << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
}
}
void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) {
if (!std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_))) {
- FAIL() << "Unexpected event: " << error_message << " at " << strTime()
- << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
- << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
- << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
+ FAIL() << "Unexpected event: " << error_message << " at " << strTime() << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) << "\nexpected_matrix:\n" << strMatrix(output_matrix_) << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
}
}
std::string DebounceTest::strTime() {
std::stringstream text;
- text << "time " << (timer_read_fast() - time_offset_)
- << " (extra_iterations=" << extra_iterations_
- << ", auto_advance_time=" << auto_advance_time_ << ")";
+ text << "time " << (timer_read_fast() - time_offset_) << " (extra_iterations=" << extra_iterations_ << ", auto_advance_time=" << auto_advance_time_ << ")";
return text.str();
}
@@ -181,49 +167,39 @@ std::string DebounceTest::strMatrix(matrix_row_t matrix[]) {
bool DebounceTest::directionValue(Direction direction) {
switch (direction) {
- case DOWN:
- return true;
+ case DOWN:
+ return true;
- case UP:
- return false;
+ case UP:
+ return false;
}
}
std::string DebounceTest::directionLabel(Direction direction) {
switch (direction) {
- case DOWN:
- return "DOWN";
+ case DOWN:
+ return "DOWN";
- case UP:
- return "UP";
+ case UP:
+ return "UP";
}
}
/* Modify a matrix and verify that events always specify a change */
void DebounceTest::matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event) {
- ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_))
- << "Test " << name << " at " << strTime()
- << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_)
- << " but it is already " << directionLabel(event.direction_)
- << "\n" << name << "_matrix:\n" << strMatrix(matrix);
+ ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_)) << "Test " << name << " at " << strTime() << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_) << " but it is already " << directionLabel(event.direction_) << "\n" << name << "_matrix:\n" << strMatrix(matrix);
switch (event.direction_) {
- case DOWN:
- matrix[event.row_] |= (1U << event.col_);
- break;
+ case DOWN:
+ matrix[event.row_] |= (1U << event.col_);
+ break;
- case UP:
- matrix[event.row_] &= ~(1U << event.col_);
- break;
+ case UP:
+ matrix[event.row_] &= ~(1U << event.col_);
+ break;
}
}
-DebounceTestEvent::DebounceTestEvent(fast_timer_t time,
- std::initializer_list<MatrixTestEvent> inputs,
- std::initializer_list<MatrixTestEvent> outputs)
- : time_(time), inputs_(inputs), outputs_(outputs) {
-}
+DebounceTestEvent::DebounceTestEvent(fast_timer_t time, std::initializer_list<MatrixTestEvent> inputs, std::initializer_list<MatrixTestEvent> outputs) : time_(time), inputs_(inputs), outputs_(outputs) {}
-MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction)
- : row_(row), col_(col), direction_(direction) {
-}
+MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction) : row_(row), col_(col), direction_(direction) {}
diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h
index d87e310594..b7becb3782 100644
--- a/quantum/debounce/tests/debounce_test_common.h
+++ b/quantum/debounce/tests/debounce_test_common.h
@@ -31,36 +31,34 @@ enum Direction {
};
class MatrixTestEvent {
-public:
+ public:
MatrixTestEvent(int row, int col, Direction direction);
- const int row_;
- const int col_;
+ const int row_;
+ const int col_;
const Direction direction_;
};
class DebounceTestEvent {
-public:
+ public:
// 0, {{0, 1, DOWN}}, {{0, 1, DOWN}})
- DebounceTestEvent(fast_timer_t time,
- std::initializer_list<MatrixTestEvent> inputs,
- std::initializer_list<MatrixTestEvent> outputs);
+ DebounceTestEvent(fast_timer_t time, std::initializer_list<MatrixTestEvent> inputs, std::initializer_list<MatrixTestEvent> outputs);
- const fast_timer_t time_;
+ const fast_timer_t time_;
const std::list<MatrixTestEvent> inputs_;
const std::list<MatrixTestEvent> outputs_;
};
class DebounceTest : public ::testing::Test {
-protected:
+ protected:
void addEvents(std::initializer_list<DebounceTestEvent> events);
void runEvents();
fast_timer_t time_offset_ = 7777;
- bool time_jumps_ = false;
+ bool time_jumps_ = false;
-private:
- static bool directionValue(Direction direction);
+ private:
+ static bool directionValue(Direction direction);
static std::string directionLabel(Direction direction);
void runEventsInternal();
@@ -78,6 +76,6 @@ private:
matrix_row_t cooked_matrix_[MATRIX_ROWS];
matrix_row_t output_matrix_[MATRIX_ROWS];
- int extra_iterations_;
+ int extra_iterations_;
bool auto_advance_time_;
};
diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk
index 66928d7eb6..e908dd6f67 100644
--- a/quantum/debounce/tests/rules.mk
+++ b/quantum/debounce/tests/rules.mk
@@ -16,7 +16,7 @@
DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5
DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \
- $(TMK_PATH)/common/test/timer.c
+ $(PLATFORM_PATH)/$(PLATFORM_KEY)/timer.c
debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS)
debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \
diff --git a/quantum/debounce/tests/sym_defer_g_tests.cpp b/quantum/debounce/tests/sym_defer_g_tests.cpp
index a56aecd8f3..73d3d45e30 100644
--- a/quantum/debounce/tests/sym_defer_g_tests.cpp
+++ b/quantum/debounce/tests/sym_defer_g_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyTooQuick1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Release key exactly on the debounce time */
{5, {{0, 1, UP}}, {}},
@@ -67,7 +71,8 @@ TEST_F(DebounceTest, OneKeyTooQuick1) {
}
TEST_F(DebounceTest, OneKeyTooQuick2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -80,7 +85,8 @@ TEST_F(DebounceTest, OneKeyTooQuick2) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -94,7 +100,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
{6, {{0, 1, UP}}, {}},
@@ -108,7 +115,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -125,7 +133,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoKeysShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 2, DOWN}}, {}},
@@ -140,7 +149,8 @@ TEST_F(DebounceTest, TwoKeysShort) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
@@ -152,7 +162,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous1) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 2, DOWN}}, {}},
@@ -167,7 +178,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is very late */
@@ -182,7 +194,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is very late */
@@ -197,7 +210,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Release key before debounce expires */
@@ -208,7 +222,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is a bit late */
diff --git a/quantum/debounce/tests/sym_defer_pk_tests.cpp b/quantum/debounce/tests/sym_defer_pk_tests.cpp
index 1f3061e59c..7542c2dad4 100644
--- a/quantum/debounce/tests/sym_defer_pk_tests.cpp
+++ b/quantum/debounce/tests/sym_defer_pk_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyTooQuick1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Release key exactly on the debounce time */
{5, {{0, 1, UP}}, {}},
@@ -67,7 +71,8 @@ TEST_F(DebounceTest, OneKeyTooQuick1) {
}
TEST_F(DebounceTest, OneKeyTooQuick2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -80,7 +85,8 @@ TEST_F(DebounceTest, OneKeyTooQuick2) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -94,7 +100,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
{6, {{0, 1, UP}}, {}},
@@ -108,7 +115,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -125,7 +133,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoKeysShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 2, DOWN}}, {}},
@@ -142,7 +151,8 @@ TEST_F(DebounceTest, TwoKeysShort) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
@@ -154,7 +164,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous1) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 2, DOWN}}, {}},
@@ -169,7 +180,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is very late */
@@ -184,7 +196,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is very late */
@@ -199,7 +212,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Release key before debounce expires */
@@ -210,7 +224,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is a bit late */
diff --git a/quantum/debounce/tests/sym_eager_pk_tests.cpp b/quantum/debounce/tests/sym_eager_pk_tests.cpp
index e0fc205e33..d9a02fe33c 100644
--- a/quantum/debounce/tests/sym_eager_pk_tests.cpp
+++ b/quantum/debounce/tests/sym_eager_pk_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyShort4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -71,7 +75,8 @@ TEST_F(DebounceTest, OneKeyShort4) {
}
TEST_F(DebounceTest, OneKeyShort5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -83,7 +88,8 @@ TEST_F(DebounceTest, OneKeyShort5) {
}
TEST_F(DebounceTest, OneKeyShort6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -95,7 +101,8 @@ TEST_F(DebounceTest, OneKeyShort6) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -110,7 +117,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Change twice in the same time period */
{1, {{0, 1, UP}}, {}},
@@ -135,7 +143,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{25, {{0, 1, UP}}, {{0, 1, UP}}},
@@ -146,7 +155,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoKeysShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
@@ -167,7 +177,8 @@ TEST_F(DebounceTest, TwoKeysShort) {
}
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted */
@@ -178,7 +189,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1 scan delay */
@@ -190,7 +202,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1ms delay */
@@ -202,7 +215,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is a bit late but the change will now be accepted */
@@ -213,7 +227,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
}
TEST_F(DebounceTest, OneKeyDelayedScan5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1 scan delay */
@@ -225,7 +240,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan5) {
}
TEST_F(DebounceTest, OneKeyDelayedScan6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1ms delay */
diff --git a/quantum/debounce/tests/sym_eager_pr_tests.cpp b/quantum/debounce/tests/sym_eager_pr_tests.cpp
index 2c4bca127e..e91dd9cb87 100644
--- a/quantum/debounce/tests/sym_eager_pr_tests.cpp
+++ b/quantum/debounce/tests/sym_eager_pr_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyShort4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -71,7 +75,8 @@ TEST_F(DebounceTest, OneKeyShort4) {
}
TEST_F(DebounceTest, OneKeyShort5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -83,7 +88,8 @@ TEST_F(DebounceTest, OneKeyShort5) {
}
TEST_F(DebounceTest, OneKeyShort6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -95,7 +101,8 @@ TEST_F(DebounceTest, OneKeyShort6) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -110,7 +117,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Change twice in the same time period */
{1, {{0, 1, UP}}, {}},
@@ -135,7 +143,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{25, {{0, 1, UP}}, {{0, 1, UP}}},
@@ -146,7 +155,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoRowsShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{2, 0, DOWN}}, {{2, 0, DOWN}}},
@@ -167,7 +177,8 @@ TEST_F(DebounceTest, TwoRowsShort) {
}
TEST_F(DebounceTest, TwoKeysOverlap) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
/* Press a second key during the first debounce */
@@ -190,7 +201,8 @@ TEST_F(DebounceTest, TwoKeysOverlap) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
{20, {{0, 1, UP}}, {{0, 1, UP}}},
{21, {{0, 2, UP}}, {}},
@@ -202,7 +214,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous1) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
{20, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}},
});
@@ -210,7 +223,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted */
@@ -221,7 +235,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1 scan delay */
@@ -233,7 +248,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1ms delay */
@@ -245,7 +261,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is a bit late but the change will now be accepted */
@@ -256,7 +273,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
}
TEST_F(DebounceTest, OneKeyDelayedScan5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1 scan delay */
@@ -268,7 +286,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan5) {
}
TEST_F(DebounceTest, OneKeyDelayedScan6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1ms delay */
diff --git a/quantum/deferred_exec.c b/quantum/deferred_exec.c
new file mode 100644
index 0000000000..5b0a5b1425
--- /dev/null
+++ b/quantum/deferred_exec.c
@@ -0,0 +1,152 @@
+// Copyright 2021 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <stddef.h>
+#include <timer.h>
+#include <deferred_exec.h>
+
+#ifndef MAX_DEFERRED_EXECUTORS
+# define MAX_DEFERRED_EXECUTORS 8
+#endif
+
+typedef struct deferred_executor_t {
+ deferred_token token;
+ uint32_t trigger_time;
+ deferred_exec_callback callback;
+ void * cb_arg;
+} deferred_executor_t;
+
+static deferred_token current_token = 0;
+static uint32_t last_deferred_exec_check = 0;
+static deferred_executor_t executors[MAX_DEFERRED_EXECUTORS] = {0};
+
+static inline bool token_can_be_used(deferred_token token) {
+ if (token == INVALID_DEFERRED_TOKEN) {
+ return false;
+ }
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ if (executors[i].token == token) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static inline deferred_token allocate_token(void) {
+ deferred_token first = ++current_token;
+ while (!token_can_be_used(current_token)) {
+ ++current_token;
+ if (current_token == first) {
+ // If we've looped back around to the first, everything is already allocated (yikes!). Need to exit with a failure.
+ return INVALID_DEFERRED_TOKEN;
+ }
+ }
+ return current_token;
+}
+
+deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) {
+ // Ignore queueing if it's a zero-time delay, or invalid callback
+ if (delay_ms == 0 || !callback) {
+ return INVALID_DEFERRED_TOKEN;
+ }
+
+ // Find an unused slot and claim it
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ deferred_executor_t *entry = &executors[i];
+ if (entry->token == INVALID_DEFERRED_TOKEN) {
+ // Work out the new token value, dropping out if none were available
+ deferred_token token = allocate_token();
+ if (token == INVALID_DEFERRED_TOKEN) {
+ return false;
+ }
+
+ // Set up the executor table entry
+ entry->token = current_token;
+ entry->trigger_time = timer_read32() + delay_ms;
+ entry->callback = callback;
+ entry->cb_arg = cb_arg;
+ return current_token;
+ }
+ }
+
+ // None available
+ return INVALID_DEFERRED_TOKEN;
+}
+
+bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) {
+ // Ignore queueing if it's a zero-time delay, or the token is not valid
+ if (delay_ms == 0 || token == INVALID_DEFERRED_TOKEN) {
+ return false;
+ }
+
+ // Find the entry corresponding to the token
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ deferred_executor_t *entry = &executors[i];
+ if (entry->token == token) {
+ // Found it, extend the delay
+ entry->trigger_time = timer_read32() + delay_ms;
+ return true;
+ }
+ }
+
+ // Not found
+ return false;
+}
+
+bool cancel_deferred_exec(deferred_token token) {
+ // Ignore request if the token is not valid
+ if (token == INVALID_DEFERRED_TOKEN) {
+ return false;
+ }
+
+ // Find the entry corresponding to the token
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ deferred_executor_t *entry = &executors[i];
+ if (entry->token == token) {
+ // Found it, cancel and clear the table entry
+ entry->token = INVALID_DEFERRED_TOKEN;
+ entry->trigger_time = 0;
+ entry->callback = NULL;
+ entry->cb_arg = NULL;
+ return true;
+ }
+ }
+
+ // Not found
+ return false;
+}
+
+void deferred_exec_task(void) {
+ uint32_t now = timer_read32();
+
+ // Throttle only once per millisecond
+ if (((int32_t)TIMER_DIFF_32(now, last_deferred_exec_check)) > 0) {
+ last_deferred_exec_check = now;
+
+ // Run through each of the executors
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ deferred_executor_t *entry = &executors[i];
+
+ // Check if we're supposed to execute this entry
+ if (entry->token != INVALID_DEFERRED_TOKEN && ((int32_t)TIMER_DIFF_32(entry->trigger_time, now)) <= 0) {
+ // Invoke the callback and work work out if we should be requeued
+ uint32_t delay_ms = entry->callback(entry->trigger_time, entry->cb_arg);
+
+ // Update the trigger time if we have to repeat, otherwise clear it out
+ if (delay_ms > 0) {
+ // Intentionally add just the delay to the existing trigger time -- this ensures the next
+ // invocation is with respect to the previous trigger, rather than when it got to execution. Under
+ // normal circumstances this won't cause issue, but if another executor is invoked that takes a
+ // considerable length of time, then this ensures best-effort timing between invocations.
+ entry->trigger_time += delay_ms;
+ } else {
+ // If it was zero, then the callback is cancelling repeated execution. Free up the slot.
+ entry->token = INVALID_DEFERRED_TOKEN;
+ entry->trigger_time = 0;
+ entry->callback = NULL;
+ entry->cb_arg = NULL;
+ }
+ }
+ }
+ }
+}
diff --git a/quantum/deferred_exec.h b/quantum/deferred_exec.h
new file mode 100644
index 0000000000..f80d353169
--- /dev/null
+++ b/quantum/deferred_exec.h
@@ -0,0 +1,38 @@
+// Copyright 2021 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+// A token that can be used to cancel an existing deferred execution.
+typedef uint8_t deferred_token;
+#define INVALID_DEFERRED_TOKEN 0
+
+// Callback to execute.
+// -- Parameter trigger_time: the intended trigger time to execute the callback -- equivalent time-space as timer_read32()
+// cb_arg: the callback argument specified when enqueueing the deferred executor
+// -- Return value: Non-zero re-queues the callback to execute after the returned number of milliseconds. Zero cancels repeated execution.
+typedef uint32_t (*deferred_exec_callback)(uint32_t trigger_time, void *cb_arg);
+
+// Configures the supplied deferred executor to be executed after the required number of milliseconds.
+// -- Parameter delay_ms: the number of milliseconds before executing the callback
+// -- callback: the executor to invoke
+// -- cb_arg: the argument to pass to the executor, may be NULL if unused by the executor
+// -- Return value: a token usable for cancellation, or INVALID_DEFERRED_TOKEN if an error occurred
+deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg);
+
+// Allows for extending the timeframe before an existing deferred execution is invoked.
+// -- Parameter token: the returned value from defer_exec for the deferred execution you wish to extend.
+// -- delay_ms: the new delay (with respect to the current time)
+// -- Return value: if the token was found, and the delay was extended
+bool extend_deferred_exec(deferred_token token, uint32_t delay_ms);
+
+// Allows for cancellation of an existing deferred execution.
+// -- Parameter token: the returned value from defer_exec for the deferred execution you wish to cancel.
+// -- Return value: if the token was found, and the executor was cancelled
+bool cancel_deferred_exec(deferred_token token);
+
+// Forward declaration for the main loop in order to execute any deferred executors. Should not be invoked by keyboard/user code.
+void deferred_exec_task(void);
diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c
index f76f37f997..8c2d2f5dce 100644
--- a/quantum/dynamic_keymap.c
+++ b/quantum/dynamic_keymap.c
@@ -14,8 +14,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-#include "tmk_core/common/eeprom.h"
+#include "config.h"
+#include "keymap.h" // to get keymaps[][][]
+#include "eeprom.h"
+#include "progmem.h" // to read default from flash
#include "quantum.h" // for send_string()
#include "eeconfig.h"
diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c
index e571309a05..7c1a1f3cb2 100644
--- a/quantum/eeconfig.c
+++ b/quantum/eeconfig.c
@@ -7,11 +7,6 @@
# include "oryx.h"
#endif
-#ifdef STM32_EEPROM_ENABLE
-# include <hal.h>
-# include "eeprom_stm32.h"
-#endif
-
#if defined(EEPROM_DRIVER)
# include "eeprom_driver.h"
#endif
@@ -46,9 +41,6 @@ __attribute__((weak)) void eeconfig_init_kb(void) {
* FIXME: needs doc
*/
void eeconfig_init_quantum(void) {
-#ifdef STM32_EEPROM_ENABLE
- EEPROM_Erase();
-#endif
#if defined(EEPROM_DRIVER)
eeprom_driver_erase();
#endif
@@ -118,9 +110,6 @@ void eeconfig_enable(void) { eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_N
* FIXME: needs doc
*/
void eeconfig_disable(void) {
-#ifdef STM32_EEPROM_ENABLE
- EEPROM_Erase();
-#endif
#if defined(EEPROM_DRIVER)
eeprom_driver_erase();
#endif
diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h
index bd39971b2c..22d874273c 100644
--- a/quantum/eeconfig.h
+++ b/quantum/eeconfig.h
@@ -111,3 +111,29 @@ void eeconfig_update_haptic(uint32_t val);
bool eeconfig_read_handedness(void);
void eeconfig_update_handedness(bool val);
+
+#define EECONFIG_DEBOUNCE_HELPER(name, offset, config) \
+ static uint8_t dirty_##name = false; \
+ \
+ static inline void eeconfig_init_##name(void) { \
+ eeprom_read_block(&config, offset, sizeof(config)); \
+ dirty_##name = false; \
+ } \
+ static inline void eeconfig_flush_##name(bool force) { \
+ if (force || dirty_##name) { \
+ eeprom_update_block(&config, offset, sizeof(config)); \
+ dirty_##name = false; \
+ } \
+ } \
+ static inline void eeconfig_flush_##name##_task(uint16_t timeout) { \
+ static uint16_t flush_timer = 0; \
+ if (timer_elapsed(flush_timer) > timeout) { \
+ eeconfig_flush_##name(false); \
+ flush_timer = timer_read(); \
+ } \
+ } \
+ static inline void eeconfig_flag_##name(bool v) { dirty_##name |= v; } \
+ static inline void eeconfig_write_##name(typeof(config) conf) { \
+ memcpy(&config, &conf, sizeof(config)); \
+ eeconfig_flag_##name(true); \
+ }
diff --git a/quantum/encoder/tests/encoder_tests.cpp b/quantum/encoder/tests/encoder_tests.cpp
new file mode 100644
index 0000000000..1888fdab8d
--- /dev/null
+++ b/quantum/encoder/tests/encoder_tests.cpp
@@ -0,0 +1,144 @@
+/* Copyright 2021 Balz Guenat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include <vector>
+#include <algorithm>
+#include <stdio.h>
+
+extern "C" {
+#include "encoder.h"
+#include "encoder/tests/mock.h"
+}
+
+struct update {
+ int8_t index;
+ bool clockwise;
+};
+
+uint8_t uidx = 0;
+update updates[32];
+
+bool encoder_update_kb(uint8_t index, bool clockwise) {
+ updates[uidx % 32] = {index, clockwise};
+ uidx++;
+ return true;
+}
+
+bool setAndRead(pin_t pin, bool val) {
+ setPin(pin, val);
+ return encoder_read();
+}
+
+class EncoderTest : public ::testing::Test {};
+
+TEST_F(EncoderTest, TestInit) {
+ uidx = 0;
+ encoder_init();
+ EXPECT_EQ(pinIsInputHigh[0], true);
+ EXPECT_EQ(pinIsInputHigh[1], true);
+ EXPECT_EQ(uidx, 0);
+}
+
+TEST_F(EncoderTest, TestOneClockwise) {
+ uidx = 0;
+ encoder_init();
+ // send 4 pulses. with resolution 4, that's one step and we should get 1 update.
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+}
+
+TEST_F(EncoderTest, TestOneCounterClockwise) {
+ uidx = 0;
+ encoder_init();
+ setAndRead(1, false);
+ setAndRead(0, false);
+ setAndRead(1, true);
+ setAndRead(0, true);
+
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, false);
+}
+
+TEST_F(EncoderTest, TestTwoClockwiseOneCC) {
+ uidx = 0;
+ encoder_init();
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+ setAndRead(1, false);
+ setAndRead(0, false);
+ setAndRead(1, true);
+ setAndRead(0, true);
+
+ EXPECT_EQ(uidx, 3);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+ EXPECT_EQ(updates[1].index, 0);
+ EXPECT_EQ(updates[1].clockwise, true);
+ EXPECT_EQ(updates[2].index, 0);
+ EXPECT_EQ(updates[2].clockwise, false);
+}
+
+TEST_F(EncoderTest, TestNoEarly) {
+ uidx = 0;
+ encoder_init();
+ // send 3 pulses. with resolution 4, that's not enough for a step.
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ EXPECT_EQ(uidx, 0);
+ // now send last pulse
+ setAndRead(1, true);
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+}
+
+TEST_F(EncoderTest, TestHalfway) {
+ uidx = 0;
+ encoder_init();
+ // go halfway
+ setAndRead(0, false);
+ setAndRead(1, false);
+ EXPECT_EQ(uidx, 0);
+ // back off
+ setAndRead(1, true);
+ setAndRead(0, true);
+ EXPECT_EQ(uidx, 0);
+ // go all the way
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+ // should result in 1 update
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+}
diff --git a/quantum/encoder/tests/encoder_tests_split.cpp b/quantum/encoder/tests/encoder_tests_split.cpp
new file mode 100644
index 0000000000..25e52c83f9
--- /dev/null
+++ b/quantum/encoder/tests/encoder_tests_split.cpp
@@ -0,0 +1,143 @@
+/* Copyright 2021 Balz Guenat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include <vector>
+#include <algorithm>
+#include <stdio.h>
+
+extern "C" {
+#include "encoder.h"
+#include "encoder/tests/mock_split.h"
+}
+
+struct update {
+ int8_t index;
+ bool clockwise;
+};
+
+uint8_t uidx = 0;
+update updates[32];
+
+bool isLeftHand;
+
+bool encoder_update_kb(uint8_t index, bool clockwise) {
+ if (!isLeftHand) {
+ // this method has no effect on slave half
+ printf("ignoring update on right hand (%d,%s)\n", index, clockwise ? "CW" : "CC");
+ return true;
+ }
+ updates[uidx % 32] = {index, clockwise};
+ uidx++;
+ return true;
+}
+
+bool setAndRead(pin_t pin, bool val) {
+ setPin(pin, val);
+ return encoder_read();
+}
+
+class EncoderTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ uidx = 0;
+ for (int i = 0; i < 32; i++) {
+ pinIsInputHigh[i] = 0;
+ pins[i] = 0;
+ }
+ }
+};
+
+TEST_F(EncoderTest, TestInitLeft) {
+ isLeftHand = true;
+ encoder_init();
+ EXPECT_EQ(pinIsInputHigh[0], true);
+ EXPECT_EQ(pinIsInputHigh[1], true);
+ EXPECT_EQ(pinIsInputHigh[2], false);
+ EXPECT_EQ(pinIsInputHigh[3], false);
+ EXPECT_EQ(uidx, 0);
+}
+
+TEST_F(EncoderTest, TestInitRight) {
+ isLeftHand = false;
+ encoder_init();
+ EXPECT_EQ(pinIsInputHigh[0], false);
+ EXPECT_EQ(pinIsInputHigh[1], false);
+ EXPECT_EQ(pinIsInputHigh[2], true);
+ EXPECT_EQ(pinIsInputHigh[3], true);
+ EXPECT_EQ(uidx, 0);
+}
+
+TEST_F(EncoderTest, TestOneClockwiseLeft) {
+ isLeftHand = true;
+ encoder_init();
+ // send 4 pulses. with resolution 4, that's one step and we should get 1 update.
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+}
+
+TEST_F(EncoderTest, TestOneClockwiseRightSent) {
+ isLeftHand = false;
+ encoder_init();
+ // send 4 pulses. with resolution 4, that's one step and we should get 1 update.
+ setAndRead(2, false);
+ setAndRead(3, false);
+ setAndRead(2, true);
+ setAndRead(3, true);
+
+ uint8_t slave_state[2] = {0};
+ encoder_state_raw(slave_state);
+
+ EXPECT_EQ((int8_t)slave_state[0], -1);
+}
+
+/* this test will not work after the previous test.
+ * this is due to encoder_value[1] already being set to -1 when simulating the right half.
+ * When we now receive this update acting as the left half, there is no change.
+ * This is hard to mock, as the static values inside encoder.c normally exist twice, once on each half,
+ * but here, they only exist once.
+ */
+
+// TEST_F(EncoderTest, TestOneClockwiseRightReceived) {
+// isLeftHand = true;
+// encoder_init();
+
+// uint8_t slave_state[2] = {255, 0};
+// encoder_update_raw(slave_state);
+
+// EXPECT_EQ(uidx, 1);
+// EXPECT_EQ(updates[0].index, 1);
+// EXPECT_EQ(updates[0].clockwise, true);
+// }
+
+TEST_F(EncoderTest, TestOneCounterClockwiseRightReceived) {
+ isLeftHand = true;
+ encoder_init();
+
+ uint8_t slave_state[2] = {0, 0};
+ encoder_update_raw(slave_state);
+
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 1);
+ EXPECT_EQ(updates[0].clockwise, false);
+}
diff --git a/quantum/encoder/tests/mock.c b/quantum/encoder/tests/mock.c
new file mode 100644
index 0000000000..d0506a938f
--- /dev/null
+++ b/quantum/encoder/tests/mock.c
@@ -0,0 +1,34 @@
+/* Copyright 2021 Balz Guenat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mock.h"
+
+bool pins[32] = {0};
+bool pinIsInputHigh[32] = {0};
+
+uint8_t mockSetPinInputHigh(pin_t pin) {
+ // dprintf("Setting pin %d input high.", pin);
+ pins[pin] = true;
+ pinIsInputHigh[pin] = true;
+ return 0;
+}
+
+bool mockReadPin(pin_t pin) { return pins[pin]; }
+
+bool setPin(pin_t pin, bool val) {
+ pins[pin] = val;
+ return val;
+}
diff --git a/quantum/visualizer/default_animations.h b/quantum/encoder/tests/mock.h
index 9accd89774..dbc25a0846 100644
--- a/quantum/visualizer/default_animations.h
+++ b/quantum/encoder/tests/mock.h
@@ -1,4 +1,4 @@
-/* Copyright 2017 Fred Sundvik
+/* Copyright 2021 Balz Guenat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,12 +16,25 @@
#pragma once
-#include "visualizer.h"
+#include <stdint.h>
+#include <stdbool.h>
-// You can use these default animations, but of course you can also write your own custom ones instead
-extern keyframe_animation_t default_startup_animation;
-extern keyframe_animation_t default_suspend_animation;
+/* Here, "pins" from 0 to 31 are allowed. */
+#define ENCODERS_PAD_A \
+ { 0 }
+#define ENCODERS_PAD_B \
+ { 1 }
-// An animation for testing and demonstrating the led support, should probably not be used for real world
-// cases
-extern keyframe_animation_t led_test_animation;
+typedef uint8_t pin_t;
+
+extern bool pins[];
+extern bool pinIsInputHigh[];
+
+#define setPinInputHigh(pin) (mockSetPinInputHigh(pin))
+#define readPin(pin) (mockReadPin(pin))
+
+uint8_t mockSetPinInputHigh(pin_t pin);
+
+bool mockReadPin(pin_t pin);
+
+bool setPin(pin_t pin, bool val);
diff --git a/quantum/encoder/tests/mock_split.c b/quantum/encoder/tests/mock_split.c
new file mode 100644
index 0000000000..68bf3af599
--- /dev/null
+++ b/quantum/encoder/tests/mock_split.c
@@ -0,0 +1,36 @@
+/* Copyright 2021 Balz Guenat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mock_split.h"
+
+bool pins[32] = {0};
+bool pinIsInputHigh[32] = {0};
+
+uint8_t mockSetPinInputHigh(pin_t pin) {
+ // dprintf("Setting pin %d input high.", pin);
+ pins[pin] = true;
+ pinIsInputHigh[pin] = true;
+ return 0;
+}
+
+bool mockReadPin(pin_t pin) { return pins[pin]; }
+
+bool setPin(pin_t pin, bool val) {
+ pins[pin] = val;
+ return val;
+}
+
+void last_encoder_activity_trigger(void) {}
diff --git a/quantum/encoder/tests/mock_split.h b/quantum/encoder/tests/mock_split.h
new file mode 100644
index 0000000000..0ae62652f9
--- /dev/null
+++ b/quantum/encoder/tests/mock_split.h
@@ -0,0 +1,48 @@
+/* Copyright 2021 Balz Guenat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define SPLIT_KEYBOARD
+/* Here, "pins" from 0 to 31 are allowed. */
+#define ENCODERS_PAD_A \
+ { 0 }
+#define ENCODERS_PAD_B \
+ { 1 }
+#define ENCODERS_PAD_A_RIGHT \
+ { 2 }
+#define ENCODERS_PAD_B_RIGHT \
+ { 3 }
+
+typedef uint8_t pin_t;
+extern bool isLeftHand;
+void encoder_state_raw(uint8_t* slave_state);
+void encoder_update_raw(uint8_t* slave_state);
+
+extern bool pins[];
+extern bool pinIsInputHigh[];
+
+#define setPinInputHigh(pin) (mockSetPinInputHigh(pin))
+#define readPin(pin) (mockReadPin(pin))
+
+uint8_t mockSetPinInputHigh(pin_t pin);
+
+bool mockReadPin(pin_t pin);
+
+bool setPin(pin_t pin, bool val);
diff --git a/quantum/encoder/tests/rules.mk b/quantum/encoder/tests/rules.mk
new file mode 100644
index 0000000000..b826ce3aed
--- /dev/null
+++ b/quantum/encoder/tests/rules.mk
@@ -0,0 +1,13 @@
+encoder_DEFS := -DENCODER_MOCK_SINGLE
+
+encoder_SRC := \
+ $(QUANTUM_PATH)/encoder/tests/mock.c \
+ $(QUANTUM_PATH)/encoder/tests/encoder_tests.cpp \
+ $(QUANTUM_PATH)/encoder.c
+
+encoder_split_DEFS := -DENCODER_MOCK_SPLIT
+
+encoder_split_SRC := \
+ $(QUANTUM_PATH)/encoder/tests/mock_split.c \
+ $(QUANTUM_PATH)/encoder/tests/encoder_tests_split.cpp \
+ $(QUANTUM_PATH)/encoder.c
diff --git a/quantum/encoder/tests/testlist.mk b/quantum/encoder/tests/testlist.mk
new file mode 100644
index 0000000000..1be9f4a054
--- /dev/null
+++ b/quantum/encoder/tests/testlist.mk
@@ -0,0 +1,3 @@
+TEST_LIST += \
+ encoder \
+ encoder_split
diff --git a/quantum/haptic.c b/quantum/haptic.c
index 65abcc15fa..f915acf946 100644
--- a/quantum/haptic.c
+++ b/quantum/haptic.c
@@ -17,6 +17,8 @@
#include "haptic.h"
#include "eeconfig.h"
#include "debug.h"
+#include "usb_device_state.h"
+#include "gpio.h"
#ifdef DRV2605L
# include "DRV2605L.h"
#endif
@@ -26,6 +28,29 @@
haptic_config_t haptic_config;
+static void update_haptic_enable_gpios(void) {
+ if (haptic_config.enable && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) {
+#if defined(HAPTIC_ENABLE_PIN)
+ HAPTIC_ENABLE_PIN_WRITE_ACTIVE();
+#endif
+#if defined(HAPTIC_ENABLE_STATUS_LED)
+ HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE();
+#endif
+ } else {
+#if defined(HAPTIC_ENABLE_PIN)
+ HAPTIC_ENABLE_PIN_WRITE_INACTIVE();
+#endif
+#if defined(HAPTIC_ENABLE_STATUS_LED)
+ HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE();
+#endif
+ }
+}
+
+static void set_haptic_config_enable(bool enabled) {
+ haptic_config.enable = enabled;
+ update_haptic_enable_gpios();
+}
+
void haptic_init(void) {
if (!eeconfig_is_enabled()) {
eeconfig_init();
@@ -44,6 +69,10 @@ void haptic_init(void) {
// or the previous firmware didn't have solenoid enabled,
// and the current one has solenoid enabled.
haptic_reset();
+ } else {
+ // Haptic configuration has been loaded through the "raw" union item.
+ // This is to execute any side effects of the configuration.
+ set_haptic_config_enable(haptic_config.enable);
}
#ifdef SOLENOID_ENABLE
solenoid_setup();
@@ -54,6 +83,12 @@ void haptic_init(void) {
dprintf("DRV2605 driver initialized\n");
#endif
eeconfig_debug_haptic();
+#ifdef HAPTIC_ENABLE_PIN
+ setPinOutput(HAPTIC_ENABLE_PIN);
+#endif
+#ifdef HAPTIC_ENABLE_STATUS_LED
+ setPinOutput(HAPTIC_ENABLE_STATUS_LED);
+#endif
}
void haptic_task(void) {
@@ -69,13 +104,13 @@ void eeconfig_debug_haptic(void) {
}
void haptic_enable(void) {
- haptic_config.enable = 1;
+ set_haptic_config_enable(true);
xprintf("haptic_config.enable = %u\n", haptic_config.enable);
eeconfig_update_haptic(haptic_config.raw);
}
void haptic_disable(void) {
- haptic_config.enable = 0;
+ set_haptic_config_enable(false);
xprintf("haptic_config.enable = %u\n", haptic_config.enable);
eeconfig_update_haptic(haptic_config.raw);
}
@@ -157,7 +192,7 @@ void haptic_dwell_decrease(void) {
}
void haptic_reset(void) {
- haptic_config.enable = true;
+ set_haptic_config_enable(true);
uint8_t feedback = HAPTIC_FEEDBACK_DEFAULT;
haptic_config.feedback = feedback;
#ifdef DRV2605L
@@ -293,3 +328,13 @@ void haptic_shutdown(void) {
solenoid_shutdown();
#endif
}
+
+void haptic_notify_usb_device_state_change(void) {
+ update_haptic_enable_gpios();
+#if defined(HAPTIC_ENABLE_PIN)
+ setPinOutput(HAPTIC_ENABLE_PIN);
+#endif
+#if defined(HAPTIC_ENABLE_STATUS_LED)
+ setPinOutput(HAPTIC_ENABLE_STATUS_LED);
+#endif
+}
diff --git a/quantum/haptic.h b/quantum/haptic.h
index fc7ca2f3e6..7d70a01333 100644
--- a/quantum/haptic.h
+++ b/quantum/haptic.h
@@ -75,3 +75,30 @@ void haptic_cont_decrease(void);
void haptic_play(void);
void haptic_shutdown(void);
+void haptic_notify_usb_device_state_change(void);
+
+#ifdef HAPTIC_ENABLE_PIN_ACTIVE_LOW
+# ifndef HAPTIC_ENABLE_PIN
+# error HAPTIC_ENABLE_PIN not defined
+# endif
+# define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_PIN)
+# define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_PIN)
+#else
+# define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_PIN)
+# define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_PIN)
+#endif
+
+#ifdef HAPTIC_ENABLE_STATUS_LED_ACTIVE_LOW
+# ifndef HAPTIC_ENABLE_STATUS_LED
+# error HAPTIC_ENABLE_STATUS_LED not defined
+# endif
+# define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED)
+# define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED)
+#else
+# define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED)
+# define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED)
+#endif
+
+#ifndef HAPTIC_OFF_IN_LOW_POWER
+# define HAPTIC_OFF_IN_LOW_POWER 0
+#endif
diff --git a/quantum/keyboard.c b/quantum/keyboard.c
index b98fc64e45..3bca05aab7 100644
--- a/quantum/keyboard.c
+++ b/quantum/keyboard.c
@@ -40,12 +40,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef PS2_MOUSE_ENABLE
# include "ps2_mouse.h"
#endif
-#ifdef SERIAL_MOUSE_ENABLE
-# include "serial_mouse.h"
-#endif
-#ifdef ADB_MOUSE_ENABLE
-# include "adb.h"
-#endif
#ifdef RGBLIGHT_ENABLE
# include "rgblight.h"
#endif
@@ -61,12 +55,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef STENO_ENABLE
# include "process_steno.h"
#endif
-#ifdef SERIAL_LINK_ENABLE
-# include "serial_link/system/serial_link.h"
-#endif
-#ifdef VISUALIZER_ENABLE
-# include "visualizer/visualizer.h"
-#endif
#ifdef POINTING_DEVICE_ENABLE
# include "pointing_device.h"
#endif
@@ -76,12 +64,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef JOYSTICK_ENABLE
# include "process_joystick.h"
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+# include "programmable_button.h"
+#endif
#ifdef HD44780_ENABLE
# include "hd44780.h"
#endif
-#ifdef QWIIC_ENABLE
-# include "qwiic.h"
-#endif
#ifdef OLED_ENABLE
# include "oled_driver.h"
#endif
@@ -97,9 +85,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef DIP_SWITCH_ENABLE
# include "dip_switch.h"
#endif
-#ifdef STM32_EEPROM_ENABLE
-# include "eeprom_stm32.h"
-#endif
#ifdef EEPROM_DRIVER
# include "eeprom_driver.h"
#endif
@@ -109,6 +94,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef DIGITIZER_ENABLE
# include "digitizer.h"
#endif
+#ifdef VIRTSER_ENABLE
+# include "virtser.h"
+#endif
+#ifdef SLEEP_LED_ENABLE
+# include "sleep_led.h"
+#endif
static uint32_t last_input_modification_time = 0;
uint32_t last_input_activity_time(void) { return last_input_modification_time; }
@@ -246,9 +237,6 @@ void keyboard_setup(void) {
disable_jtag();
#endif
print_set_sendchar(sendchar);
-#ifdef STM32_EEPROM_ENABLE
- EEPROM_Init();
-#endif
#ifdef EEPROM_DRIVER
eeprom_driver_init();
#endif
@@ -316,9 +304,6 @@ void keyboard_init(void) {
#if defined(CRC_ENABLE)
crc_init();
#endif
-#ifdef QWIIC_ENABLE
- qwiic_init();
-#endif
#ifdef OLED_ENABLE
oled_init(OLED_ROTATION_0);
#endif
@@ -328,12 +313,6 @@ void keyboard_init(void) {
#ifdef PS2_MOUSE_ENABLE
ps2_mouse_init();
#endif
-#ifdef SERIAL_MOUSE_ENABLE
- serial_mouse_init();
-#endif
-#ifdef ADB_MOUSE_ENABLE
- adb_mouse_init();
-#endif
#ifdef BACKLIGHT_ENABLE
backlight_init();
#endif
@@ -356,6 +335,12 @@ void keyboard_init(void) {
#ifdef DIP_SWITCH_ENABLE
dip_switch_init();
#endif
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_init();
+#endif
+#ifdef VIRTSER_ENABLE
+ virtser_init();
+#endif
#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)
debug_enable = true;
@@ -384,7 +369,6 @@ void switch_events(uint8_t row, uint8_t col, bool pressed) {
*
* * scan matrix
* * handle mouse movements
- * * run visualizer code
* * handle midi commands
* * light LEDs
*
@@ -473,10 +457,6 @@ MATRIX_LOOP_END:
if (encoders_changed) last_encoder_activity_trigger();
#endif
-#ifdef QWIIC_ENABLE
- qwiic_task();
-#endif
-
#ifdef OLED_ENABLE
oled_task();
# if OLED_TIMEOUT > 0
@@ -510,22 +490,6 @@ MATRIX_LOOP_END:
ps2_mouse_task();
#endif
-#ifdef SERIAL_MOUSE_ENABLE
- serial_mouse_task();
-#endif
-
-#ifdef ADB_MOUSE_ENABLE
- adb_mouse_task();
-#endif
-
-#ifdef SERIAL_LINK_ENABLE
- serial_link_update();
-#endif
-
-#ifdef VISUALIZER_ENABLE
- visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds());
-#endif
-
#ifdef POINTING_DEVICE_ENABLE
pointing_device_task();
#endif
@@ -548,6 +512,10 @@ MATRIX_LOOP_END:
digitizer_task();
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ programmable_button_send();
+#endif
+
// update LED
if (led_status != host_keyboard_leds()) {
led_status = host_keyboard_leds();
diff --git a/quantum/keycode.h b/quantum/keycode.h
index 8facabd818..38a29b439b 100644
--- a/quantum/keycode.h
+++ b/quantum/keycode.h
@@ -29,7 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED)
#define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF)
#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL)
-#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI)
+#define IS_MOD(code) (KC_LEFT_CTRL <= (code) && (code) <= KC_RIGHT_GUI)
#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE)
@@ -46,10 +46,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MOD_BIT(code) (1 << MOD_INDEX(code))
#define MOD_INDEX(code) ((code)&0x07)
-#define MOD_MASK_CTRL (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RCTRL))
-#define MOD_MASK_SHIFT (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))
-#define MOD_MASK_ALT (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT))
-#define MOD_MASK_GUI (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI))
+#define MOD_MASK_CTRL (MOD_BIT(KC_LEFT_CTRL) | MOD_BIT(KC_RIGHT_CTRL))
+#define MOD_MASK_SHIFT (MOD_BIT(KC_LEFT_SHIFT) | MOD_BIT(KC_RIGHT_SHIFT))
+#define MOD_MASK_ALT (MOD_BIT(KC_LEFT_ALT) | MOD_BIT(KC_RIGHT_ALT))
+#define MOD_MASK_GUI (MOD_BIT(KC_LEFT_GUI) | MOD_BIT(KC_RIGHT_GUI))
#define MOD_MASK_CS (MOD_MASK_CTRL | MOD_MASK_SHIFT)
#define MOD_MASK_CA (MOD_MASK_CTRL | MOD_MASK_ALT)
#define MOD_MASK_CG (MOD_MASK_CTRL | MOD_MASK_GUI)
@@ -67,6 +67,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define FN_MIN KC_FN0
#define FN_MAX KC_FN31
+// clang-format off
+
/*
* Short names for ease of definition of keymap
*/
@@ -75,47 +77,55 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_TRNS KC_TRANSPARENT
/* Punctuation */
-#define KC_ENT KC_ENTER
-#define KC_ESC KC_ESCAPE
-#define KC_BSPC KC_BSPACE
-#define KC_SPC KC_SPACE
+#define KC_ENT KC_ENTER
+#define KC_ESC KC_ESCAPE
+#define KC_BSPC KC_BACKSPACE
+#define KC_SPC KC_SPACE
#define KC_MINS KC_MINUS
-#define KC_EQL KC_EQUAL
-#define KC_LBRC KC_LBRACKET
-#define KC_RBRC KC_RBRACKET
-#define KC_BSLS KC_BSLASH
+#define KC_EQL KC_EQUAL
+#define KC_LBRC KC_LEFT_BRACKET
+#define KC_RBRC KC_RIGHT_BRACKET
+#define KC_BSLS KC_BACKSLASH
#define KC_NUHS KC_NONUS_HASH
-#define KC_SCLN KC_SCOLON
+#define KC_SCLN KC_SEMICOLON
#define KC_QUOT KC_QUOTE
-#define KC_GRV KC_GRAVE
+#define KC_GRV KC_GRAVE
#define KC_COMM KC_COMMA
#define KC_SLSH KC_SLASH
-#define KC_NUBS KC_NONUS_BSLASH
+#define KC_NUBS KC_NONUS_BACKSLASH
/* Lock Keys */
-#define KC_CLCK KC_CAPSLOCK
-#define KC_CAPS KC_CAPSLOCK
-#define KC_SLCK KC_SCROLLLOCK
-#define KC_NLCK KC_NUMLOCK
-#define KC_LCAP KC_LOCKING_CAPS
-#define KC_LNUM KC_LOCKING_NUM
-#define KC_LSCR KC_LOCKING_SCROLL
+#define KC_CAPS KC_CAPS_LOCK
+#define KC_SCRL KC_SCROLL_LOCK
+#define KC_NUM KC_NUM_LOCK
+#define KC_LCAP KC_LOCKING_CAPS_LOCK
+#define KC_LNUM KC_LOCKING_NUM_LOCK
+#define KC_LSCR KC_LOCKING_SCROLL_LOCK
/* Commands */
-#define KC_PSCR KC_PSCREEN
+#define KC_PSCR KC_PRINT_SCREEN
#define KC_PAUS KC_PAUSE
-#define KC_BRK KC_PAUSE
-#define KC_INS KC_INSERT
-#define KC_DEL KC_DELETE
-#define KC_PGDN KC_PGDOWN
+#define KC_BRK KC_PAUSE
+#define KC_INS KC_INSERT
+#define KC_PGUP KC_PAGE_UP
+#define KC_DEL KC_DELETE
+#define KC_PGDN KC_PAGE_DOWN
#define KC_RGHT KC_RIGHT
-#define KC_APP KC_APPLICATION
+#define KC_APP KC_APPLICATION
#define KC_EXEC KC_EXECUTE
#define KC_SLCT KC_SELECT
#define KC_AGIN KC_AGAIN
#define KC_PSTE KC_PASTE
-#define KC_ERAS KC_ALT_ERASE
-#define KC_CLR KC_CLEAR
+#define KC_ERAS KC_ALTERNATE_ERASE
+#define KC_SYRQ KC_SYSTEM_REQUEST
+#define KC_CNCL KC_CANCEL
+#define KC_CLR KC_CLEAR
+#define KC_PRIR KC_PRIOR
+#define KC_RETN KC_RETURN
+#define KC_SEPR KC_SEPARATOR
+#define KC_CLAG KC_CLEAR_AGAIN
+#define KC_CRSL KC_CRSEL
+#define KC_EXSL KC_EXSEL
/* Keypad */
#define KC_PSLS KC_KP_SLASH
@@ -123,47 +133,59 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_PMNS KC_KP_MINUS
#define KC_PPLS KC_KP_PLUS
#define KC_PENT KC_KP_ENTER
-#define KC_P1 KC_KP_1
-#define KC_P2 KC_KP_2
-#define KC_P3 KC_KP_3
-#define KC_P4 KC_KP_4
-#define KC_P5 KC_KP_5
-#define KC_P6 KC_KP_6
-#define KC_P7 KC_KP_7
-#define KC_P8 KC_KP_8
-#define KC_P9 KC_KP_9
-#define KC_P0 KC_KP_0
+#define KC_P1 KC_KP_1
+#define KC_P2 KC_KP_2
+#define KC_P3 KC_KP_3
+#define KC_P4 KC_KP_4
+#define KC_P5 KC_KP_5
+#define KC_P6 KC_KP_6
+#define KC_P7 KC_KP_7
+#define KC_P8 KC_KP_8
+#define KC_P9 KC_KP_9
+#define KC_P0 KC_KP_0
#define KC_PDOT KC_KP_DOT
#define KC_PEQL KC_KP_EQUAL
#define KC_PCMM KC_KP_COMMA
-/* Japanese specific */
-#define KC_ZKHK KC_GRAVE
-#define KC_RO KC_INT1
-#define KC_KANA KC_INT2
-#define KC_JYEN KC_INT3
-#define KC_HENK KC_INT4
-#define KC_MHEN KC_INT5
-
-/* Korean specific */
-#define KC_HAEN KC_LANG1
-#define KC_HANJ KC_LANG2
+/* Language Specific */
+#define KC_INT1 KC_INTERNATIONAL_1
+#define KC_INT2 KC_INTERNATIONAL_2
+#define KC_INT3 KC_INTERNATIONAL_3
+#define KC_INT4 KC_INTERNATIONAL_4
+#define KC_INT5 KC_INTERNATIONAL_5
+#define KC_INT6 KC_INTERNATIONAL_6
+#define KC_INT7 KC_INTERNATIONAL_7
+#define KC_INT8 KC_INTERNATIONAL_8
+#define KC_INT9 KC_INTERNATIONAL_9
+#define KC_LNG1 KC_LANGUAGE_1
+#define KC_LNG2 KC_LANGUAGE_2
+#define KC_LNG3 KC_LANGUAGE_3
+#define KC_LNG4 KC_LANGUAGE_4
+#define KC_LNG5 KC_LANGUAGE_5
+#define KC_LNG6 KC_LANGUAGE_6
+#define KC_LNG7 KC_LANGUAGE_7
+#define KC_LNG8 KC_LANGUAGE_8
+#define KC_LNG9 KC_LANGUAGE_9
/* Modifiers */
-#define KC_LCTL KC_LCTRL
-#define KC_LSFT KC_LSHIFT
-#define KC_LOPT KC_LALT
-#define KC_LCMD KC_LGUI
-#define KC_LWIN KC_LGUI
-#define KC_RCTL KC_RCTRL
-#define KC_RSFT KC_RSHIFT
-#define KC_ALGR KC_RALT
-#define KC_ROPT KC_RALT
-#define KC_RCMD KC_RGUI
-#define KC_RWIN KC_RGUI
+#define KC_LCTL KC_LEFT_CTRL
+#define KC_LSFT KC_LEFT_SHIFT
+#define KC_LALT KC_LEFT_ALT
+#define KC_LOPT KC_LEFT_ALT
+#define KC_LGUI KC_LEFT_GUI
+#define KC_LCMD KC_LEFT_GUI
+#define KC_LWIN KC_LEFT_GUI
+#define KC_RCTL KC_RIGHT_CTRL
+#define KC_RSFT KC_RIGHT_SHIFT
+#define KC_RALT KC_RIGHT_ALT
+#define KC_ALGR KC_RIGHT_ALT
+#define KC_ROPT KC_RIGHT_ALT
+#define KC_RGUI KC_RIGHT_GUI
+#define KC_RCMD KC_RIGHT_GUI
+#define KC_RWIN KC_RIGHT_GUI
/* Generic Desktop Page (0x01) */
-#define KC_PWR KC_SYSTEM_POWER
+#define KC_PWR KC_SYSTEM_POWER
#define KC_SLEP KC_SYSTEM_SLEEP
#define KC_WAKE KC_SYSTEM_WAKE
@@ -193,7 +215,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* System Specific */
#define KC_BRMU KC_PAUSE
-#define KC_BRMD KC_SCROLLLOCK
+#define KC_BRMD KC_SCROLL_LOCK
/* Mouse Keys */
#define KC_MS_U KC_MS_UP
@@ -216,6 +238,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_ACL1 KC_MS_ACCEL1
#define KC_ACL2 KC_MS_ACCEL2
+// clang-format on
+
/* Keyboard/Keypad Page (0x07) */
enum hid_keyboard_keypad_usage {
KC_NO = 0x00,
@@ -260,22 +284,22 @@ enum hid_keyboard_keypad_usage {
KC_0,
KC_ENTER,
KC_ESCAPE,
- KC_BSPACE,
+ KC_BACKSPACE,
KC_TAB,
KC_SPACE,
KC_MINUS,
KC_EQUAL,
- KC_LBRACKET,
- KC_RBRACKET, // 0x30
- KC_BSLASH,
+ KC_LEFT_BRACKET,
+ KC_RIGHT_BRACKET, // 0x30
+ KC_BACKSLASH,
KC_NONUS_HASH,
- KC_SCOLON,
+ KC_SEMICOLON,
KC_QUOTE,
KC_GRAVE,
KC_COMMA,
KC_DOT,
KC_SLASH,
- KC_CAPSLOCK,
+ KC_CAPS_LOCK,
KC_F1,
KC_F2,
KC_F3,
@@ -288,20 +312,20 @@ enum hid_keyboard_keypad_usage {
KC_F10,
KC_F11,
KC_F12,
- KC_PSCREEN,
- KC_SCROLLLOCK,
+ KC_PRINT_SCREEN,
+ KC_SCROLL_LOCK,
KC_PAUSE,
KC_INSERT,
KC_HOME,
- KC_PGUP,
+ KC_PAGE_UP,
KC_DELETE,
KC_END,
- KC_PGDOWN,
+ KC_PAGE_DOWN,
KC_RIGHT,
KC_LEFT, // 0x50
KC_DOWN,
KC_UP,
- KC_NUMLOCK,
+ KC_NUM_LOCK,
KC_KP_SLASH,
KC_KP_ASTERISK,
KC_KP_MINUS,
@@ -318,9 +342,9 @@ enum hid_keyboard_keypad_usage {
KC_KP_9,
KC_KP_0,
KC_KP_DOT,
- KC_NONUS_BSLASH,
+ KC_NONUS_BACKSLASH,
KC_APPLICATION,
- KC_POWER,
+ KC_KB_POWER,
KC_KP_EQUAL,
KC_F13,
KC_F14,
@@ -345,34 +369,34 @@ enum hid_keyboard_keypad_usage {
KC_COPY,
KC_PASTE,
KC_FIND,
- KC__MUTE,
- KC__VOLUP, // 0x80
- KC__VOLDOWN,
- KC_LOCKING_CAPS,
- KC_LOCKING_NUM,
- KC_LOCKING_SCROLL,
+ KC_KB_MUTE,
+ KC_KB_VOLUME_UP, // 0x80
+ KC_KB_VOLUME_DOWN,
+ KC_LOCKING_CAPS_LOCK,
+ KC_LOCKING_NUM_LOCK,
+ KC_LOCKING_SCROLL_LOCK,
KC_KP_COMMA,
KC_KP_EQUAL_AS400,
- KC_INT1,
- KC_INT2,
- KC_INT3,
- KC_INT4,
- KC_INT5,
- KC_INT6,
- KC_INT7,
- KC_INT8,
- KC_INT9,
- KC_LANG1, // 0x90
- KC_LANG2,
- KC_LANG3,
- KC_LANG4,
- KC_LANG5,
- KC_LANG6,
- KC_LANG7,
- KC_LANG8,
- KC_LANG9,
- KC_ALT_ERASE,
- KC_SYSREQ,
+ KC_INTERNATIONAL_1,
+ KC_INTERNATIONAL_2,
+ KC_INTERNATIONAL_3,
+ KC_INTERNATIONAL_4,
+ KC_INTERNATIONAL_5,
+ KC_INTERNATIONAL_6,
+ KC_INTERNATIONAL_7,
+ KC_INTERNATIONAL_8,
+ KC_INTERNATIONAL_9,
+ KC_LANGUAGE_1, // 0x90
+ KC_LANGUAGE_2,
+ KC_LANGUAGE_3,
+ KC_LANGUAGE_4,
+ KC_LANGUAGE_5,
+ KC_LANGUAGE_6,
+ KC_LANGUAGE_7,
+ KC_LANGUAGE_8,
+ KC_LANGUAGE_9,
+ KC_ALTERNATE_ERASE,
+ KC_SYSTEM_REQUEST,
KC_CANCEL,
KC_CLEAR,
KC_PRIOR,
@@ -397,12 +421,12 @@ enum hid_keyboard_keypad_usage {
KC_DECIMAL_SEPARATOR,
KC_CURRENCY_UNIT,
KC_CURRENCY_SUB_UNIT,
- KC_KP_LPAREN,
- KC_KP_RPAREN,
- KC_KP_LCBRACKET,
- KC_KP_RCBRACKET,
+ KC_KP_LEFT_PARENTHESIS,
+ KC_KP_RIGHT_PARENTHESIS,
+ KC_KP_LEFT_BRACE,
+ KC_KP_RIGHT_BRACE,
KC_KP_TAB,
- KC_KP_BSPACE,
+ KC_KP_BACKSPACE,
KC_KP_A,
KC_KP_B,
KC_KP_C,
@@ -411,17 +435,17 @@ enum hid_keyboard_keypad_usage {
KC_KP_F,
KC_KP_XOR,
KC_KP_HAT,
- KC_KP_PERC,
- KC_KP_LT,
- KC_KP_GT,
+ KC_KP_PERCENT,
+ KC_KP_LESS_THAN,
+ KC_KP_GREATER_THAN,
KC_KP_AND,
- KC_KP_LAZYAND,
+ KC_KP_LAZY_AND,
KC_KP_OR,
- KC_KP_LAZYOR,
+ KC_KP_LAZY_OR,
KC_KP_COLON,
KC_KP_HASH,
KC_KP_SPACE,
- KC_KP_ATMARK,
+ KC_KP_AT,
KC_KP_EXCLAMATION,
KC_KP_MEM_STORE, //0xD0
KC_KP_MEM_RECALL,
@@ -440,14 +464,14 @@ enum hid_keyboard_keypad_usage {
#endif
/* Modifiers */
- KC_LCTRL = 0xE0,
- KC_LSHIFT,
- KC_LALT,
- KC_LGUI,
- KC_RCTRL,
- KC_RSHIFT,
- KC_RALT,
- KC_RGUI
+ KC_LEFT_CTRL = 0xE0,
+ KC_LEFT_SHIFT,
+ KC_LEFT_ALT,
+ KC_LEFT_GUI,
+ KC_RIGHT_CTRL,
+ KC_RIGHT_SHIFT,
+ KC_RIGHT_ALT,
+ KC_RIGHT_GUI
// **********************************************
// * 0xF0-0xFF are unallocated in the HID spec. *
@@ -558,3 +582,5 @@ enum mouse_keys {
KC_MS_ACCEL1,
KC_MS_ACCEL2 // 0xFF
};
+
+#include "keycode_legacy.h"
diff --git a/quantum/keycode_config.c b/quantum/keycode_config.c
index f340905eab..dd2a17e242 100644
--- a/quantum/keycode_config.c
+++ b/quantum/keycode_config.c
@@ -25,89 +25,89 @@ extern keymap_config_t keymap_config;
*/
uint16_t keycode_config(uint16_t keycode) {
switch (keycode) {
- case KC_CAPSLOCK:
- case KC_LOCKING_CAPS:
+ case KC_CAPS_LOCK:
+ case KC_LOCKING_CAPS_LOCK:
if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
- return KC_LCTL;
+ return KC_LEFT_CTRL;
}
return keycode;
- case KC_LCTL:
+ case KC_LEFT_CTRL:
if (keymap_config.swap_control_capslock) {
- return KC_CAPSLOCK;
+ return KC_CAPS_LOCK;
}
if (keymap_config.swap_lctl_lgui) {
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_LGUI;
+ return KC_LEFT_GUI;
}
- return KC_LCTL;
- case KC_LALT:
+ return KC_LEFT_CTRL;
+ case KC_LEFT_ALT:
if (keymap_config.swap_lalt_lgui) {
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_LGUI;
+ return KC_LEFT_GUI;
}
- return KC_LALT;
- case KC_LGUI:
+ return KC_LEFT_ALT;
+ case KC_LEFT_GUI:
if (keymap_config.swap_lalt_lgui) {
- return KC_LALT;
+ return KC_LEFT_ALT;
}
if (keymap_config.swap_lctl_lgui) {
- return KC_LCTRL;
+ return KC_LEFT_CTRL;
}
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_LGUI;
- case KC_RCTL:
+ return KC_LEFT_GUI;
+ case KC_RIGHT_CTRL:
if (keymap_config.swap_rctl_rgui) {
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_RGUI;
+ return KC_RIGHT_GUI;
}
- return KC_RCTL;
- case KC_RALT:
+ return KC_RIGHT_CTRL;
+ case KC_RIGHT_ALT:
if (keymap_config.swap_ralt_rgui) {
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_RGUI;
+ return KC_RIGHT_GUI;
}
- return KC_RALT;
- case KC_RGUI:
+ return KC_RIGHT_ALT;
+ case KC_RIGHT_GUI:
if (keymap_config.swap_ralt_rgui) {
- return KC_RALT;
+ return KC_RIGHT_ALT;
}
if (keymap_config.swap_rctl_rgui) {
- return KC_RCTL;
+ return KC_RIGHT_CTRL;
}
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_RGUI;
+ return KC_RIGHT_GUI;
case KC_GRAVE:
if (keymap_config.swap_grave_esc) {
- return KC_ESC;
+ return KC_ESCAPE;
}
return KC_GRAVE;
- case KC_ESC:
+ case KC_ESCAPE:
if (keymap_config.swap_grave_esc) {
return KC_GRAVE;
}
- return KC_ESC;
- case KC_BSLASH:
+ return KC_ESCAPE;
+ case KC_BACKSLASH:
if (keymap_config.swap_backslash_backspace) {
- return KC_BSPACE;
+ return KC_BACKSPACE;
}
- return KC_BSLASH;
- case KC_BSPACE:
+ return KC_BACKSLASH;
+ case KC_BACKSPACE:
if (keymap_config.swap_backslash_backspace) {
- return KC_BSLASH;
+ return KC_BACKSLASH;
}
- return KC_BSPACE;
+ return KC_BACKSPACE;
default:
return keycode;
}
diff --git a/quantum/keycode_legacy.h b/quantum/keycode_legacy.h
new file mode 100644
index 0000000000..0317a05534
--- /dev/null
+++ b/quantum/keycode_legacy.h
@@ -0,0 +1,53 @@
+#pragma once
+
+// clang-format off
+
+// These keycode names have been deprecated
+
+#define KC_BSPACE KC_BACKSPACE
+#define KC_LBRACKET KC_LEFT_BRACKET
+#define KC_RBRACKET KC_RIGHT_BRACKET
+#define KC_BSLASH KC_BACKSLASH
+#define KC_SCOLON KC_SEMICOLON
+#define KC_CAPSLOCK KC_CAPS_LOCK
+#define KC_PSCREEN KC_PRINT_SCREEN
+#define KC_SCROLLLOCK KC_SCROLL_LOCK
+#define KC_PGDOWN KC_PAGE_DOWN
+#define KC_NUMLOCK KC_NUM_LOCK
+#define KC_NONUS_BSLASH KC_NONUS_BACKSLASH
+#define KC_POWER KC_KB_POWER
+#define KC__MUTE KC_KB_MUTE
+#define KC__VOLUP KC_KB_VOLUME_UP
+#define KC__VOLDOWN KC_KB_VOLUME_DOWN
+#define KC_LOCKING_CAPS KC_LOCKING_CAPS_LOCK
+#define KC_LOCKING_NUM KC_LOCKING_NUM_LOCK
+#define KC_LOCKING_SCROLL KC_LOCKING_SCROLL_LOCK
+#define KC_LANG1 KC_LANGUAGE_1
+#define KC_LANG2 KC_LANGUAGE_2
+#define KC_LANG3 KC_LANGUAGE_3
+#define KC_LANG4 KC_LANGUAGE_4
+#define KC_LANG5 KC_LANGUAGE_5
+#define KC_LANG6 KC_LANGUAGE_6
+#define KC_LANG7 KC_LANGUAGE_7
+#define KC_LANG8 KC_LANGUAGE_8
+#define KC_LANG9 KC_LANGUAGE_9
+#define KC_ALT_ERASE KC_ALTERNATE_ERASE
+#define KC_SYSREQ KC_SYSTEM_REQUEST
+
+#define KC_LCTRL KC_LEFT_CTRL
+#define KC_LSHIFT KC_LEFT_SHIFT
+#define KC_RCTRL KC_RIGHT_CTRL
+#define KC_RSHIFT KC_RIGHT_SHIFT
+
+#define KC_ZKHK KC_GRAVE
+#define KC_RO KC_INTERNATIONAL_1
+#define KC_KANA KC_INTERNATIONAL_2
+#define KC_JYEN KC_INTERNATIONAL_3
+#define KC_HENK KC_INTERNATIONAL_4
+#define KC_MHEN KC_INTERNATIONAL_5
+#define KC_HAEN KC_LANGUAGE_1
+#define KC_HANJ KC_LANGUAGE_2
+
+#define KC_CLCK KC_CAPS_LOCK
+#define KC_SLCK KC_SCROLL_LOCK
+#define KC_NLCK KC_NUM_LOCK
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index 780c71ab9b..5007f15f11 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -56,7 +56,7 @@ action_t action_for_keycode(uint16_t keycode) {
switch (keycode) {
case KC_A ... KC_EXSEL:
- case KC_LCTRL ... KC_RGUI:
+ case KC_LEFT_CTRL ... KC_RIGHT_GUI:
action.code = ACTION_KEY(keycode);
break;
#ifdef EXTRAKEY_ENABLE
@@ -72,7 +72,7 @@ action_t action_for_keycode(uint16_t keycode) {
action.code = ACTION_MOUSEKEY(keycode);
break;
#endif
- case KC_TRNS:
+ case KC_TRANSPARENT:
action.code = ACTION_TRANSPARENT;
break;
case QK_MODS ... QK_MODS_MAX:;
diff --git a/quantum/keymap_extras/keymap_korean.h b/quantum/keymap_extras/keymap_korean.h
index 23d235ef09..74be122dad 100644
--- a/quantum/keymap_extras/keymap_korean.h
+++ b/quantum/keymap_extras/keymap_korean.h
@@ -85,8 +85,8 @@
#define KR_DOT KC_DOT // .
#define KR_SLSH KC_SLSH // /
// Row 5
-#define KR_HANJ KC_LANG2 // Hanja (한자)
-#define KR_HAEN KC_LANG1 // Han ↔ Yeong (한 ↔ 영)
+#define KR_HANJ KC_LNG2 // Hanja (한자)
+#define KR_HAEN KC_LNG1 // Han ↔ Yeong (한 ↔ 영)
/* Shifted symbols
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
diff --git a/quantum/keymap_extras/keymap_steno.h b/quantum/keymap_extras/keymap_steno.h
index ab95b43fdd..310aa07409 100644
--- a/quantum/keymap_extras/keymap_steno.h
+++ b/quantum/keymap_extras/keymap_steno.h
@@ -74,8 +74,7 @@ enum steno_keycodes {
};
#ifdef STENO_COMBINEDMAP
-enum steno_combined_keycodes
-{
+enum steno_combined_keycodes {
STN_S3 = QK_STENO_COMB,
STN_TKL,
STN_PWL,
diff --git a/quantum/keymap_extras/keymap_turkish_f.h b/quantum/keymap_extras/keymap_turkish_f.h
index 226f8cbeb0..f86ef21546 100644
--- a/quantum/keymap_extras/keymap_turkish_f.h
+++ b/quantum/keymap_extras/keymap_turkish_f.h
@@ -111,7 +111,7 @@
#define TR_LPRN S(TR_8) // (
#define TR_RPRN S(TR_9) // )
#define TR_EQL S(TR_0) // =
-#define TR_QUES S(TR_ASTR) // ?
+#define TR_QUES S(TR_SLSH) // ?
#define TR_UNDS S(TR_MINS) // _
// Row 4
#define TR_RABK S(TR_LABK) // >
diff --git a/quantum/led_matrix/animations/alpha_mods_anim.h b/quantum/led_matrix/animations/alpha_mods_anim.h
index 14038cd082..4d017894a1 100644
--- a/quantum/led_matrix/animations/alpha_mods_anim.h
+++ b/quantum/led_matrix/animations/alpha_mods_anim.h
@@ -17,8 +17,8 @@ bool ALPHAS_MODS(effect_params_t* params) {
led_matrix_set_value(i, val1);
}
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_ALPHAS_MODS
+#endif // ENABLE_LED_MATRIX_ALPHAS_MODS
diff --git a/quantum/led_matrix/animations/band_anim.h b/quantum/led_matrix/animations/band_anim.h
index 5548787b88..293be4f67a 100644
--- a/quantum/led_matrix/animations/band_anim.h
+++ b/quantum/led_matrix/animations/band_anim.h
@@ -10,4 +10,4 @@ static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) {
bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_BAND
+#endif // ENABLE_LED_MATRIX_BAND
diff --git a/quantum/led_matrix/animations/band_pinwheel_anim.h b/quantum/led_matrix/animations/band_pinwheel_anim.h
index 89651582d5..f47a3869ce 100644
--- a/quantum/led_matrix/animations/band_pinwheel_anim.h
+++ b/quantum/led_matrix/animations/band_pinwheel_anim.h
@@ -7,4 +7,4 @@ static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t t
bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_BAND_PINWHEEL
+#endif // ENABLE_LED_MATRIX_BAND_PINWHEEL
diff --git a/quantum/led_matrix/animations/band_spiral_anim.h b/quantum/led_matrix/animations/band_spiral_anim.h
index 70b0ffaea9..a4bd382181 100644
--- a/quantum/led_matrix/animations/band_spiral_anim.h
+++ b/quantum/led_matrix/animations/band_spiral_anim.h
@@ -7,4 +7,4 @@ static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dis
bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_BAND_SPIRAL
+#endif // ENABLE_LED_MATRIX_BAND_SPIRAL
diff --git a/quantum/led_matrix/animations/breathing_anim.h b/quantum/led_matrix/animations/breathing_anim.h
index e3f600c45c..899925f516 100644
--- a/quantum/led_matrix/animations/breathing_anim.h
+++ b/quantum/led_matrix/animations/breathing_anim.h
@@ -12,8 +12,8 @@ bool BREATHING(effect_params_t* params) {
LED_MATRIX_TEST_LED_FLAGS();
led_matrix_set_value(i, val);
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_BREATHING
+#endif // ENABLE_LED_MATRIX_BREATHING
diff --git a/quantum/led_matrix/animations/cycle_left_right_anim.h b/quantum/led_matrix/animations/cycle_left_right_anim.h
index 769e6d7942..1a8999b831 100644
--- a/quantum/led_matrix/animations/cycle_left_right_anim.h
+++ b/quantum/led_matrix/animations/cycle_left_right_anim.h
@@ -7,4 +7,4 @@ static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { ret
bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
+#endif // ENABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
diff --git a/quantum/led_matrix/animations/cycle_out_in_anim.h b/quantum/led_matrix/animations/cycle_out_in_anim.h
index 6adf9c25ff..77d3a14b6f 100644
--- a/quantum/led_matrix/animations/cycle_out_in_anim.h
+++ b/quantum/led_matrix/animations/cycle_out_in_anim.h
@@ -7,4 +7,4 @@ static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t di
bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN
+#endif // ENABLE_LED_MATRIX_CYCLE_OUT_IN
diff --git a/quantum/led_matrix/animations/cycle_up_down_anim.h b/quantum/led_matrix/animations/cycle_up_down_anim.h
index 7a5868ac26..b25947199c 100644
--- a/quantum/led_matrix/animations/cycle_up_down_anim.h
+++ b/quantum/led_matrix/animations/cycle_up_down_anim.h
@@ -7,4 +7,4 @@ static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return
bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN
+#endif // ENABLE_LED_MATRIX_CYCLE_UP_DOWN
diff --git a/quantum/led_matrix/animations/dual_beacon_anim.h b/quantum/led_matrix/animations/dual_beacon_anim.h
index 3552c9fc39..81735e323c 100644
--- a/quantum/led_matrix/animations/dual_beacon_anim.h
+++ b/quantum/led_matrix/animations/dual_beacon_anim.h
@@ -7,4 +7,4 @@ static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i,
bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_DUAL_BEACON
+#endif // ENABLE_LED_MATRIX_DUAL_BEACON
diff --git a/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
index ef97631b90..fa9b7dbbfa 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
@@ -12,5 +12,5 @@ bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) {
int16_t dy = g_led_config.point[i].y - k_led_matrix_center.y;
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, time));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
index 5ef5938be0..061a5f07fe 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
@@ -13,5 +13,5 @@ bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func)
uint8_t dist = sqrt16(dx * dx + dy * dy);
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, dist, time));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/led_matrix/animations/runners/effect_runner_i.h b/quantum/led_matrix/animations/runners/effect_runner_i.h
index b3015759be..f6f8c0dee0 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_i.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_i.h
@@ -10,5 +10,5 @@ bool effect_runner_i(effect_params_t* params, i_f effect_func) {
LED_MATRIX_TEST_LED_FLAGS();
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, i, time));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/led_matrix/animations/runners/effect_runner_reactive.h b/quantum/led_matrix/animations/runners/effect_runner_reactive.h
index 4369ea8c49..be3090aa53 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_reactive.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_reactive.h
@@ -22,7 +22,7 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) {
uint16_t offset = scale16by8(tick, led_matrix_eeconfig.speed);
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, offset));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
index d6eb9731ee..f6ffc825a1 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
@@ -20,7 +20,7 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react
}
led_matrix_set_value(i, scale8(val, led_matrix_eeconfig.val));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
index 4a5219abd1..3145e27139 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
@@ -12,5 +12,5 @@ bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) {
LED_MATRIX_TEST_LED_FLAGS();
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, cos_value, sin_value, i, time));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/led_matrix/animations/solid_anim.h b/quantum/led_matrix/animations/solid_anim.h
index 4c9e43c581..c728dbcc98 100644
--- a/quantum/led_matrix/animations/solid_anim.h
+++ b/quantum/led_matrix/animations/solid_anim.h
@@ -9,7 +9,7 @@ bool SOLID(effect_params_t* params) {
LED_MATRIX_TEST_LED_FLAGS();
led_matrix_set_value(i, val);
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
#endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/quantum/led_matrix/animations/solid_reactive_cross.h b/quantum/led_matrix/animations/solid_reactive_cross.h
index 3a3c46be13..a149e9a929 100644
--- a/quantum/led_matrix/animations/solid_reactive_cross.h
+++ b/quantum/led_matrix/animations/solid_reactive_cross.h
@@ -1,5 +1,5 @@
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
+# if defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS
LED_MATRIX_EFFECT(SOLID_REACTIVE_CROSS)
@@ -31,5 +31,5 @@ bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_r
# endif
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
+# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/solid_reactive_nexus.h b/quantum/led_matrix/animations/solid_reactive_nexus.h
index 2520b8e1df..5a86e48c6c 100644
--- a/quantum/led_matrix/animations/solid_reactive_nexus.h
+++ b/quantum/led_matrix/animations/solid_reactive_nexus.h
@@ -28,5 +28,5 @@ bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_r
# endif
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
+# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/solid_reactive_simple_anim.h b/quantum/led_matrix/animations/solid_reactive_simple_anim.h
index 43f6ad9ab4..14f5e90730 100644
--- a/quantum/led_matrix/animations/solid_reactive_simple_anim.h
+++ b/quantum/led_matrix/animations/solid_reactive_simple_anim.h
@@ -8,5 +8,5 @@ static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { return
bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
+# endif // ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/solid_reactive_wide.h b/quantum/led_matrix/animations/solid_reactive_wide.h
index d683b02510..3aa88063a7 100644
--- a/quantum/led_matrix/animations/solid_reactive_wide.h
+++ b/quantum/led_matrix/animations/solid_reactive_wide.h
@@ -1,5 +1,5 @@
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
+# if !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
LED_MATRIX_EFFECT(SOLID_REACTIVE_WIDE)
@@ -26,5 +26,5 @@ bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_re
# endif
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
+# endif // !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/solid_splash_anim.h b/quantum/led_matrix/animations/solid_splash_anim.h
index cf599c8fe6..17b692a09a 100644
--- a/quantum/led_matrix/animations/solid_splash_anim.h
+++ b/quantum/led_matrix/animations/solid_splash_anim.h
@@ -1,5 +1,5 @@
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_LED_MATRIX_SOLID_SPLASH) || !defined(DISABLE_LED_MATRIX_SOLID_MULTISPLASH)
+# if defined(ENABLE_LED_MATRIX_SOLID_SPLASH) || defined(ENABLE_LED_MATRIX_SOLID_MULTISPLASH)
# ifdef ENABLE_LED_MATRIX_SOLID_SPLASH
LED_MATRIX_EFFECT(SOLID_SPLASH)
@@ -26,5 +26,5 @@ bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_
# endif
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH)
+# endif // defined(ENABLE_LED_MATRIX_SPLASH) || defined(ENABLE_LED_MATRIX_MULTISPLASH)
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/wave_left_right_anim.h b/quantum/led_matrix/animations/wave_left_right_anim.h
index c062cf968e..76487f8515 100644
--- a/quantum/led_matrix/animations/wave_left_right_anim.h
+++ b/quantum/led_matrix/animations/wave_left_right_anim.h
@@ -7,4 +7,4 @@ static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { retu
bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT
+#endif // ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT
diff --git a/quantum/led_matrix/animations/wave_up_down_anim.h b/quantum/led_matrix/animations/wave_up_down_anim.h
index 5e612f6b6d..94710f5c6e 100644
--- a/quantum/led_matrix/animations/wave_up_down_anim.h
+++ b/quantum/led_matrix/animations/wave_up_down_anim.h
@@ -7,4 +7,4 @@ static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return
bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN
+#endif // ENABLE_LED_MATRIX_WAVE_UP_DOWN
diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c
index 50510e49aa..be1494e884 100644
--- a/quantum/led_matrix/led_matrix.c
+++ b/quantum/led_matrix/led_matrix.c
@@ -33,14 +33,6 @@ const led_point_t k_led_matrix_center = {112, 32};
const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
#endif
-// clang-format off
-#ifndef LED_MATRIX_IMMEDIATE_EEPROM
-# define led_eeconfig_update(v) led_update_eeprom |= v
-#else
-# define led_eeconfig_update(v) if (v) eeconfig_update_led_matrix()
-#endif
-// clang-format on
-
// Generic effect runners
#include "led_matrix_runners.inc"
@@ -107,7 +99,6 @@ last_hit_t g_last_hit_tracker;
// internals
static bool suspend_state = false;
-static bool led_update_eeprom = false;
static uint8_t led_last_enable = UINT8_MAX;
static uint8_t led_last_effect = UINT8_MAX;
static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false};
@@ -127,9 +118,9 @@ static last_hit_t last_hit_buffer;
const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT;
#endif
-void eeconfig_read_led_matrix(void) { eeprom_read_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); }
+EECONFIG_DEBOUNCE_HELPER(led_matrix, EECONFIG_LED_MATRIX, led_matrix_eeconfig);
-void eeconfig_update_led_matrix(void) { eeprom_update_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); }
+void eeconfig_update_led_matrix(void) { eeconfig_flush_led_matrix(true); }
void eeconfig_update_led_matrix_default(void) {
dprintf("eeconfig_update_led_matrix_default\n");
@@ -138,7 +129,7 @@ void eeconfig_update_led_matrix_default(void) {
led_matrix_eeconfig.val = LED_MATRIX_STARTUP_VAL;
led_matrix_eeconfig.speed = LED_MATRIX_STARTUP_SPD;
led_matrix_eeconfig.flags = LED_FLAG_ALL;
- eeconfig_update_led_matrix();
+ eeconfig_flush_led_matrix(true);
}
void eeconfig_debug_led_matrix(void) {
@@ -165,20 +156,10 @@ uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l
void led_matrix_update_pwm_buffers(void) { led_matrix_driver.flush(); }
void led_matrix_set_value(int index, uint8_t value) {
-#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
- if (!is_keyboard_left() && index >= k_led_matrix_split[0])
-# ifdef USE_CIE1931_CURVE
- led_matrix_driver.set_value(index - k_led_matrix_split[0], pgm_read_byte(&CIE1931_CURVE[value]));
-# else
- led_matrix_driver.set_value(index - k_led_matrix_split[0], value);
-# endif
- else if (is_keyboard_left() && index < k_led_matrix_split[0])
-#endif
#ifdef USE_CIE1931_CURVE
- led_matrix_driver.set_value(index, pgm_read_byte(&CIE1931_CURVE[value]));
-#else
- led_matrix_driver.set_value(index, value);
+ value = pgm_read_byte(&CIE1931_CURVE[value]);
#endif
+ led_matrix_driver.set_value(index, value);
}
void led_matrix_set_value_all(uint8_t value) {
@@ -232,11 +213,11 @@ void process_led_matrix(uint8_t row, uint8_t col, bool pressed) {
}
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
-#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP)
+#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
if (led_matrix_eeconfig.mode == LED_MATRIX_TYPING_HEATMAP) {
process_led_matrix_typing_heatmap(row, col);
}
-#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP)
+#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
}
static bool led_matrix_none(effect_params_t *params) {
@@ -279,9 +260,8 @@ static void led_task_timers(void) {
}
static void led_task_sync(void) {
+ eeconfig_flush_led_matrix(false);
// next task
- if (led_update_eeprom) eeconfig_update_led_matrix();
- led_update_eeprom = false;
if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING;
}
@@ -449,7 +429,7 @@ void led_matrix_init(void) {
eeconfig_update_led_matrix_default();
}
- eeconfig_read_led_matrix();
+ eeconfig_init_led_matrix();
if (!led_matrix_eeconfig.mode) {
dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n");
eeconfig_update_led_matrix_default();
@@ -472,7 +452,7 @@ bool led_matrix_get_suspend_state(void) { return suspend_state; }
void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
led_matrix_eeconfig.enable ^= 1;
led_task_state = STARTING;
- led_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_led_matrix(write_to_eeprom);
dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable);
}
void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); }
@@ -480,7 +460,7 @@ void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); }
void led_matrix_enable(void) {
led_matrix_enable_noeeprom();
- led_eeconfig_update(true);
+ eeconfig_flag_led_matrix(true);
}
void led_matrix_enable_noeeprom(void) {
@@ -490,7 +470,7 @@ void led_matrix_enable_noeeprom(void) {
void led_matrix_disable(void) {
led_matrix_disable_noeeprom();
- led_eeconfig_update(true);
+ eeconfig_flag_led_matrix(true);
}
void led_matrix_disable_noeeprom(void) {
@@ -512,7 +492,7 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
led_matrix_eeconfig.mode = mode;
}
led_task_state = STARTING;
- led_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_led_matrix(write_to_eeprom);
dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode);
}
void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); }
@@ -539,7 +519,7 @@ void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) {
return;
}
led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val;
- led_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_led_matrix(write_to_eeprom);
dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val);
}
void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); }
@@ -557,7 +537,7 @@ void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); }
void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
led_matrix_eeconfig.speed = speed;
- led_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_led_matrix(write_to_eeprom);
dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed);
}
void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); }
diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h
index a7a1c983f7..e42be64661 100644
--- a/quantum/led_matrix/led_matrix.h
+++ b/quantum/led_matrix/led_matrix.h
@@ -23,7 +23,6 @@
#include <stdbool.h>
#include "led_matrix_types.h"
#include "quantum.h"
-#include "led_matrix_legacy_enables.h"
#ifdef IS31FL3731
# include "is31fl3731-simple.h"
@@ -38,14 +37,33 @@
#endif
#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL
-# define LED_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \
- uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \
- if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
+# if defined(LED_MATRIX_SPLIT)
+# define LED_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \
+ uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \
+ if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; \
+ uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; \
+ if (is_keyboard_left() && (max > k_led_matrix_split[0])) max = k_led_matrix_split[0]; \
+ if (!(is_keyboard_left()) && (min < k_led_matrix_split[0])) min = k_led_matrix_split[0];
+# else
+# define LED_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \
+ uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \
+ if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
+# endif
#else
-# define LED_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = 0; \
- uint8_t max = DRIVER_LED_TOTAL;
+# if defined(LED_MATRIX_SPLIT)
+# define LED_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = 0; \
+ uint8_t max = DRIVER_LED_TOTAL; \
+ const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; \
+ if (is_keyboard_left() && (max > k_led_matrix_split[0])) max = k_led_matrix_split[0]; \
+ if (!(is_keyboard_left()) && (min < k_led_matrix_split[0])) min = k_led_matrix_split[0];
+# else
+# define LED_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = 0; \
+ uint8_t max = DRIVER_LED_TOTAL;
+# endif
#endif
#define LED_MATRIX_TEST_LED_FLAGS() \
@@ -147,6 +165,18 @@ typedef struct {
void (*flush)(void);
} led_matrix_driver_t;
+static inline bool led_matrix_check_finished_leds(uint8_t led_idx) {
+#if defined(LED_MATRIX_SPLIT)
+ if (is_keyboard_left()) {
+ uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT;
+ return led_idx < k_led_matrix_split[0];
+ } else
+ return led_idx < DRIVER_LED_TOTAL;
+#else
+ return led_idx < DRIVER_LED_TOTAL;
+#endif
+}
+
extern const led_matrix_driver_t led_matrix_driver;
extern led_eeconfig_t led_matrix_eeconfig;
diff --git a/quantum/led_matrix/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c
index 1d46b2c506..2157619a0b 100644
--- a/quantum/led_matrix/led_matrix_drivers.c
+++ b/quantum/led_matrix/led_matrix_drivers.c
@@ -26,128 +26,123 @@
*/
#if defined(IS31FL3731) || defined(IS31FL3733)
-
# include "i2c_master.h"
static void init(void) {
i2c_init();
-# ifdef IS31FL3731
-# ifdef LED_DRIVER_ADDR_1
+
+# if defined(IS31FL3731)
IS31FL3731_init(LED_DRIVER_ADDR_1);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3731_init(LED_DRIVER_ADDR_2);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3731_init(LED_DRIVER_ADDR_3);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3731_init(LED_DRIVER_ADDR_4);
-# endif
-# else
-# ifdef LED_DRIVER_ADDR_1
-# ifndef LED_DRIVER_SYNC_1
-# define LED_DRIVER_SYNC_1 0
+# endif
# endif
- IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1);
# endif
-# ifdef LED_DRIVER_ADDR_2
-# ifndef LED_DRIVER_SYNC_2
+
+# elif defined(IS31FL3733)
+# if !defined(LED_DRIVER_SYNC_1)
+# define LED_DRIVER_SYNC_1 0
+# endif
+ IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1);
+# if defined(LED_DRIVER_ADDR_2)
+# if !defined(LED_DRIVER_SYNC_2)
# define LED_DRIVER_SYNC_2 0
# endif
IS31FL3733_init(LED_DRIVER_ADDR_2, LED_DRIVER_SYNC_2);
-# endif
-# ifdef LED_DRIVER_ADDR_3
-# ifndef LED_DRIVER_SYNC_3
-# define LED_DRIVER_SYNC_3 0
-# endif
+# if defined(LED_DRIVER_ADDR_3)
+# if !defined(LED_DRIVER_SYNC_3)
+# define LED_DRIVER_SYNC_3 0
+# endif
IS31FL3733_init(LED_DRIVER_ADDR_3, LED_DRIVER_SYNC_3);
-# endif
-# ifdef LED_DRIVER_ADDR_4
-# ifndef LED_DRIVER_SYNC_4
-# define LED_DRIVER_SYNC_4 0
-# endif
+# if defined(LED_DRIVER_ADDR_4)
+# if !defined(LED_DRIVER_SYNC_4)
+# define LED_DRIVER_SYNC_4 0
+# endif
IS31FL3733_init(LED_DRIVER_ADDR_4, LED_DRIVER_SYNC_4);
+# endif
+# endif
# endif
# endif
for (int index = 0; index < DRIVER_LED_TOTAL; index++) {
-# ifdef IS31FL3731
+# if defined(IS31FL3731)
IS31FL3731_set_led_control_register(index, true);
-# else
+# elif defined(IS31FL3733)
IS31FL3733_set_led_control_register(index, true);
# endif
}
+
// This actually updates the LED drivers
-# ifdef IS31FL3731
-# ifdef LED_DRIVER_ADDR_1
+# if defined(IS31FL3731)
IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_1, 0);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_2, 1);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_3, 2);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
-# else
-# ifdef LED_DRIVER_ADDR_1
+
+# elif defined(IS31FL3733)
IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_1, 0);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_2, 1);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_3, 2);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
# endif
}
+# if defined(IS31FL3731)
static void flush(void) {
-# ifdef IS31FL3731
-# ifdef LED_DRIVER_ADDR_1
IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
-# else
-# ifdef LED_DRIVER_ADDR_1
+}
+
+const led_matrix_driver_t led_matrix_driver = {
+ .init = init,
+ .flush = flush,
+ .set_value = IS31FL3731_set_value,
+ .set_value_all = IS31FL3731_set_value_all,
+};
+
+# elif defined(IS31FL3733)
+static void flush(void) {
IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
-# endif
}
const led_matrix_driver_t led_matrix_driver = {
- .init = init,
+ .init = init,
.flush = flush,
-# ifdef IS31FL3731
- .set_value = IS31FL3731_set_value,
- .set_value_all = IS31FL3731_set_value_all,
-# else
.set_value = IS31FL3733_set_value,
.set_value_all = IS31FL3733_set_value_all,
-# endif
};
-
+# endif
#endif
diff --git a/quantum/led_matrix/led_matrix_legacy_enables.h b/quantum/led_matrix/led_matrix_legacy_enables.h
deleted file mode 100644
index 7738d2f34e..0000000000
--- a/quantum/led_matrix/led_matrix_legacy_enables.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Copyright 2021 QMK
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-// to-do: remove this
-
-#pragma once
-
-#ifndef DISABLE_LED_MATRIX_ALPHAS_MODS
-# define ENABLE_LED_MATRIX_ALPHAS_MODS
-#endif
-#ifndef DISABLE_LED_MATRIX_BREATHING
-# define ENABLE_LED_MATRIX_BREATHING
-#endif
-#ifndef DISABLE_LED_MATRIX_BAND
-# define ENABLE_LED_MATRIX_BAND
-#endif
-#ifndef DISABLE_LED_MATRIX_BAND_PINWHEEL
-# define ENABLE_LED_MATRIX_BAND_PINWHEEL
-#endif
-#ifndef DISABLE_LED_MATRIX_BAND_SPIRAL
-# define ENABLE_LED_MATRIX_BAND_SPIRAL
-#endif
-#ifndef DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
-# define ENABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
-#endif
-#ifndef DISABLE_LED_MATRIX_CYCLE_UP_DOWN
-# define ENABLE_LED_MATRIX_CYCLE_UP_DOWN
-#endif
-#ifndef DISABLE_LED_MATRIX_CYCLE_OUT_IN
-# define ENABLE_LED_MATRIX_CYCLE_OUT_IN
-#endif
-#ifndef DISABLE_LED_MATRIX_DUAL_BEACON
-# define ENABLE_LED_MATRIX_DUAL_BEACON
-#endif
-#if defined(LED_MATRIX_KEYREACTIVE_ENABLED)
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS
-# endif
-# ifndef DISABLE_LED_MATRIX_SPLASH
-# define ENABLE_LED_MATRIX_SPLASH
-# endif
-# ifndef DISABLE_LED_MATRIX_MULTISPLASH
-# define ENABLE_LED_MATRIX_MULTISPLASH
-# endif
-#endif
-#ifndef DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT
-# define ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT
-#endif
-#ifndef DISABLE_LED_MATRIX_WAVE_UP_DOWN
-# define ENABLE_LED_MATRIX_WAVE_UP_DOWN
-#endif
diff --git a/quantum/main.c b/quantum/main.c
index 2cbcd73d8f..6ed6b95741 100644
--- a/quantum/main.c
+++ b/quantum/main.c
@@ -19,8 +19,33 @@
void platform_setup(void);
void protocol_setup(void);
-void protocol_init(void);
-void protocol_task(void);
+void protocol_pre_init(void);
+void protocol_post_init(void);
+void protocol_pre_task(void);
+void protocol_post_task(void);
+
+// Bodge as refactoring this area sucks....
+void protocol_init(void) __attribute__((weak));
+void protocol_init(void) {
+ protocol_pre_init();
+
+ keyboard_init();
+
+ protocol_post_init();
+}
+
+void protocol_task(void) __attribute__((weak));
+void protocol_task(void) {
+ protocol_pre_task();
+
+ keyboard_task();
+
+ protocol_post_task();
+}
+
+#ifdef DEFERRED_EXEC_ENABLE
+void deferred_exec_task(void);
+#endif // DEFERRED_EXEC_ENABLE
/** \brief Main
*
@@ -30,12 +55,19 @@ int main(void) __attribute__((weak));
int main(void) {
platform_setup();
protocol_setup();
+ keyboard_setup();
protocol_init();
/* Main loop */
while (true) {
protocol_task();
+
+#ifdef DEFERRED_EXEC_ENABLE
+ // Run deferred executions
+ deferred_exec_task();
+#endif // DEFERRED_EXEC_ENABLE
+
housekeeping_task();
}
}
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 33586c431b..483d518ecc 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -69,7 +69,7 @@ uint8_t thisHand, thatHand;
// user-defined overridable functions
__attribute__((weak)) void matrix_init_pins(void);
__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
-__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
+__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter);
#ifdef SPLIT_KEYBOARD
__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }
__attribute__((weak)) void matrix_slave_scan_user(void) {}
@@ -113,10 +113,11 @@ __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[]
// Start with a clear matrix row
matrix_row_t current_row_value = 0;
- for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
+ matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
+ for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) {
pin_t pin = direct_pins[current_row][col_index];
if (pin != NO_PIN) {
- current_row_value |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
+ current_row_value |= readPin(pin) ? 0 : row_shifter;
}
}
@@ -169,11 +170,12 @@ __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[]
matrix_output_select_delay();
// For each col...
- for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
+ matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
+ for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) {
uint8_t pin_state = readMatrixPin(col_pins[col_index]);
// Populate the matrix row with the state of the col pin
- current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
+ current_row_value |= pin_state ? 0 : row_shifter;
}
// Unselect row
@@ -217,7 +219,7 @@ __attribute__((weak)) void matrix_init_pins(void) {
}
}
-__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
+__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter) {
bool key_pressed = false;
// Select col
@@ -231,11 +233,11 @@ __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[]
// Check row pin state
if (readMatrixPin(row_pins[row_index]) == 0) {
// Pin LO, set col bit
- current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
+ current_matrix[row_index] |= row_shifter;
key_pressed = true;
} else {
// Pin HI, clear col bit
- current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
+ current_matrix[row_index] &= ~row_shifter;
}
}
@@ -288,10 +290,8 @@ void matrix_init(void) {
matrix_init_pins();
// initialize matrix state: all keys off
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- raw_matrix[i] = 0;
- matrix[i] = 0;
- }
+ memset(matrix, 0, sizeof(matrix));
+ memset(raw_matrix, 0, sizeof(raw_matrix));
debounce_init(ROWS_PER_HAND);
@@ -312,24 +312,22 @@ __attribute__((weak)) bool transport_master_if_connected(matrix_row_t master_mat
bool matrix_post_scan(void) {
bool changed = false;
if (is_keyboard_master()) {
+ static bool last_connected = false;
matrix_row_t slave_matrix[ROWS_PER_HAND] = {0};
if (transport_master_if_connected(matrix + thisHand, slave_matrix)) {
- for (int i = 0; i < ROWS_PER_HAND; ++i) {
- if (matrix[thatHand + i] != slave_matrix[i]) {
- matrix[thatHand + i] = slave_matrix[i];
- changed = true;
- }
- }
- } else {
- // reset other half if disconnected
- for (int i = 0; i < ROWS_PER_HAND; ++i) {
- matrix[thatHand + i] = 0;
- slave_matrix[i] = 0;
- }
+ changed = memcmp(matrix + thatHand, slave_matrix, sizeof(slave_matrix)) != 0;
+ last_connected = true;
+ } else if (last_connected) {
+ // reset other half when disconnected
+ memset(slave_matrix, 0, sizeof(slave_matrix));
changed = true;
+
+ last_connected = false;
}
+ if (changed) memcpy(matrix + thatHand, slave_matrix, sizeof(slave_matrix));
+
matrix_scan_quantum();
} else {
transport_slave(matrix + thatHand, matrix + thisHand);
@@ -351,8 +349,9 @@ uint8_t matrix_scan(void) {
}
#elif (DIODE_DIRECTION == ROW2COL)
// Set col, read rows
- for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
- matrix_read_rows_on_col(curr_matrix, current_col);
+ matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
+ for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++, row_shifter <<= 1) {
+ matrix_read_rows_on_col(curr_matrix, current_col, row_shifter);
}
#endif
diff --git a/quantum/pointing_device.c b/quantum/pointing_device.c
index 09d889f697..2fefdb67b6 100644
--- a/quantum/pointing_device.c
+++ b/quantum/pointing_device.c
@@ -1,34 +1,57 @@
-/*
-Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdint.h>
-#include "report.h"
-#include "host.h"
-#include "timer.h"
-#include "print.h"
-#include "debug.h"
+/* Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com>
+ * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2021 Dasky (@daskygit)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#include "pointing_device.h"
+#include <string.h>
+#ifdef MOUSEKEY_ENABLE
+# include "mousekey.h"
+#endif
+#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
+# error More than one rotation selected. This is not supported.
+#endif
static report_mouse_t mouseReport = {};
-__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return (new.buttons != old.buttons) || (new.x&& new.x != old.x) || (new.y&& new.y != old.y) || (new.h&& new.h != old.h) || (new.v&& new.v != old.v); }
+extern const pointing_device_driver_t pointing_device_driver;
+
+__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return memcmp(&new, &old, sizeof(new)); }
+
+__attribute__((weak)) void pointing_device_init_kb(void) {}
+__attribute__((weak)) void pointing_device_init_user(void) {}
+__attribute__((weak)) report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) { return pointing_device_task_user(mouse_report); }
+__attribute__((weak)) report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { return mouse_report; }
+
+__attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) {
+ if (pressed) {
+ buttons |= 1 << (button);
+ } else {
+ buttons &= ~(1 << (button));
+ }
+ return buttons;
+}
__attribute__((weak)) void pointing_device_init(void) {
- // initialize device, if that needs to be done.
+ pointing_device_driver.init();
+#ifdef POINTING_DEVICE_MOTION_PIN
+ setPinInputHigh(POINTING_DEVICE_MOTION_PIN);
+#endif
+ pointing_device_init_kb();
+ pointing_device_init_user();
}
__attribute__((weak)) void pointing_device_send(void) {
@@ -43,20 +66,55 @@ __attribute__((weak)) void pointing_device_send(void) {
mouseReport.y = 0;
mouseReport.v = 0;
mouseReport.h = 0;
- old_report = mouseReport;
+
+ memcpy(&old_report, &mouseReport, sizeof(mouseReport));
}
__attribute__((weak)) void pointing_device_task(void) {
- // gather info and put it in:
- // mouseReport.x = 127 max -127 min
- // mouseReport.y = 127 max -127 min
- // mouseReport.v = 127 max -127 min (scroll vertical)
- // mouseReport.h = 127 max -127 min (scroll horizontal)
- // mouseReport.buttons = 0x1F (decimal 31, binary 00011111) max (bitmask for mouse buttons 1-5, 1 is rightmost, 5 is leftmost) 0x00 min
- // send the report
+ // Gather report info
+#ifdef POINTING_DEVICE_MOTION_PIN
+ if (!readPin(POINTING_DEVICE_MOTION_PIN))
+#endif
+ mouseReport = pointing_device_driver.get_report(mouseReport);
+
+ // Support rotation of the sensor data
+#if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270)
+ int8_t x = mouseReport.x, y = mouseReport.y;
+# if defined(POINTING_DEVICE_ROTATION_90)
+ mouseReport.x = y;
+ mouseReport.y = -x;
+# elif defined(POINTING_DEVICE_ROTATION_180)
+ mouseReport.x = -x;
+ mouseReport.y = -y;
+# elif defined(POINTING_DEVICE_ROTATION_270)
+ mouseReport.x = -y;
+ mouseReport.y = x;
+# else
+# error "How the heck did you get here?!"
+# endif
+#endif
+ // Support Inverting the X and Y Axises
+#if defined(POINTING_DEVICE_INVERT_X)
+ mouseReport.x = -mouseReport.x;
+#endif
+#if defined(POINTING_DEVICE_INVERT_Y)
+ mouseReport.y = -mouseReport.y;
+#endif
+
+ // allow kb to intercept and modify report
+ mouseReport = pointing_device_task_kb(mouseReport);
+ // combine with mouse report to ensure that the combined is sent correctly
+#ifdef MOUSEKEY_ENABLE
+ report_mouse_t mousekey_report = mousekey_get_report();
+ mouseReport.buttons = mouseReport.buttons | mousekey_report.buttons;
+#endif
pointing_device_send();
}
report_mouse_t pointing_device_get_report(void) { return mouseReport; }
void pointing_device_set_report(report_mouse_t newMouseReport) { mouseReport = newMouseReport; }
+
+uint16_t pointing_device_get_cpi(void) { return pointing_device_driver.get_cpi(); }
+
+void pointing_device_set_cpi(uint16_t cpi) { pointing_device_driver.set_cpi(cpi); }
diff --git a/quantum/pointing_device.h b/quantum/pointing_device.h
index 56a542d545..5106c26660 100644
--- a/quantum/pointing_device.h
+++ b/quantum/pointing_device.h
@@ -21,9 +21,68 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "host.h"
#include "report.h"
+#if defined(POINTING_DEVICE_DRIVER_adns5050)
+# include "drivers/sensors/adns5050.h"
+#elif defined(POINTING_DEVICE_DRIVER_adns9800)
+# include "spi_master.h"
+# include "drivers/sensors/adns9800.h"
+#elif defined(POINTING_DEVICE_DRIVER_analog_joystick)
+# include "analog.h"
+# include "drivers/sensors/analog_joystick.h"
+#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
+# include "drivers/sensors/cirque_pinnacle.h"
+#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
+# include "i2c_master.h"
+# include "drivers/sensors/pimoroni_trackball.h"
+// support for legacy pimoroni defines
+# ifdef PIMORONI_TRACKBALL_INVERT_X
+# define POINTING_DEVICE_INVERT_X
+# endif
+# ifdef PIMORONI_TRACKBALL_INVERT_Y
+# define POINTING_DEVICE_INVERT_Y
+# endif
+# ifdef PIMORONI_TRACKBALL_ROTATE
+# define POINTING_DEVICE_ROTATION_90
+# endif
+#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
+# include "spi_master.h"
+# include "drivers/sensors/pmw3360.h"
+#else
+void pointing_device_driver_init(void);
+report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report);
+uint16_t pointing_device_driver_get_cpi(void);
+void pointing_device_driver_set_cpi(uint16_t cpi);
+#endif
+
+typedef struct {
+ void (*init)(void);
+ report_mouse_t (*get_report)(report_mouse_t mouse_report);
+ void (*set_cpi)(uint16_t);
+ uint16_t (*get_cpi)(void);
+} pointing_device_driver_t;
+
+typedef enum {
+ POINTING_DEVICE_BUTTON1,
+ POINTING_DEVICE_BUTTON2,
+ POINTING_DEVICE_BUTTON3,
+ POINTING_DEVICE_BUTTON4,
+ POINTING_DEVICE_BUTTON5,
+ POINTING_DEVICE_BUTTON6,
+ POINTING_DEVICE_BUTTON7,
+ POINTING_DEVICE_BUTTON8,
+} pointing_device_buttons_t;
+
void pointing_device_init(void);
void pointing_device_task(void);
void pointing_device_send(void);
report_mouse_t pointing_device_get_report(void);
void pointing_device_set_report(report_mouse_t newMouseReport);
bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old);
+uint16_t pointing_device_get_cpi(void);
+void pointing_device_set_cpi(uint16_t cpi);
+
+void pointing_device_init_kb(void);
+void pointing_device_init_user(void);
+report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report);
+report_mouse_t pointing_device_task_user(report_mouse_t mouse_report);
+uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button);
diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c
new file mode 100644
index 0000000000..9ad5e76ba6
--- /dev/null
+++ b/quantum/pointing_device_drivers.c
@@ -0,0 +1,262 @@
+/* Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com>
+ * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2021 Dasky (@daskygit)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pointing_device.h"
+#include "debug.h"
+#include "wait.h"
+#include "timer.h"
+#include <stddef.h>
+
+// hid mouse reports cannot exceed -127 to 127, so constrain to that value
+#define constrain_hid(amt) ((amt) < -127 ? -127 : ((amt) > 127 ? 127 : (amt)))
+
+// get_report functions should probably be moved to their respective drivers.
+#if defined(POINTING_DEVICE_DRIVER_adns5050)
+report_mouse_t adns5050_get_report(report_mouse_t mouse_report) {
+ report_adns5050_t data = adns5050_read_burst();
+
+ if (data.dx != 0 || data.dy != 0) {
+# ifdef CONSOLE_ENABLE
+ if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy);
+# endif
+
+ mouse_report.x = data.dx;
+ mouse_report.y = data.dy;
+ }
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = adns5050_init,
+ .get_report = adns5050_get_report,
+ .set_cpi = adns5050_set_cpi,
+ .get_cpi = adns5050_get_cpi,
+};
+// clang-format on
+#elif defined(POINTING_DEVICE_DRIVER_adns9800)
+
+report_mouse_t adns9800_get_report_driver(report_mouse_t mouse_report) {
+ report_adns9800_t sensor_report = adns9800_get_report();
+
+ int8_t clamped_x = constrain_hid(sensor_report.x);
+ int8_t clamped_y = constrain_hid(sensor_report.y);
+
+ mouse_report.x = clamped_x;
+ mouse_report.y = clamped_y;
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = adns9800_init,
+ .get_report = adns9800_get_report_driver,
+ .set_cpi = adns9800_set_cpi,
+ .get_cpi = adns9800_get_cpi
+};
+// clang-format on
+#elif defined(POINTING_DEVICE_DRIVER_analog_joystick)
+report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) {
+ report_analog_joystick_t data = analog_joystick_read();
+
+# ifdef CONSOLE_ENABLE
+ if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
+# endif
+
+ mouse_report.x = data.x;
+ mouse_report.y = data.y;
+
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, data.button, POINTING_DEVICE_BUTTON1);
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = analog_joystick_init,
+ .get_report = analog_joystick_get_report,
+ .set_cpi = NULL,
+ .get_cpi = NULL
+};
+// clang-format on
+#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
+# ifndef CIRQUE_PINNACLE_TAPPING_TERM
+# ifdef TAPPING_TERM_PER_KEY
+# include "action.h"
+# include "action_tapping.h"
+# define CIRQUE_PINNACLE_TAPPING_TERM get_tapping_term(KC_BTN1, NULL)
+# else
+# ifdef TAPPING_TERM
+# define CIRQUE_PINNACLE_TAPPING_TERM TAPPING_TERM
+# else
+# define CIRQUE_PINNACLE_TAPPING_TERM 200
+# endif
+# endif
+# endif
+# ifndef CIRQUE_PINNACLE_TOUCH_DEBOUNCE
+# define CIRQUE_PINNACLE_TOUCH_DEBOUNCE (CIRQUE_PINNACLE_TAPPING_TERM * 8)
+# endif
+
+report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
+ pinnacle_data_t touchData = cirque_pinnacle_read_data();
+ static uint16_t x = 0, y = 0, mouse_timer = 0;
+ int8_t report_x = 0, report_y = 0;
+ static bool is_z_down = false;
+
+ cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); // Scale coordinates to arbitrary X, Y resolution
+
+ if (x && y && touchData.xValue && touchData.yValue) {
+ report_x = (int8_t)(touchData.xValue - x);
+ report_y = (int8_t)(touchData.yValue - y);
+ }
+ x = touchData.xValue;
+ y = touchData.yValue;
+
+ if ((bool)touchData.zValue != is_z_down) {
+ is_z_down = (bool)touchData.zValue;
+ if (!touchData.zValue) {
+ if (timer_elapsed(mouse_timer) < CIRQUE_PINNACLE_TAPPING_TERM && mouse_timer != 0) {
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
+ pointing_device_set_report(mouse_report);
+ pointing_device_send();
+# if TAP_CODE_DELAY > 0
+ wait_ms(TAP_CODE_DELAY);
+# endif
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
+ pointing_device_set_report(mouse_report);
+ pointing_device_send();
+ }
+ }
+ mouse_timer = timer_read();
+ }
+ if (timer_elapsed(mouse_timer) > (CIRQUE_PINNACLE_TOUCH_DEBOUNCE)) {
+ mouse_timer = 0;
+ }
+ mouse_report.x = report_x;
+ mouse_report.y = report_y;
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = cirque_pinnacle_init,
+ .get_report = cirque_pinnacle_get_report,
+ .set_cpi = cirque_pinnacle_set_scale,
+ .get_cpi = cirque_pinnacle_get_scale
+};
+// clang-format on
+
+#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
+report_mouse_t pimorono_trackball_get_report(report_mouse_t mouse_report) {
+ static fast_timer_t throttle = 0;
+ static uint16_t debounce = 0;
+ static uint8_t error_count = 0;
+ pimoroni_data_t pimoroni_data = {0};
+ static int16_t x_offset = 0, y_offset = 0;
+
+ if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) {
+ i2c_status_t status = read_pimoroni_trackball(&pimoroni_data);
+
+ if (status == I2C_STATUS_SUCCESS) {
+ error_count = 0;
+
+ if (!(pimoroni_data.click & 128)) {
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
+ if (!debounce) {
+ x_offset += pimoroni_trackball_get_offsets(pimoroni_data.right, pimoroni_data.left, PIMORONI_TRACKBALL_SCALE);
+ y_offset += pimoroni_trackball_get_offsets(pimoroni_data.down, pimoroni_data.up, PIMORONI_TRACKBALL_SCALE);
+ pimoroni_trackball_adapt_values(&mouse_report.x, &x_offset);
+ pimoroni_trackball_adapt_values(&mouse_report.y, &y_offset);
+ } else {
+ debounce--;
+ }
+ } else {
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
+ debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES;
+ }
+ } else {
+ error_count++;
+ }
+ throttle = timer_read_fast();
+ }
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = pimironi_trackball_device_init,
+ .get_report = pimorono_trackball_get_report,
+ .set_cpi = NULL,
+ .get_cpi = NULL
+};
+// clang-format on
+#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
+
+static void init(void) { pmw3360_init(); }
+
+report_mouse_t pmw3360_get_report(report_mouse_t mouse_report) {
+ report_pmw3360_t data = pmw3360_read_burst();
+ static uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
+
+ if (data.isOnSurface && data.isMotion) {
+ // Reset timer if stopped moving
+ if (!data.isMotion) {
+ if (MotionStart != 0) MotionStart = 0;
+ return mouse_report;
+ }
+
+ // Set timer if new motion
+ if ((MotionStart == 0) && data.isMotion) {
+# ifdef CONSOLE_ENABLE
+ if (debug_mouse) dprintf("Starting motion.\n");
+# endif
+ MotionStart = timer_read();
+ }
+ mouse_report.x = constrain_hid(data.dx);
+ mouse_report.y = constrain_hid(data.dy);
+ }
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = init,
+ .get_report = pmw3360_get_report,
+ .set_cpi = pmw3360_set_cpi,
+ .get_cpi = pmw3360_get_cpi
+};
+// clang-format on
+#else
+__attribute__((weak)) void pointing_device_driver_init(void) {}
+__attribute__((weak)) report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) { return mouse_report; }
+__attribute__((weak)) uint16_t pointing_device_driver_get_cpi(void) { return 0; }
+__attribute__((weak)) void pointing_device_driver_set_cpi(uint16_t cpi) {}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = pointing_device_driver_init,
+ .get_report = pointing_device_driver_get_report,
+ .get_cpi = pointing_device_driver_get_cpi,
+ .set_cpi = pointing_device_driver_set_cpi
+};
+// clang-format on
+#endif
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
index 5d8de56a37..bbc6367ff1 100644
--- a/quantum/process_keycode/process_auto_shift.c
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -18,14 +18,33 @@
# include <stdbool.h>
# include <stdio.h>
-
# include "process_auto_shift.h"
-static uint16_t autoshift_time = 0;
-static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
-static uint16_t autoshift_lastkey = KC_NO;
+# ifndef AUTO_SHIFT_DISABLED_AT_STARTUP
+# define AUTO_SHIFT_STARTUP_STATE true /* enabled */
+# else
+# define AUTO_SHIFT_STARTUP_STATE false /* disabled */
+# endif
+
+// Stores the last Auto Shift key's up or down time, for evaluation or keyrepeat.
+static uint16_t autoshift_time = 0;
+# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+// Stores the last key's up or down time, to replace autoshift_time so that Tap Hold times are accurate.
+static uint16_t retroshift_time = 0;
+// Stores a possibly Retro Shift key's up or down time, as retroshift_time needs
+// to be set before the Retro Shift key is evaluated if it is interrupted by an
+// Auto Shifted key.
+static uint16_t last_retroshift_time;
+# endif
+static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
+static uint16_t autoshift_lastkey = KC_NO;
+static keyrecord_t autoshift_lastrecord;
+// Keys take 8 bits if modifiers are excluded. This records the shift state
+// when pressed for each key, so that can be passed to the release function
+// and it knows which key needs to be released (if shifted is different base).
+static uint16_t autoshift_shift_states[((1 << 8) + 15) / 16];
static struct {
- // Whether autoshift is enabled.
+ // Whether Auto Shift 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.
@@ -34,43 +53,157 @@ static struct {
bool in_progress : 1;
// Whether the auto-shifted keypress has been registered.
bool holding_shift : 1;
-} autoshift_flags = {true, false, false, false};
+ // Whether the user is holding a shift and we removed it.
+ bool cancelling_lshift : 1;
+ bool cancelling_rshift : 1;
+ // clang-format wants to remove the true for some reason.
+ // clang-format off
+} autoshift_flags = {AUTO_SHIFT_STARTUP_STATE, false, false, false, false, false};
+// clang-format on
+
+/** \brief Called on physical press, returns whether key should be added to Auto Shift */
+__attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { return false; }
+
+/** \brief Called on physical press, returns whether is Auto Shift key */
+__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+# ifndef NO_AUTO_SHIFT_ALPHA
+ case AUTO_SHIFT_ALPHA:
+# endif
+# ifndef NO_AUTO_SHIFT_NUMERIC
+ case AUTO_SHIFT_NUMERIC:
+# endif
+# ifndef NO_AUTO_SHIFT_SPECIAL
+ case AUTO_SHIFT_SPECIAL:
+# endif
+ return true;
+ }
+ return get_custom_auto_shifted_key(keycode, record);
+}
+
+/** \brief Called to check whether defines should apply if PER_KEY is set for it */
+__attribute__((weak)) bool get_auto_shift_repeat(uint16_t keycode, keyrecord_t *record) { return true; }
+__attribute__((weak)) bool get_auto_shift_no_auto_repeat(uint16_t keycode, keyrecord_t *record) { return true; }
+
+/** \brief Called when an Auto Shift key needs to be pressed */
+__attribute__((weak)) void autoshift_press_user(uint16_t keycode, bool shifted, keyrecord_t *record) {
+ if (shifted) {
+ add_weak_mods(MOD_BIT(KC_LSFT));
+ }
+ register_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode);
+}
+
+/** \brief Called when an Auto Shift key needs to be released */
+__attribute__((weak)) void autoshift_release_user(uint16_t keycode, bool shifted, keyrecord_t *record) { unregister_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode); }
+
+/** \brief Sets the shift state to use when keyrepeating, required by custom shifts */
+void set_autoshift_shift_state(uint16_t keycode, bool shifted) {
+ keycode = keycode & 0xFF;
+ if (shifted) {
+ autoshift_shift_states[keycode / 16] |= (uint16_t)1 << keycode % 16;
+ } else {
+ autoshift_shift_states[keycode / 16] &= ~((uint16_t)1 << keycode % 16);
+ }
+}
+
+/** \brief Gets the shift state to use when keyrepeating, required by custom shifts */
+bool get_autoshift_shift_state(uint16_t keycode) {
+ keycode = keycode & 0xFF;
+ return (autoshift_shift_states[keycode / 16] & (uint16_t)1 << keycode % 16) != (uint16_t)0;
+}
+
+/** \brief Restores the shift key if it was cancelled by Auto Shift */
+static void autoshift_flush_shift(void) {
+ autoshift_flags.holding_shift = false;
+ del_weak_mods(MOD_BIT(KC_LSFT));
+ if (autoshift_flags.cancelling_lshift) {
+ autoshift_flags.cancelling_lshift = false;
+ add_mods(MOD_BIT(KC_LSFT));
+ }
+ if (autoshift_flags.cancelling_rshift) {
+ autoshift_flags.cancelling_rshift = false;
+ add_mods(MOD_BIT(KC_RSFT));
+ }
+ send_keyboard_report();
+}
/** \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;
- }
-
+ // clang-format off
+ if ((get_mods()
+# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
+ | get_oneshot_mods()
+# endif
+ ) & (~MOD_BIT(KC_LSFT))
+ ) {
+ // clang-format on
+ // Prevents keyrepeating unshifted value of key after using it in a key combo.
+ autoshift_lastkey = KC_NO;
# ifndef AUTO_SHIFT_MODIFIERS
- if (get_mods()) {
- return true;
- }
+ // We can't return true here anymore because custom unshifted values are
+ // possible and there's no good way to tell whether the press returned
+ // true upon release.
+ set_autoshift_shift_state(keycode, false);
+ autoshift_press_user(keycode, false, record);
+# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
+ set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT)));
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+# endif
+ return false;
# 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) {
+ }
+
+ // Store record to be sent to user functions if there's no release record then.
+ autoshift_lastrecord = *record;
+ autoshift_lastrecord.event.pressed = false;
+ autoshift_lastrecord.event.time = 0;
+ // clang-format off
+# if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)
+ if (keycode == autoshift_lastkey &&
+# ifdef AUTO_SHIFT_REPEAT_PER_KEY
+ get_auto_shift_repeat(autoshift_lastkey, record) &&
# 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;
+# if !defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY)
+ (
+ !autoshift_flags.lastshifted
+# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY
+ || get_auto_shift_no_auto_repeat(autoshift_lastkey, record)
+# endif
+ ) &&
+# endif
+ TIMER_DIFF_16(now, autoshift_time) <
+# ifdef TAPPING_TERM_PER_KEY
+ get_tapping_term(autoshift_lastkey, record)
+# else
+ TAPPING_TERM
+# endif
+ ) {
+ // clang-format on
+ // Allow a tap-then-hold for keyrepeat.
+ if (get_mods() & MOD_BIT(KC_LSFT)) {
+ autoshift_flags.cancelling_lshift = true;
+ del_mods(MOD_BIT(KC_LSFT));
+ }
+ if (get_mods() & MOD_BIT(KC_RSFT)) {
+ autoshift_flags.cancelling_rshift = true;
+ del_mods(MOD_BIT(KC_RSFT));
}
-# ifndef AUTO_SHIFT_NO_AUTO_REPEAT
+ // autoshift_shift_state doesn't need to be changed.
+ autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record);
+ return false;
}
-# endif
# endif
+ // Use physical shift state of press event to be more like normal typing.
+# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
+ autoshift_flags.lastshifted = (get_mods() | get_oneshot_mods()) & MOD_BIT(KC_LSFT);
+ set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT)));
+# else
+ autoshift_flags.lastshifted = get_mods() & MOD_BIT(KC_LSFT);
+# endif
// Record the keycode so we can simulate it later.
autoshift_lastkey = keycode;
autoshift_time = now;
@@ -84,51 +217,70 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)
/** \brief Registers an autoshiftable key under the right conditions
*
- * If the autoshift delay has elapsed, register a shift and the key.
+ * If autoshift_timeout has elapsed, register a shift and the key.
*
- * If the autoshift key is released before the delay has elapsed, register the
+ * If the Auto Shift key is released before the delay has elapsed, register the
* key without a shift.
+ *
+ * Called on key down with keycode=KC_NO, auto-shifted key up, and timeout.
*/
-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) {
+static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, keyrecord_t *record) {
+ if (autoshift_flags.in_progress && (keycode == autoshift_lastkey || keycode == KC_NO)) {
// 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 {
- // 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;
- }
+ // clang-format off
+ autoshift_flags.lastshifted =
+ autoshift_flags.lastshifted
+ || TIMER_DIFF_16(now, autoshift_time) >=
+# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY
+ get_autoshift_timeout(autoshift_lastkey, record)
+# else
+ autoshift_timeout
# endif
+ ;
+ // clang-format on
+ set_autoshift_shift_state(autoshift_lastkey, autoshift_flags.lastshifted);
+ if (get_mods() & MOD_BIT(KC_LSFT)) {
+ autoshift_flags.cancelling_lshift = true;
+ del_mods(MOD_BIT(KC_LSFT));
+ }
+ if (get_mods() & MOD_BIT(KC_RSFT)) {
+ autoshift_flags.cancelling_rshift = true;
+ del_mods(MOD_BIT(KC_RSFT));
}
+ autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record);
+ // clang-format off
+# if (defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)) && (!defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY))
+ if (matrix_trigger
+# ifdef AUTO_SHIFT_REPEAT_PER_KEY
+ && get_auto_shift_repeat(autoshift_lastkey, record)
+# endif
+# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY
+ && !get_auto_shift_no_auto_repeat(autoshift_lastkey, record)
+# endif
+ ) {
+ // Prevents release.
+ return;
+ }
+# endif
+ // clang-format on
# if TAP_CODE_DELAY > 0
wait_ms(TAP_CODE_DELAY);
# endif
- unregister_code(autoshift_lastkey);
- del_weak_mods(MOD_BIT(KC_LSFT));
+
+ autoshift_release_user(autoshift_lastkey, autoshift_flags.lastshifted, record);
+ autoshift_flush_shift();
} else {
// Release after keyrepeat.
- unregister_code(keycode);
+ autoshift_release_user(keycode, get_autoshift_shift_state(keycode), record);
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));
+ // pressed. That prevents 'aaaaBBBB' then releasing a from unshifting
+ // later 'B's (if 'B' wasn't auto-shiftable).
+ autoshift_flush_shift();
}
}
- send_keyboard_report(); // del_weak_mods doesn't send one.
// Roll the autoshift_time forward for detecting tap-and-hold.
autoshift_time = now;
}
@@ -141,24 +293,29 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) {
*/
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);
+ const uint16_t now = timer_read();
+ if (TIMER_DIFF_16(now, autoshift_time) >=
+# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY
+ get_autoshift_timeout(autoshift_lastkey, &autoshift_lastrecord)
+# else
+ autoshift_timeout
+# endif
+ ) {
+ autoshift_end(autoshift_lastkey, now, true, &autoshift_lastrecord);
}
}
}
void autoshift_toggle(void) {
autoshift_flags.enabled = !autoshift_flags.enabled;
- del_weak_mods(MOD_BIT(KC_LSFT));
+ autoshift_flush_shift();
}
void autoshift_enable(void) { autoshift_flags.enabled = true; }
void autoshift_disable(void) {
autoshift_flags.enabled = false;
- del_weak_mods(MOD_BIT(KC_LSFT));
+ autoshift_flush_shift();
}
# ifndef AUTO_SHIFT_NO_SETUP
@@ -173,78 +330,158 @@ void autoshift_timer_report(void) {
bool get_autoshift_state(void) { return autoshift_flags.enabled; }
-uint16_t get_autoshift_timeout(void) { return autoshift_timeout; }
+uint16_t get_generic_autoshift_timeout() { return autoshift_timeout; }
+__attribute__((weak)) uint16_t get_autoshift_timeout(uint16_t keycode, keyrecord_t *record) { return autoshift_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();
+ // clang-format off
+ const uint16_t now =
+# if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING)
+ timer_read()
+# else
+ (record->event.pressed) ? retroshift_time : timer_read()
+# endif
+ ;
+ // clang-format on
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);
+ // Evaluate previous key if there is one.
+ autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
}
- // For pressing another key while keyrepeating shifted autoshift.
- del_weak_mods(MOD_BIT(KC_LSFT));
switch (keycode) {
case KC_ASTG:
autoshift_toggle();
- return true;
+ break;
case KC_ASON:
autoshift_enable();
- return true;
+ break;
case KC_ASOFF:
autoshift_disable();
- return true;
+ break;
# ifndef AUTO_SHIFT_NO_SETUP
case KC_ASUP:
autoshift_timeout += 5;
- return true;
+ break;
case KC_ASDN:
autoshift_timeout -= 5;
- return true;
-
+ break;
case KC_ASRP:
autoshift_timer_report();
- return true;
+ break;
# endif
}
+ // If Retro Shift is disabled, possible custom actions shouldn't happen.
+ // clang-format off
+ if (IS_RETRO(keycode)
+# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+ // Not tapped or #defines mean that rolls should use hold action.
+ && (
+ record->tap.count == 0
+# ifdef RETRO_TAPPING_PER_KEY
+ || !get_retro_tapping(keycode, record)
+# endif
+ || (record->tap.interrupted && (IS_LT(keycode)
+# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
+# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
+ ? get_hold_on_other_key_press(keycode, record)
+# else
+ ? true
+# endif
+# else
+ ? false
+# endif
+# if defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
+# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
+ : !get_ignore_mod_tap_interrupt(keycode, record)
+# else
+ : false
+# endif
+# else
+ : true
+# endif
+ ))
+ )
+# endif
+ ) {
+ // clang-format on
+ autoshift_lastkey = KC_NO;
+ return true;
+ }
+ } else {
+ if (keycode == KC_LSFT) {
+ autoshift_flags.cancelling_lshift = false;
+ } else if (keycode == KC_RSFT) {
+ autoshift_flags.cancelling_rshift = false;
+ }
+ // Same as above (for pressed), additional checks are not needed because
+ // tap.count gets set to 0 in process_action
+ // clang-format off
+ else if (IS_RETRO(keycode)
+# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+ && (
+ record->tap.count == 0
+# ifdef RETRO_TAPPING_PER_KEY
+ || !get_retro_tapping(keycode, record)
+# endif
+ )
+# endif
+ ) {
+ // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set.
+# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
+ if (autoshift_flags.in_progress
+# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
+ && !get_ignore_mod_tap_interrupt(keycode, record)
+# endif
+ ) {
+ autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
+ }
+# endif
+ // clang-format on
+ return true;
+ }
+ }
+
+ if (!autoshift_flags.enabled) {
+ return true;
}
if (get_auto_shifted_key(keycode, record)) {
if (record->event.pressed) {
return autoshift_press(keycode, now, record);
} else {
- autoshift_end(keycode, now, false);
+ autoshift_end(keycode, now, false, record);
return false;
}
}
+
+ // Prevent keyrepeating of older keys upon non-AS key event.
+ // Not commented at above returns but they serve the same function.
+ if (record->event.pressed) {
+ autoshift_lastkey = KC_NO;
+ }
return true;
}
-__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
- switch (keycode) {
-# ifndef NO_AUTO_SHIFT_ALPHA
- case KC_A ... KC_Z:
-# endif
-# ifndef NO_AUTO_SHIFT_NUMERIC
- 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
- return true;
+# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+// Called to record time before possible delays by action_tapping_process.
+void retroshift_poll_time(keyevent_t *event) {
+ last_retroshift_time = retroshift_time;
+ retroshift_time = timer_read();
+}
+// Used to swap the times of Retro Shifted key and Auto Shift key that interrupted it.
+void retroshift_swap_times() {
+ if (last_retroshift_time != 0 && autoshift_flags.in_progress) {
+ uint16_t temp = retroshift_time;
+ retroshift_time = last_retroshift_time;
+ last_retroshift_time = temp;
}
- return false;
}
+# endif
#endif
diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h
index 00a9ab036f..ac6a143746 100644
--- a/quantum/process_keycode/process_auto_shift.h
+++ b/quantum/process_keycode/process_auto_shift.h
@@ -22,13 +22,31 @@
# define AUTO_SHIFT_TIMEOUT 175
#endif
+#define IS_LT(kc) ((kc) >= QK_LAYER_TAP && (kc) <= QK_LAYER_TAP_MAX)
+#define IS_MT(kc) ((kc) >= QK_MOD_TAP && (kc) <= QK_MOD_TAP_MAX)
+#define IS_RETRO(kc) (IS_MT(kc) || IS_LT(kc))
+#define DO_GET_AUTOSHIFT_TIMEOUT(keycode, record, ...) record
+// clang-format off
+#define AUTO_SHIFT_ALPHA KC_A ... KC_Z
+#define AUTO_SHIFT_NUMERIC KC_1 ... KC_0
+#define AUTO_SHIFT_SPECIAL \
+ KC_TAB: \
+ case KC_MINUS ... KC_SLASH: \
+ case KC_NONUS_BSLASH
+// clang-format on
+
bool process_auto_shift(uint16_t keycode, keyrecord_t *record);
+void retroshift_poll_time(keyevent_t *event);
+void retroshift_swap_times(void);
void autoshift_enable(void);
void autoshift_disable(void);
void autoshift_toggle(void);
bool get_autoshift_state(void);
-uint16_t get_autoshift_timeout(void);
+uint16_t get_generic_autoshift_timeout(void);
+// clang-format off
+uint16_t (get_autoshift_timeout)(uint16_t keycode, keyrecord_t *record);
void set_autoshift_timeout(uint16_t timeout);
void autoshift_matrix_scan(void);
-bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
+bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
+// clang-format on
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c
index e8661839c7..a050161edf 100644
--- a/quantum/process_keycode/process_combo.c
+++ b/quantum/process_keycode/process_combo.c
@@ -18,10 +18,9 @@
#include "process_combo.h"
#include "action_tapping.h"
-
#ifdef COMBO_COUNT
-__attribute__((weak)) combo_t key_combos[COMBO_COUNT];
-uint16_t COMBO_LEN = COMBO_COUNT;
+__attribute__((weak)) combo_t key_combos[COMBO_COUNT];
+uint16_t COMBO_LEN = COMBO_COUNT;
#else
extern combo_t key_combos[];
extern uint16_t COMBO_LEN;
@@ -46,64 +45,86 @@ __attribute__((weak)) bool process_combo_key_release(uint16_t combo_index, combo
#endif
#ifndef COMBO_NO_TIMER
-static uint16_t timer = 0;
+static uint16_t timer = 0;
#endif
-static bool b_combo_enable = true; // defaults to enabled
-static uint16_t longest_term = 0;
+static bool b_combo_enable = true; // defaults to enabled
+static uint16_t longest_term = 0;
typedef struct {
keyrecord_t record;
- uint16_t combo_index;
- uint16_t keycode;
+ uint16_t combo_index;
+ uint16_t keycode;
} queued_record_t;
-static uint8_t key_buffer_size = 0;
+static uint8_t key_buffer_size = 0;
static queued_record_t key_buffer[COMBO_KEY_BUFFER_LENGTH];
typedef struct {
uint16_t combo_index;
} queued_combo_t;
-static uint8_t combo_buffer_write= 0;
-static uint8_t combo_buffer_read = 0;
+static uint8_t combo_buffer_write = 0;
+static uint8_t combo_buffer_read = 0;
static queued_combo_t combo_buffer[COMBO_BUFFER_LENGTH];
#define INCREMENT_MOD(i) i = (i + 1) % COMBO_BUFFER_LENGTH
-#define COMBO_KEY_POS ((keypos_t){.col=254, .row=254})
-
+#define COMBO_KEY_POS ((keypos_t){.col = 254, .row = 254})
#ifndef EXTRA_SHORT_COMBOS
/* flags are their own elements in combo_t struct. */
-# define COMBO_ACTIVE(combo) (combo->active)
+# define COMBO_ACTIVE(combo) (combo->active)
# define COMBO_DISABLED(combo) (combo->disabled)
-# define COMBO_STATE(combo) (combo->state)
-
-# define ACTIVATE_COMBO(combo) do {combo->active = true;}while(0)
-# define DEACTIVATE_COMBO(combo) do {combo->active = false;}while(0)
-# define DISABLE_COMBO(combo) do {combo->disabled = true;}while(0)
-# define RESET_COMBO_STATE(combo) do { \
- combo->disabled = false; \
- combo->state = 0; \
-}while(0)
+# define COMBO_STATE(combo) (combo->state)
+
+# define ACTIVATE_COMBO(combo) \
+ do { \
+ combo->active = true; \
+ } while (0)
+# define DEACTIVATE_COMBO(combo) \
+ do { \
+ combo->active = false; \
+ } while (0)
+# define DISABLE_COMBO(combo) \
+ do { \
+ combo->disabled = true; \
+ } while (0)
+# define RESET_COMBO_STATE(combo) \
+ do { \
+ combo->disabled = false; \
+ combo->state = 0; \
+ } while (0)
#else
/* flags are at the two high bits of state. */
-# define COMBO_ACTIVE(combo) (combo->state & 0x80)
+# define COMBO_ACTIVE(combo) (combo->state & 0x80)
# define COMBO_DISABLED(combo) (combo->state & 0x40)
-# define COMBO_STATE(combo) (combo->state & 0x3F)
-
-# define ACTIVATE_COMBO(combo) do {combo->state |= 0x80;}while(0)
-# define DEACTIVATE_COMBO(combo) do {combo->state &= ~0x80;}while(0)
-# define DISABLE_COMBO(combo) do {combo->state |= 0x40;}while(0)
-# define RESET_COMBO_STATE(combo) do {combo->state &= ~0x7F;}while(0)
+# define COMBO_STATE(combo) (combo->state & 0x3F)
+
+# define ACTIVATE_COMBO(combo) \
+ do { \
+ combo->state |= 0x80; \
+ } while (0)
+# define DEACTIVATE_COMBO(combo) \
+ do { \
+ combo->state &= ~0x80; \
+ } while (0)
+# define DISABLE_COMBO(combo) \
+ do { \
+ combo->state |= 0x40; \
+ } while (0)
+# define RESET_COMBO_STATE(combo) \
+ do { \
+ combo->state &= ~0x7F; \
+ } while (0)
#endif
static inline void release_combo(uint16_t combo_index, combo_t *combo) {
if (combo->keycode) {
keyrecord_t record = {
- .event = {
- .key = COMBO_KEY_POS,
- .time = timer_read()|1,
- .pressed = false,
- },
+ .event =
+ {
+ .key = COMBO_KEY_POS,
+ .time = timer_read() | 1,
+ .pressed = false,
+ },
.keycode = combo->keycode,
};
#ifndef NO_ACTION_TAPPING
@@ -123,18 +144,17 @@ static inline bool _get_combo_must_hold(uint16_t combo_index, combo_t *combo) {
#elif defined(COMBO_MUST_HOLD_PER_COMBO)
return get_combo_must_hold(combo_index, combo);
#elif defined(COMBO_MUST_HOLD_MODS)
- return (KEYCODE_IS_MOD(combo->keycode) ||
- (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX));
+ return (KEYCODE_IS_MOD(combo->keycode) || (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX));
#endif
return false;
}
-static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo ) {
+static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo) {
if (_get_combo_must_hold(combo_index, combo)
#ifdef COMBO_MUST_TAP_PER_COMBO
- || get_combo_must_tap(combo_index, combo)
+ || get_combo_must_tap(combo_index, combo)
#endif
- ) {
+ ) {
if (longest_term < COMBO_HOLD_TERM) {
return COMBO_HOLD_TERM;
}
@@ -144,9 +164,8 @@ static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo ) {
}
static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) {
-
#if defined(COMBO_TERM_PER_COMBO)
- return get_combo_term(combo_index, combo);
+ return get_combo_term(combo_index, combo);
#endif
return COMBO_TERM;
@@ -154,7 +173,7 @@ static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) {
void clear_combos(void) {
uint16_t index = 0;
- longest_term = 0;
+ longest_term = 0;
for (index = 0; index < COMBO_LEN; ++index) {
combo_t *combo = &key_combos[index];
if (!COMBO_ACTIVE(combo)) {
@@ -175,7 +194,7 @@ static inline void dump_key_buffer(void) {
key_buffer_next = key_buffer_i + 1;
queued_record_t *qrecord = &key_buffer[key_buffer_i];
- keyrecord_t *record = &qrecord->record;
+ keyrecord_t * record = &qrecord->record;
if (IS_NOEVENT(record->event)) {
continue;
@@ -185,9 +204,9 @@ static inline void dump_key_buffer(void) {
process_combo_event(qrecord->combo_index, true);
} else {
#ifndef NO_ACTION_TAPPING
- action_tapping_process(*record);
+ action_tapping_process(*record);
#else
- process_record(record);
+ process_record(record);
#endif
}
record->event.time = 0;
@@ -242,7 +261,9 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
/* Apply combo's result keycode to the last chord key of the combo and
* disable the other keys. */
- if (COMBO_DISABLED(combo)) { return; }
+ if (COMBO_DISABLED(combo)) {
+ return;
+ }
// state to check against so we find the last key of the combo from the buffer
#if defined(EXTRA_EXTRA_LONG_COMBOS)
@@ -254,12 +275,11 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
#endif
for (uint8_t key_buffer_i = 0; key_buffer_i < key_buffer_size; key_buffer_i++) {
-
queued_record_t *qrecord = &key_buffer[key_buffer_i];
- keyrecord_t *record = &qrecord->record;
- uint16_t keycode = qrecord->keycode;
+ keyrecord_t * record = &qrecord->record;
+ uint16_t keycode = qrecord->keycode;
- uint8_t key_count = 0;
+ uint8_t key_count = 0;
uint16_t key_index = -1;
_find_key_index_and_count(combo->keys, keycode, &key_index, &key_count);
@@ -271,7 +291,7 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
KEY_STATE_DOWN(state, key_index);
if (ALL_COMBO_KEYS_ARE_DOWN(state, key_count)) {
// this in the end executes the combo when the key_buffer is dumped.
- record->keycode = combo->keycode;
+ record->keycode = combo->keycode;
record->event.key = COMBO_KEY_POS;
qrecord->combo_index = combo_index;
@@ -283,19 +303,15 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
// by making it a TICK event.
record->event.time = 0;
}
-
}
drop_combo_from_buffer(combo_index);
}
static inline void apply_combos(void) {
// Apply all buffered normal combos.
- for (uint8_t i = combo_buffer_read;
- i != combo_buffer_write;
- INCREMENT_MOD(i)) {
-
+ for (uint8_t i = combo_buffer_read; i != combo_buffer_write; INCREMENT_MOD(i)) {
queued_combo_t *buffered_combo = &combo_buffer[i];
- combo_t *combo = &key_combos[buffered_combo->combo_index];
+ combo_t * combo = &key_combos[buffered_combo->combo_index];
#ifdef COMBO_MUST_TAP_PER_COMBO
if (get_combo_must_tap(buffered_combo->combo_index, combo)) {
@@ -310,15 +326,15 @@ static inline void apply_combos(void) {
clear_combos();
}
-combo_t* overlaps(combo_t *combo1, combo_t *combo2) {
+combo_t *overlaps(combo_t *combo1, combo_t *combo2) {
/* Checks if the combos overlap and returns the combo that should be
* dropped from the combo buffer.
* The combo that has less keys will be dropped. If they have the same
* amount of keys, drop combo1. */
- uint8_t idx1 = 0, idx2 = 0;
+ uint8_t idx1 = 0, idx2 = 0;
uint16_t key1, key2;
- bool overlaps = false;
+ bool overlaps = false;
while ((key1 = pgm_read_word(&combo1->keys[idx1])) != COMBO_END) {
idx2 = 0;
@@ -335,7 +351,7 @@ combo_t* overlaps(combo_t *combo1, combo_t *combo2) {
}
static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record, uint16_t combo_index) {
- uint8_t key_count = 0;
+ uint8_t key_count = 0;
uint16_t key_index = -1;
_find_key_index_and_count(combo->keys, keycode, &key_index, &key_count);
@@ -369,12 +385,9 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
// disable readied combos that overlap with this combo
combo_t *drop = NULL;
- for (uint8_t combo_buffer_i = combo_buffer_read;
- combo_buffer_i != combo_buffer_write;
- INCREMENT_MOD(combo_buffer_i)) {
-
- queued_combo_t *qcombo = &combo_buffer[combo_buffer_i];
- combo_t *buffered_combo = &key_combos[qcombo->combo_index];
+ for (uint8_t combo_buffer_i = combo_buffer_read; combo_buffer_i != combo_buffer_write; INCREMENT_MOD(combo_buffer_i)) {
+ queued_combo_t *qcombo = &combo_buffer[combo_buffer_i];
+ combo_t * buffered_combo = &key_combos[qcombo->combo_index];
if ((drop = overlaps(buffered_combo, combo))) {
DISABLE_COMBO(drop);
@@ -387,21 +400,19 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
INCREMENT_MOD(combo_buffer_read);
}
}
-
}
if (drop != combo) {
// save this combo to buffer
combo_buffer[combo_buffer_write] = (queued_combo_t){
- .combo_index=combo_index,
+ .combo_index = combo_index,
};
INCREMENT_MOD(combo_buffer_write);
// get possible longer waiting time for tap-/hold-only combos.
longest_term = _get_wait_time(combo_index, combo);
}
- } // if timer elapsed end
-
+ } // if timer elapsed end
}
} else {
// chord releases
@@ -416,7 +427,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
else if (get_combo_must_tap(combo_index, combo)) {
// immediately apply tap-only combo
apply_combo(combo_index, combo);
- apply_combos(); // also apply other prepared combos and dump key buffer
+ apply_combos(); // also apply other prepared combos and dump key buffer
# ifdef COMBO_PROCESS_KEY_RELEASE
if (process_combo_key_release(combo_index, combo, key_index, keycode)) {
release_combo(combo_index, combo);
@@ -424,10 +435,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
# endif
}
#endif
- } else if (COMBO_ACTIVE(combo)
- && ONLY_ONE_KEY_IS_DOWN(COMBO_STATE(combo))
- && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)
- ) {
+ } else if (COMBO_ACTIVE(combo) && ONLY_ONE_KEY_IS_DOWN(COMBO_STATE(combo)) && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)) {
/* last key released */
release_combo(combo_index, combo);
key_is_part_of_combo = true;
@@ -435,9 +443,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
#ifdef COMBO_PROCESS_KEY_RELEASE
process_combo_key_release(combo_index, combo, key_index, keycode);
#endif
- } else if (COMBO_ACTIVE(combo)
- && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)
- ) {
+ } else if (COMBO_ACTIVE(combo) && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)) {
/* first or middle key released */
key_is_part_of_combo = true;
@@ -489,21 +495,21 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed && is_combo_key) {
#ifndef COMBO_NO_TIMER
-# ifdef COMBO_STRICT_TIMER
+# ifdef COMBO_STRICT_TIMER
if (!timer) {
// timer is set only on the first key
timer = timer_read();
}
-# else
+# else
timer = timer_read();
-# endif
+# endif
#endif
if (key_buffer_size < COMBO_KEY_BUFFER_LENGTH) {
key_buffer[key_buffer_size++] = (queued_record_t){
- .record = *record,
- .keycode = keycode,
- .combo_index = -1, // this will be set when applying combos
+ .record = *record,
+ .keycode = keycode,
+ .combo_index = -1, // this will be set when applying combos
};
}
} else {
@@ -532,7 +538,7 @@ void combo_task(void) {
if (combo_buffer_read != combo_buffer_write) {
apply_combos();
longest_term = 0;
- timer = 0;
+ timer = 0;
} else {
dump_key_buffer();
timer = 0;
@@ -546,9 +552,9 @@ void combo_enable(void) { b_combo_enable = true; }
void combo_disable(void) {
#ifndef COMBO_NO_TIMER
- timer = 0;
+ timer = 0;
#endif
- b_combo_enable = false;
+ b_combo_enable = false;
combo_buffer_read = combo_buffer_write;
clear_combos();
dump_key_buffer();
diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h
index 43c36d79e6..4c4e574e34 100644
--- a/quantum/process_keycode/process_combo.h
+++ b/quantum/process_keycode/process_combo.h
@@ -43,8 +43,8 @@ typedef struct {
#ifdef EXTRA_SHORT_COMBOS
uint8_t state;
#else
- bool disabled;
- bool active;
+ bool disabled;
+ bool active;
# if defined(EXTRA_EXTRA_LONG_COMBOS)
uint32_t state;
# elif defined(EXTRA_LONG_COMBOS)
diff --git a/quantum/process_keycode/process_dynamic_tapping_term.c b/quantum/process_keycode/process_dynamic_tapping_term.c
new file mode 100644
index 0000000000..bdc5529e33
--- /dev/null
+++ b/quantum/process_keycode/process_dynamic_tapping_term.c
@@ -0,0 +1,50 @@
+/* Copyright 2020 Vladislav Kucheriavykh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "quantum.h"
+#include "process_dynamic_tapping_term.h"
+
+#ifndef DYNAMIC_TAPPING_TERM_INCREMENT
+# define DYNAMIC_TAPPING_TERM_INCREMENT 5
+#endif
+
+static void tapping_term_report(void) {
+ const char *tapping_term_str = get_u16_str(g_tapping_term, ' ');
+ // Skip padding spaces
+ while (*tapping_term_str == ' ') {
+ tapping_term_str++;
+ }
+ send_string(tapping_term_str);
+}
+
+bool process_dynamic_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ if (record->event.pressed) {
+ switch (keycode) {
+ case DT_PRNT:
+ tapping_term_report();
+ return false;
+
+ case DT_UP:
+ g_tapping_term += DYNAMIC_TAPPING_TERM_INCREMENT;
+ return false;
+
+ case DT_DOWN:
+ g_tapping_term -= DYNAMIC_TAPPING_TERM_INCREMENT;
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/drivers/qwiic/qwiic.h b/quantum/process_keycode/process_dynamic_tapping_term.h
index 8c3d1c8d63..85e83ee73b 100644
--- a/drivers/qwiic/qwiic.h
+++ b/quantum/process_keycode/process_dynamic_tapping_term.h
@@ -1,4 +1,4 @@
-/* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
+/* Copyright 2020 Vladislav Kucheriavykh
*
* 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
@@ -13,16 +13,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#pragma once
-#include "i2c_master.h"
+#include <stdbool.h>
+#include "action.h"
-#ifdef QWIIC_JOYSTIIC_ENABLE
-# include "joystiic.h"
-#endif
-#ifdef QWIIC_MICRO_OLED_ENABLE
-# include "micro_oled.h"
+#ifndef DYNAMIC_TAPPING_TERM_INCREMENT
+# define DYNAMIC_TAPPING_TERM_INCREMENT 5
#endif
-void qwiic_init(void);
-void qwiic_task(void);
+bool process_dynamic_tapping_term(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_haptic.c b/quantum/process_keycode/process_haptic.c
index 64d455d009..85b2ffcddd 100644
--- a/quantum/process_keycode/process_haptic.c
+++ b/quantum/process_keycode/process_haptic.c
@@ -17,6 +17,7 @@
#include "process_haptic.h"
#include "quantum_keycodes.h"
#include "action_tapping.h"
+#include "usb_device_state.h"
__attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
@@ -30,8 +31,9 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
if (record->tap.count == 0) return false;
break;
- case KC_LCTRL ... KC_RGUI:
+ case KC_LEFT_CTRL ... KC_RIGHT_GUI:
case QK_MOMENTARY ... QK_MOMENTARY_MAX:
+ case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
#endif
#ifdef NO_HAPTIC_FN
case KC_FN0 ... KC_FN31:
@@ -42,34 +44,34 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t
#ifdef NO_HAPTIC_PUNCTUATION
case KC_ENTER:
case KC_ESCAPE:
- case KC_BSPACE:
+ case KC_BACKSPACE:
case KC_SPACE:
case KC_MINUS:
case KC_EQUAL:
- case KC_LBRACKET:
- case KC_RBRACKET:
- case KC_BSLASH:
+ case KC_LEFT_BRACKET:
+ case KC_RIGHT_BRACKET:
+ case KC_BACKSLASH:
case KC_NONUS_HASH:
- case KC_SCOLON:
+ case KC_SEMICOLON:
case KC_QUOTE:
case KC_GRAVE:
case KC_COMMA:
case KC_SLASH:
case KC_DOT:
- case KC_NONUS_BSLASH:
+ case KC_NONUS_BACKSLASH:
#endif
#ifdef NO_HAPTIC_LOCKKEYS
- case KC_CAPSLOCK:
- case KC_SCROLLLOCK:
- case KC_NUMLOCK:
+ case KC_CAPS_LOCK:
+ case KC_SCROLL_LOCK:
+ case KC_NUM_LOCK:
#endif
#ifdef NO_HAPTIC_NAV
- case KC_PSCREEN:
+ case KC_PRINT_SCREEN:
case KC_PAUSE:
case KC_INSERT:
case KC_DELETE:
- case KC_PGDOWN:
- case KC_PGUP:
+ case KC_PAGE_DOWN:
+ case KC_PAGE_UP:
case KC_LEFT:
case KC_UP:
case KC_RIGHT:
@@ -130,7 +132,7 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) {
}
}
- if (haptic_get_enable()) {
+ if (haptic_get_enable() && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) {
if (record->event.pressed) {
// keypress
if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) {
diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c
index 2beccbd8f9..6822c5e289 100644
--- a/quantum/process_keycode/process_music.c
+++ b/quantum/process_keycode/process_music.c
@@ -146,7 +146,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
if (music_activated || midi_activated) {
if (record->event.pressed) {
- if (keycode == KC_LCTL) { // Start recording
+ if (keycode == KC_LEFT_CTRL) { // Start recording
music_all_notes_off();
music_sequence_recording = true;
music_sequence_recorded = false;
@@ -155,7 +155,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
return false;
}
- if (keycode == KC_LALT) { // Stop recording/playing
+ if (keycode == KC_LEFT_ALT) { // Stop recording/playing
music_all_notes_off();
if (music_sequence_recording) { // was recording
music_sequence_recorded = true;
@@ -165,7 +165,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
return false;
}
- if (keycode == KC_LGUI && music_sequence_recorded) { // Start playing
+ if (keycode == KC_LEFT_GUI && music_sequence_recorded) { // Start playing
music_all_notes_off();
music_sequence_recording = false;
music_sequence_playing = true;
diff --git a/quantum/process_keycode/process_printer.c b/quantum/process_keycode/process_printer.c
index 7c5e4169a6..82528cc680 100644
--- a/quantum/process_keycode/process_printer.c
+++ b/quantum/process_keycode/process_printer.c
@@ -31,7 +31,7 @@ uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0
// uint8_t keycode_to_ascii[0xFF][2];
-// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
+// keycode_to_ascii[KC_MINUS] = {0x2D, 0x5F};
void print_char(char c) {
USB_Disable();
@@ -90,8 +90,8 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
case KC_PIPE:
case KC_TILD:
keycode &= 0xFF;
- case KC_LSFT:
- case KC_RSFT:
+ case KC_LEFT_SHIFT:
+ case KC_RIGHT_SHIFT:
if (record->event.pressed) {
character_shift++;
} else {
@@ -107,13 +107,13 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
print_box_string("This is a line of text!");
}
return false;
- case KC_ESC:
+ case KC_ESCAPE:
if (record->event.pressed) {
print_char(0x1B);
}
return false;
break;
- case KC_SPC:
+ case KC_SPACE:
if (record->event.pressed) {
print_char(0x20);
}
@@ -139,7 +139,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_ENT:
+ case KC_ENTER:
if (record->event.pressed) {
if (character_shift) {
print_char(0x0C);
@@ -149,7 +149,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_BSPC:
+ case KC_BACKSPACE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x18);
@@ -169,7 +169,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_COMM:
+ case KC_COMMA:
if (record->event.pressed) {
if (character_shift) {
print_char(0x3C);
@@ -179,7 +179,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_SLSH:
+ case KC_SLASH:
if (record->event.pressed) {
if (character_shift) {
print_char(0x3F);
@@ -189,7 +189,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_QUOT:
+ case KC_QUOTE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x22);
@@ -199,7 +199,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_GRV:
+ case KC_GRAVE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7E);
@@ -209,7 +209,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_MINS:
+ case KC_MINUS:
if (record->event.pressed) {
if (character_shift) {
print_char(0x5F);
@@ -219,7 +219,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_EQL:
+ case KC_EQUAL:
if (record->event.pressed) {
if (character_shift) {
print_char(0x2B);
@@ -229,7 +229,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_LBRC:
+ case KC_LEFT_BRACKET:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7B);
@@ -239,7 +239,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_RBRC:
+ case KC_RIGHT_BRACKET:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7D);
@@ -249,7 +249,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_BSLS:
+ case KC_BACKSLASH:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7C);
diff --git a/quantum/process_keycode/process_printer_bb.c b/quantum/process_keycode/process_printer_bb.c
index e482d82591..6c91bd27ef 100644
--- a/quantum/process_keycode/process_printer_bb.c
+++ b/quantum/process_keycode/process_printer_bb.c
@@ -45,7 +45,7 @@ uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0
// uint8_t keycode_to_ascii[0xFF][2];
-// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
+// keycode_to_ascii[KC_MINUS] = {0x2D, 0x5F};
void print_char(char c) {
uint8_t b = 8;
@@ -84,8 +84,8 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
case KC_PIPE:
case KC_TILD:
keycode &= 0xFF;
- case KC_LSFT:
- case KC_RSFT:
+ case KC_LEFT_SHIFT:
+ case KC_RIGHT_SHIFT:
if (record->event.pressed) {
character_shift++;
} else {
@@ -101,13 +101,13 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
print_string("This is a line of text!\n\n\n");
}
return false;
- case KC_ESC:
+ case KC_ESCAPE:
if (record->event.pressed) {
print_char(0x1B);
}
return false;
break;
- case KC_SPC:
+ case KC_SPACE:
if (record->event.pressed) {
print_char(0x20);
}
@@ -133,7 +133,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_ENT:
+ case KC_ENTER:
if (record->event.pressed) {
if (character_shift) {
print_char(0x0C);
@@ -143,7 +143,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_BSPC:
+ case KC_BACKSPACE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x18);
@@ -163,7 +163,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_COMM:
+ case KC_COMMA:
if (record->event.pressed) {
if (character_shift) {
print_char(0x3C);
@@ -173,7 +173,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_SLSH:
+ case KC_SLASH:
if (record->event.pressed) {
if (character_shift) {
print_char(0x3F);
@@ -183,7 +183,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_QUOT:
+ case KC_QUOTE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x22);
@@ -193,7 +193,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_GRV:
+ case KC_GRAVE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7E);
@@ -203,7 +203,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_MINS:
+ case KC_MINUS:
if (record->event.pressed) {
if (character_shift) {
print_char(0x5F);
@@ -213,7 +213,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_EQL:
+ case KC_EQUAL:
if (record->event.pressed) {
if (character_shift) {
print_char(0x2B);
@@ -223,7 +223,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_LBRC:
+ case KC_LEFT_BRACKET:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7B);
@@ -233,7 +233,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_RBRC:
+ case KC_RIGHT_BRACKET:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7D);
@@ -243,7 +243,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_BSLS:
+ case KC_BACKSLASH:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7C);
diff --git a/quantum/process_keycode/process_programmable_button.c b/quantum/process_keycode/process_programmable_button.c
new file mode 100644
index 0000000000..c6e77faacc
--- /dev/null
+++ b/quantum/process_keycode/process_programmable_button.c
@@ -0,0 +1,31 @@
+/*
+Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "process_programmable_button.h"
+#include "programmable_button.h"
+
+bool process_programmable_button(uint16_t keycode, keyrecord_t *record) {
+ if (keycode >= PROGRAMMABLE_BUTTON_MIN && keycode <= PROGRAMMABLE_BUTTON_MAX) {
+ uint8_t button = keycode - PROGRAMMABLE_BUTTON_MIN + 1;
+ if (record->event.pressed) {
+ programmable_button_on(button);
+ } else {
+ programmable_button_off(button);
+ }
+ }
+ return true;
+}
diff --git a/tmk_core/protocol/serial_mouse.h b/quantum/process_keycode/process_programmable_button.h
index cb83cf4f62..47c6ce5614 100644
--- a/tmk_core/protocol/serial_mouse.h
+++ b/quantum/process_keycode/process_programmable_button.h
@@ -1,5 +1,5 @@
/*
-Copyright 2014 Robin Haberkorn <robin.haberkorn@googlemail.com>
+Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,12 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <stdint.h>
+#include "quantum.h"
-#include "serial.h"
-
-static inline uint8_t serial_mouse_init(void) {
- serial_init();
- return 0;
-}
-
-void serial_mouse_task(void);
+bool process_programmable_button(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_space_cadet.c b/quantum/process_keycode/process_space_cadet.c
index f99db2a87b..46b2648c35 100644
--- a/quantum/process_keycode/process_space_cadet.c
+++ b/quantum/process_keycode/process_space_cadet.c
@@ -27,53 +27,53 @@
// Shift / Enter setup
#ifndef SFTENT_KEY
-# define SFTENT_KEY KC_ENT
+# define SFTENT_KEY KC_ENTER
#endif
#ifdef DISABLE_SPACE_CADET_MODIFIER
# ifndef LSPO_MOD
-# define LSPO_MOD KC_TRNS
+# define LSPO_MOD KC_TRANSPARENT
# endif
# ifndef RSPC_MOD
-# define RSPC_MOD KC_TRNS
+# define RSPC_MOD KC_TRANSPARENT
# endif
#else
# ifndef LSPO_MOD
-# define LSPO_MOD KC_LSFT
+# define LSPO_MOD KC_LEFT_SHIFT
# endif
# ifndef RSPC_MOD
-# define RSPC_MOD KC_RSFT
+# define RSPC_MOD KC_RIGHT_SHIFT
# endif
#endif
// **********************************************************
// Shift / paren setup
#ifndef LSPO_KEYS
-# define LSPO_KEYS KC_LSFT, LSPO_MOD, LSPO_KEY
+# define LSPO_KEYS KC_LEFT_SHIFT, LSPO_MOD, LSPO_KEY
#endif
#ifndef RSPC_KEYS
-# define RSPC_KEYS KC_RSFT, RSPC_MOD, RSPC_KEY
+# define RSPC_KEYS KC_RIGHT_SHIFT, RSPC_MOD, RSPC_KEY
#endif
// Control / paren setup
#ifndef LCPO_KEYS
-# define LCPO_KEYS KC_LCTL, KC_LSFT, KC_9
+# define LCPO_KEYS KC_LEFT_CTRL, KC_LEFT_SHIFT, KC_9
#endif
#ifndef RCPC_KEYS
-# define RCPC_KEYS KC_RCTL, KC_RSFT, KC_0
+# define RCPC_KEYS KC_RIGHT_CTRL, KC_RIGHT_SHIFT, KC_0
#endif
// Alt / paren setup
#ifndef LAPO_KEYS
-# define LAPO_KEYS KC_LALT, KC_LSFT, KC_9
+# define LAPO_KEYS KC_LEFT_ALT, KC_LEFT_SHIFT, KC_9
#endif
#ifndef RAPC_KEYS
-# define RAPC_KEYS KC_RALT, KC_RSFT, KC_0
+# define RAPC_KEYS KC_RIGHT_ALT, KC_RIGHT_SHIFT, KC_0
#endif
// Shift / Enter setup
#ifndef SFTENT_KEYS
-# define SFTENT_KEYS KC_RSFT, KC_TRNS, SFTENT_KEY
+# define SFTENT_KEYS KC_RIGHT_SHIFT, KC_TRANSPARENT, SFTENT_KEY
#endif
static uint8_t sc_last = 0;
diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c
index a964aead35..5d0bb313b4 100644
--- a/quantum/process_keycode/process_steno.c
+++ b/quantum/process_keycode/process_steno.c
@@ -67,7 +67,7 @@ static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM,
#ifdef STENO_COMBINEDMAP
/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */
-static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
+static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U};
#endif
@@ -174,11 +174,10 @@ bool process_steno(uint16_t keycode, keyrecord_t *record) {
return false;
#ifdef STENO_COMBINEDMAP
- case QK_STENO_COMB ... QK_STENO_COMB_MAX:
- {
+ case QK_STENO_COMB ... QK_STENO_COMB_MAX: {
uint8_t result;
- result = process_steno(combinedmap_first[keycode-QK_STENO_COMB], record);
- result &= process_steno(combinedmap_second[keycode-QK_STENO_COMB], record);
+ result = process_steno(combinedmap_first[keycode - QK_STENO_COMB], record);
+ result &= process_steno(combinedmap_second[keycode - QK_STENO_COMB], record);
return result;
}
#endif
diff --git a/quantum/process_keycode/process_terminal.c b/quantum/process_keycode/process_terminal.c
index 7d1eefa9ed..a059f3a521 100644
--- a/quantum/process_keycode/process_terminal.c
+++ b/quantum/process_keycode/process_terminal.c
@@ -257,12 +257,12 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
process_terminal_command();
return false;
break;
- case KC_ESC:
+ case KC_ESCAPE:
SEND_STRING("\n");
enable_terminal();
return false;
break;
- case KC_BSPC:
+ case KC_BACKSPACE:
str_len = strlen(buffer);
if (str_len > 0) {
buffer[str_len - 1] = 0;
@@ -284,7 +284,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
str_len = strlen(buffer);
for (int i = 0; i < str_len; ++i) {
send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
- // process_terminal(KC_BSPC,record);
+ // process_terminal(KC_BACKSPACE,record);
}
strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 80);
@@ -299,7 +299,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
str_len = strlen(buffer);
for (int i = 0; i < str_len; ++i) {
send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
- // process_terminal(KC_BSPC,record);
+ // process_terminal(KC_BACKSPACE,record);
}
strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 79);
@@ -311,7 +311,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
default:
if (keycode <= 58) {
char_to_add = 0;
- if (get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) {
+ if (get_mods() & (MOD_BIT(KC_LEFT_SHIFT) | MOD_BIT(KC_RIGHT_SHIFT))) {
char_to_add = shifted_keycode_to_ascii_lut[keycode];
} else if (get_mods() == 0) {
char_to_add = keycode_to_ascii_lut[keycode];
diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c
index 12b0aba9bf..d084d2b66c 100644
--- a/quantum/process_keycode/process_ucis.c
+++ b/quantum/process_keycode/process_ucis.c
@@ -46,7 +46,7 @@ static bool is_uni_seq(char *seq) {
return false;
}
}
- return qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC;
+ return qk_ucis_state.codes[i] == KC_ENTER || qk_ucis_state.codes[i] == KC_SPACE;
}
__attribute__((weak)) void qk_ucis_symbol_fallback(void) {
@@ -72,7 +72,7 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
return true;
}
- bool special = keycode == KC_SPC || keycode == KC_ENT || keycode == KC_ESC || keycode == KC_BSPC;
+ bool special = keycode == KC_SPACE || keycode == KC_ENTER || keycode == KC_ESCAPE || keycode == KC_BACKSPACE;
if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) {
return false;
}
@@ -81,7 +81,7 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
qk_ucis_state.count++;
switch (keycode) {
- case KC_BSPC:
+ case KC_BACKSPACE:
if (qk_ucis_state.count >= 2) {
qk_ucis_state.count -= 2;
return true;
@@ -90,16 +90,16 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
return false;
}
- case KC_SPC:
- case KC_ENT:
- case KC_ESC:
+ case KC_SPACE:
+ case KC_ENTER:
+ case KC_ESCAPE:
for (uint8_t i = 0; i < qk_ucis_state.count; i++) {
- register_code(KC_BSPC);
- unregister_code(KC_BSPC);
+ register_code(KC_BACKSPACE);
+ unregister_code(KC_BACKSPACE);
wait_ms(UNICODE_TYPE_DELAY);
}
- if (keycode == KC_ESC) {
+ if (keycode == KC_ESCAPE) {
qk_ucis_state.in_progress = false;
qk_ucis_cancel();
return false;
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c
index 46fcaaa86b..7685bb1c99 100644
--- a/quantum/process_keycode/process_unicode_common.c
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -22,6 +22,7 @@
unicode_config_t unicode_config;
uint8_t unicode_saved_mods;
bool unicode_saved_caps_lock;
+bool unicode_saved_num_lock;
#if UNICODE_SELECTED_MODES != -1
static uint8_t selected[] = {UNICODE_SELECTED_MODES};
@@ -79,13 +80,14 @@ void persist_unicode_input_mode(void) { eeprom_update_byte(EECONFIG_UNICODEMODE,
__attribute__((weak)) void unicode_input_start(void) {
unicode_saved_caps_lock = host_keyboard_led_state().caps_lock;
+ unicode_saved_num_lock = host_keyboard_led_state().num_lock;
// Note the order matters here!
// Need to do this before we mess around with the mods, or else
// UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work
// correctly in the shifted case.
if (unicode_config.input_mode == UC_LNX && unicode_saved_caps_lock) {
- tap_code(KC_CAPS);
+ tap_code(KC_CAPS_LOCK);
}
unicode_saved_mods = get_mods(); // Save current mods
@@ -99,8 +101,13 @@ __attribute__((weak)) void unicode_input_start(void) {
tap_code16(UNICODE_KEY_LNX);
break;
case UC_WIN:
- register_code(KC_LALT);
- tap_code(KC_PPLS);
+ // For increased reliability, use numpad keys for inputting digits
+ if (!unicode_saved_num_lock) {
+ tap_code(KC_NUM_LOCK);
+ }
+ register_code(KC_LEFT_ALT);
+ wait_ms(UNICODE_TYPE_DELAY);
+ tap_code(KC_KP_PLUS);
break;
case UC_WINC:
tap_code(UNICODE_KEY_WINC);
@@ -117,13 +124,16 @@ __attribute__((weak)) void unicode_input_finish(void) {
unregister_code(UNICODE_KEY_MAC);
break;
case UC_LNX:
- tap_code(KC_SPC);
+ tap_code(KC_SPACE);
if (unicode_saved_caps_lock) {
- tap_code(KC_CAPS);
+ tap_code(KC_CAPS_LOCK);
}
break;
case UC_WIN:
- unregister_code(KC_LALT);
+ unregister_code(KC_LEFT_ALT);
+ if (!unicode_saved_num_lock) {
+ tap_code(KC_NUM_LOCK);
+ }
break;
case UC_WINC:
tap_code(KC_ENTER);
@@ -139,26 +149,44 @@ __attribute__((weak)) void unicode_input_cancel(void) {
unregister_code(UNICODE_KEY_MAC);
break;
case UC_LNX:
- tap_code(KC_ESC);
+ tap_code(KC_ESCAPE);
if (unicode_saved_caps_lock) {
- tap_code(KC_CAPS);
+ tap_code(KC_CAPS_LOCK);
}
break;
case UC_WINC:
- tap_code(KC_ESC);
+ tap_code(KC_ESCAPE);
break;
case UC_WIN:
- unregister_code(KC_LALT);
+ unregister_code(KC_LEFT_ALT);
+ if (!unicode_saved_num_lock) {
+ tap_code(KC_NUM_LOCK);
+ }
break;
}
set_mods(unicode_saved_mods); // Reregister previously set mods
}
+// clang-format off
+
+static void send_nibble_wrapper(uint8_t digit) {
+ if (unicode_config.input_mode == UC_WIN) {
+ uint8_t kc = digit < 10
+ ? KC_KP_1 + (10 + digit - 1) % 10
+ : KC_A + (digit - 10);
+ tap_code(kc);
+ return;
+ }
+ send_nibble(digit);
+}
+
+// clang-format on
+
void register_hex(uint16_t hex) {
for (int i = 3; i >= 0; i--) {
uint8_t digit = ((hex >> (i * 4)) & 0xF);
- send_nibble(digit);
+ send_nibble_wrapper(digit);
}
}
@@ -171,10 +199,10 @@ void register_hex32(uint32_t hex) {
uint8_t digit = ((hex >> (i * 4)) & 0xF);
if (digit == 0) {
if (!onzerostart) {
- send_nibble(digit);
+ send_nibble_wrapper(digit);
}
} else {
- send_nibble(digit);
+ send_nibble_wrapper(digit);
onzerostart = false;
}
}
diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h
index c10e171ec3..72defb445e 100644
--- a/quantum/process_keycode/process_unicode_common.h
+++ b/quantum/process_keycode/process_unicode_common.h
@@ -24,13 +24,13 @@
// Keycodes used for starting Unicode input on different platforms
#ifndef UNICODE_KEY_MAC
-# define UNICODE_KEY_MAC KC_LALT
+# define UNICODE_KEY_MAC KC_LEFT_ALT
#endif
#ifndef UNICODE_KEY_LNX
# define UNICODE_KEY_LNX LCTL(LSFT(KC_U))
#endif
#ifndef UNICODE_KEY_WINC
-# define UNICODE_KEY_WINC KC_RALT
+# define UNICODE_KEY_WINC KC_RIGHT_ALT
#endif
// Comma-delimited, ordered list of input modes selected for use (e.g. in cycle)
diff --git a/quantum/programmable_button.c b/quantum/programmable_button.c
new file mode 100644
index 0000000000..be828fd17c
--- /dev/null
+++ b/quantum/programmable_button.c
@@ -0,0 +1,37 @@
+/*
+Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "programmable_button.h"
+#include "host.h"
+
+#define REPORT_BIT(index) (((uint32_t)1) << (index - 1))
+
+static uint32_t programmable_button_report = 0;
+
+void programmable_button_clear(void) { programmable_button_report = 0; }
+
+void programmable_button_send(void) { host_programmable_button_send(programmable_button_report); }
+
+void programmable_button_on(uint8_t index) { programmable_button_report |= REPORT_BIT(index); }
+
+void programmable_button_off(uint8_t index) { programmable_button_report &= ~REPORT_BIT(index); }
+
+bool programmable_button_is_on(uint8_t index) { return !!(programmable_button_report & REPORT_BIT(index)); };
+
+uint32_t programmable_button_get_report(void) { return programmable_button_report; };
+
+void programmable_button_set_report(uint32_t report) { programmable_button_report = report; }
diff --git a/quantum/programmable_button.h b/quantum/programmable_button.h
new file mode 100644
index 0000000000..e89b8b9fd6
--- /dev/null
+++ b/quantum/programmable_button.h
@@ -0,0 +1,30 @@
+/*
+Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "report.h"
+
+void programmable_button_clear(void);
+void programmable_button_send(void);
+void programmable_button_on(uint8_t index);
+void programmable_button_off(uint8_t index);
+bool programmable_button_is_on(uint8_t index);
+uint32_t programmable_button_get_report(void);
+void programmable_button_set_report(uint32_t report);
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 14f25597ca..5568c54703 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -26,10 +26,6 @@
# include "backlight.h"
#endif
-#ifdef API_ENABLE
-# include "api.h"
-#endif
-
#ifdef MIDI_ENABLE
# include "process_midi.h"
#endif
@@ -67,15 +63,15 @@ uint8_t extract_mod_bits(uint16_t code) {
uint8_t mods_to_send = 0;
if (code & QK_RMODS_MIN) { // Right mod flag is set
- if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RCTL);
- if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RSFT);
- if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RALT);
- if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_RGUI);
+ if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RIGHT_CTRL);
+ if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RIGHT_SHIFT);
+ if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RIGHT_ALT);
+ if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_RIGHT_GUI);
} else {
- if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_LCTL);
- if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_LSFT);
- if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_LALT);
- if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LGUI);
+ if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_LEFT_CTRL);
+ if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_LEFT_SHIFT);
+ if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_LEFT_ALT);
+ if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LEFT_GUI);
}
return mods_to_send;
@@ -146,12 +142,13 @@ void reset_keyboard(void) {
/* Convert record into usable keycode via the contained event. */
uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) {
#ifdef COMBO_ENABLE
- if (record->keycode) { return record->keycode; }
+ if (record->keycode) {
+ return record->keycode;
+ }
#endif
return get_event_keycode(record->event, update_layer_cache);
}
-
/* Convert event into usable keycode. Checks the layer cache to ensure that it
* retains the correct keycode after a layer change, if the key is still pressed.
* "update_layer_cache" is to ensure that it only updates the layer cache when
@@ -180,12 +177,12 @@ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache) {
bool pre_process_record_quantum(keyrecord_t *record) {
if (!(
#ifdef COMBO_ENABLE
- process_combo(get_record_keycode(record, true), record) &&
+ process_combo(get_record_keycode(record, true), record) &&
#endif
- true)) {
+ true)) {
return false;
}
- return true; // continue processing
+ return true; // continue processing
}
/* Get keycode, and then call keyboard function */
@@ -282,6 +279,9 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef AUTO_SHIFT_ENABLE
process_auto_shift(keycode, record) &&
#endif
+#ifdef DYNAMIC_TAPPING_TERM_ENABLE
+ process_dynamic_tapping_term(keycode, record) &&
+#endif
#ifdef TERMINAL_ENABLE
process_terminal(keycode, record) &&
#endif
@@ -300,6 +300,9 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef JOYSTICK_ENABLE
process_joystick(keycode, record) &&
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ process_programmable_button(keycode, record) &&
+#endif
true)) {
return false;
}
@@ -479,14 +482,6 @@ void matrix_scan_quantum() {
# include "hd44780.h"
#endif
-void api_send_unicode(uint32_t unicode) {
-#ifdef API_ENABLE
- uint8_t chunk[4];
- dword_to_bytes(unicode, chunk);
- MT_SEND_DATA(DT_UNICODE, chunk, 5);
-#endif
-}
-
//------------------------------------------------------------------------------
// Override these functions in your keymap file to play different tunes on
// different events such as startup and bootloader jump
@@ -500,10 +495,166 @@ __attribute__((weak)) bool webusb_receive_user(uint8_t *data, uint8_t length) {
__attribute__((weak)) bool webusb_receive_kb(uint8_t *data, uint8_t length) { return webusb_receive_user(data, length); }
bool webusb_receive_quantum(uint8_t *data, uint8_t length) {
-#ifdef ORYX_ENABLE
+# ifdef ORYX_ENABLE
return webusb_receive_oryx(data, length);
-#else
+# else
return webusb_receive_kb(data, length);
+# endif
+}
+#endif
+
+/** \brief Run keyboard level Power down
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_power_down_user(void) {}
+/** \brief Run keyboard level Power down
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
+
+void suspend_power_down_quantum(void) {
+#ifndef NO_SUSPEND_POWER_DOWN
+// Turn off backlight
+# ifdef BACKLIGHT_ENABLE
+ backlight_set(0);
+# endif
+
+# ifdef LED_MATRIX_ENABLE
+ led_matrix_task();
+# endif
+# ifdef RGB_MATRIX_ENABLE
+ rgb_matrix_task();
+# endif
+
+ // Turn off LED indicators
+ uint8_t leds_off = 0;
+# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
+ if (is_backlight_enabled()) {
+ // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
+ leds_off |= (1 << USB_LED_CAPS_LOCK);
+ }
+# endif
+ led_set(leds_off);
+
+// Turn off audio
+# ifdef AUDIO_ENABLE
+ stop_all_notes();
+# endif
+
+// Turn off underglow
+# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
+ rgblight_suspend();
+# endif
+
+# if defined(LED_MATRIX_ENABLE)
+ led_matrix_set_suspend_state(true);
+# endif
+# if defined(RGB_MATRIX_ENABLE)
+ rgb_matrix_set_suspend_state(true);
+# endif
+
+# ifdef OLED_ENABLE
+ oled_off();
+# endif
+# ifdef ST7565_ENABLE
+ st7565_off();
+# endif
+# if defined(POINTING_DEVICE_ENABLE)
+ // run to ensure scanning occurs while suspended
+ pointing_device_task();
+# endif
#endif
}
+
+/** \brief run user level code immediately after wakeup
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_wakeup_init_user(void) {}
+
+/** \brief run keyboard level code immediately after wakeup
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
+
+__attribute__((weak)) void suspend_wakeup_init_quantum(void) {
+// Turn on backlight
+#ifdef BACKLIGHT_ENABLE
+ backlight_init();
+#endif
+
+ // Restore LED indicators
+ led_set(host_keyboard_leds());
+
+// Wake up underglow
+#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
+ rgblight_wakeup();
#endif
+
+#if defined(LED_MATRIX_ENABLE)
+ led_matrix_set_suspend_state(false);
+#endif
+#if defined(RGB_MATRIX_ENABLE)
+ rgb_matrix_set_suspend_state(false);
+#endif
+ suspend_wakeup_init_kb();
+}
+
+/** \brief converts unsigned integers into char arrays
+ *
+ * Takes an unsigned integer and converts that value into an equivalent char array
+ * A padding character may be specified, ' ' for leading spaces, '0' for leading zeros.
+ */
+
+const char *get_numeric_str(char *buf, size_t buf_len, uint32_t curr_num, char curr_pad) {
+ buf[buf_len - 1] = '\0';
+ for (size_t i = 0; i < buf_len - 1; ++i) {
+ char c = '0' + curr_num % 10;
+ buf[buf_len - 2 - i] = (c == '0' && i == 0) ? '0' : (curr_num > 0 ? c : curr_pad);
+ curr_num /= 10;
+ }
+ return buf;
+}
+
+/** \brief converts uint8_t into char array
+ *
+ * Takes an uint8_t, and uses an internal static buffer to render that value into a char array
+ * A padding character may be specified, ' ' for leading spaces, '0' for leading zeros.
+ *
+ * NOTE: Subsequent invocations will reuse the same static buffer and overwrite the previous
+ * contents. Use the result immediately, instead of caching it.
+ */
+const char *get_u8_str(uint8_t curr_num, char curr_pad) {
+ static char buf[4] = {0};
+ static uint8_t last_num = 0xFF;
+ static char last_pad = '\0';
+ if (last_num == curr_num && last_pad == curr_pad) {
+ return buf;
+ }
+ last_num = curr_num;
+ last_pad = curr_pad;
+ return get_numeric_str(buf, sizeof(buf), curr_num, curr_pad);
+}
+
+/** \brief converts uint16_t into char array
+ *
+ * Takes an uint16_t, and uses an internal static buffer to render that value into a char array
+ * A padding character may be specified, ' ' for leading spaces, '0' for leading zeros.
+ *
+ * NOTE: Subsequent invocations will reuse the same static buffer and overwrite the previous
+ * contents. Use the result immediately, instead of caching it.
+ */
+const char *get_u16_str(uint16_t curr_num, char curr_pad) {
+ static char buf[6] = {0};
+ static uint16_t last_num = 0xFF;
+ static char last_pad = '\0';
+ if (last_num == curr_num && last_pad == curr_pad) {
+ return buf;
+ }
+ last_num = curr_num;
+ last_pad = curr_pad;
+ return get_numeric_str(buf, sizeof(buf), curr_num, curr_pad);
+}
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 22afacec0d..d0829629f5 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -54,6 +54,10 @@
#include <stddef.h>
#include <stdlib.h>
+#ifdef DEFERRED_EXEC_ENABLE
+# include "deferred_exec.h"
+#endif
+
extern layer_state_t default_layer_state;
#ifndef NO_ACTION_LAYER
@@ -121,6 +125,10 @@ extern layer_state_t layer_state;
# include "process_auto_shift.h"
#endif
+#ifdef DYNAMIC_TAPPING_TERM_ENABLE
+# include "process_dynamic_tapping_term.h"
+#endif
+
#ifdef COMBO_ENABLE
# include "process_combo.h"
#endif
@@ -147,6 +155,10 @@ extern layer_state_t layer_state;
# include "process_joystick.h"
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+# include "process_programmable_button.h"
+#endif
+
#ifdef GRAVE_ESC_ENABLE
# include "process_grave_esc.h"
#endif
@@ -210,6 +222,10 @@ extern layer_state_t layer_state;
# include "encoder.h"
#endif
+#ifdef POINTING_DEVICE_ENABLE
+# include "pointing_device.h"
+#endif
+
// For tri-layer
void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3);
@@ -244,7 +260,9 @@ void led_set_kb(uint8_t usb_led);
bool led_update_user(led_t led_state);
bool led_update_kb(led_t led_state);
-void api_send_unicode(uint32_t unicode);
-
bool webusb_receive_kb(uint8_t *data, uint8_t length);
bool webusb_receive_user(uint8_t *data, uint8_t length);
+
+const char *get_numeric_str(char *buf, size_t buf_len, uint32_t curr_num, char curr_pad);
+const char *get_u8_str(uint8_t curr_num, char curr_pad);
+const char *get_u16_str(uint16_t curr_num, char curr_pad);
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 6cce7808f1..7093d46f87 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -19,7 +19,7 @@
#include "sequencer.h"
// Fillers to make layering more clear
-#define _______ KC_TRNS
+#define _______ KC_TRANSPARENT
#define XXXXXXX KC_NO
enum quantum_keycodes {
@@ -526,6 +526,79 @@ enum quantum_keycodes {
// Additional magic key
MAGIC_TOGGLE_GUI,
+ // Adjust tapping term on the fly
+ DT_PRNT,
+ DT_UP,
+ DT_DOWN,
+
+ // Programmable Button
+ PROGRAMMABLE_BUTTON_1,
+ PROGRAMMABLE_BUTTON_2,
+ PROGRAMMABLE_BUTTON_3,
+ PROGRAMMABLE_BUTTON_4,
+ PROGRAMMABLE_BUTTON_5,
+ PROGRAMMABLE_BUTTON_6,
+ PROGRAMMABLE_BUTTON_7,
+ PROGRAMMABLE_BUTTON_8,
+ PROGRAMMABLE_BUTTON_9,
+ PROGRAMMABLE_BUTTON_10,
+ PROGRAMMABLE_BUTTON_11,
+ PROGRAMMABLE_BUTTON_12,
+ PROGRAMMABLE_BUTTON_13,
+ PROGRAMMABLE_BUTTON_14,
+ PROGRAMMABLE_BUTTON_15,
+ PROGRAMMABLE_BUTTON_16,
+ PROGRAMMABLE_BUTTON_17,
+ PROGRAMMABLE_BUTTON_18,
+ PROGRAMMABLE_BUTTON_19,
+ PROGRAMMABLE_BUTTON_20,
+ PROGRAMMABLE_BUTTON_21,
+ PROGRAMMABLE_BUTTON_22,
+ PROGRAMMABLE_BUTTON_23,
+ PROGRAMMABLE_BUTTON_24,
+ PROGRAMMABLE_BUTTON_25,
+ PROGRAMMABLE_BUTTON_26,
+ PROGRAMMABLE_BUTTON_27,
+ PROGRAMMABLE_BUTTON_28,
+ PROGRAMMABLE_BUTTON_29,
+ PROGRAMMABLE_BUTTON_30,
+ PROGRAMMABLE_BUTTON_31,
+ PROGRAMMABLE_BUTTON_32,
+
+ // Dedicated macro keys for Configurator and VIA
+ MACRO_0,
+ MACRO_1,
+ MACRO_2,
+ MACRO_3,
+ MACRO_4,
+ MACRO_5,
+ MACRO_6,
+ MACRO_7,
+ MACRO_8,
+ MACRO_9,
+ MACRO_10,
+ MACRO_11,
+ MACRO_12,
+ MACRO_13,
+ MACRO_14,
+ MACRO_15,
+ MACRO_16,
+ MACRO_17,
+ MACRO_18,
+ MACRO_19,
+ MACRO_20,
+ MACRO_21,
+ MACRO_22,
+ MACRO_23,
+ MACRO_24,
+ MACRO_25,
+ MACRO_26,
+ MACRO_27,
+ MACRO_28,
+ MACRO_29,
+ MACRO_30,
+ MACRO_31,
+
// Start of custom keycode range for keyboards and keymaps - always leave at the end
SAFE_RANGE
};
@@ -567,69 +640,67 @@ enum quantum_keycodes {
#define MOD_MEH 0x7
// US ANSI shifted keycode aliases
-#define KC_TILD LSFT(KC_GRV) // ~
-#define KC_TILDE KC_TILD
+#define KC_TILDE LSFT(KC_GRAVE) // ~
+#define KC_TILD KC_TILDE
-#define KC_EXLM LSFT(KC_1) // !
-#define KC_EXCLAIM KC_EXLM
+#define KC_EXCLAIM LSFT(KC_1) // !
+#define KC_EXLM KC_EXCLAIM
#define KC_AT LSFT(KC_2) // @
#define KC_HASH LSFT(KC_3) // #
-#define KC_DLR LSFT(KC_4) // $
-#define KC_DOLLAR KC_DLR
-
-#define KC_PERC LSFT(KC_5) // %
-#define KC_PERCENT KC_PERC
+#define KC_DOLLAR LSFT(KC_4) // $
+#define KC_DLR KC_DOLLAR
-#define KC_CIRC LSFT(KC_6) // ^
-#define KC_CIRCUMFLEX KC_CIRC
+#define KC_PERCENT LSFT(KC_5) // %
+#define KC_PERC KC_PERCENT
-#define KC_AMPR LSFT(KC_7) // &
-#define KC_AMPERSAND KC_AMPR
+#define KC_CIRCUMFLEX LSFT(KC_6) // ^
+#define KC_CIRC KC_CIRCUMFLEX
-#define KC_ASTR LSFT(KC_8) // *
-#define KC_ASTERISK KC_ASTR
+#define KC_AMPERSAND LSFT(KC_7) // &
+#define KC_AMPR KC_AMPERSAND
-#define KC_LPRN LSFT(KC_9) // (
-#define KC_LEFT_PAREN KC_LPRN
+#define KC_ASTERISK LSFT(KC_8) // *
+#define KC_ASTR KC_ASTERISK
-#define KC_RPRN LSFT(KC_0) // )
-#define KC_RIGHT_PAREN KC_RPRN
+#define KC_LEFT_PAREN LSFT(KC_9) // (
+#define KC_LPRN KC_LEFT_PAREN
-#define KC_UNDS LSFT(KC_MINS) // _
-#define KC_UNDERSCORE KC_UNDS
+#define KC_RIGHT_PAREN LSFT(KC_0) // )
+#define KC_RPRN KC_RIGHT_PAREN
-#define KC_PLUS LSFT(KC_EQL) // +
+#define KC_UNDERSCORE LSFT(KC_MINUS) // _
+#define KC_UNDS KC_UNDERSCORE
-#define KC_LCBR LSFT(KC_LBRC) // {
-#define KC_LEFT_CURLY_BRACE KC_LCBR
+#define KC_PLUS LSFT(KC_EQUAL) // +
-#define KC_RCBR LSFT(KC_RBRC) // }
-#define KC_RIGHT_CURLY_BRACE KC_RCBR
+#define KC_LEFT_CURLY_BRACE LSFT(KC_LEFT_BRACKET) // {
+#define KC_LCBR KC_LEFT_CURLY_BRACE
-#define KC_LABK LSFT(KC_COMM) // <
-#define KC_LEFT_ANGLE_BRACKET KC_LABK
+#define KC_RIGHT_CURLY_BRACE LSFT(KC_RIGHT_BRACKET) // }
+#define KC_RCBR KC_RIGHT_CURLY_BRACE
-#define KC_RABK LSFT(KC_DOT) // >
-#define KC_RIGHT_ANGLE_BRACKET KC_RABK
+#define KC_LEFT_ANGLE_BRACKET LSFT(KC_COMMA) // <
+#define KC_LABK KC_LEFT_ANGLE_BRACKET
+#define KC_LT KC_LEFT_ANGLE_BRACKET
-#define KC_COLN LSFT(KC_SCLN) // :
-#define KC_COLON KC_COLN
+#define KC_RIGHT_ANGLE_BRACKET LSFT(KC_DOT) // >
+#define KC_RABK KC_RIGHT_ANGLE_BRACKET
+#define KC_GT KC_RIGHT_ANGLE_BRACKET
-#define KC_PIPE LSFT(KC_BSLS) // |
+#define KC_COLON LSFT(KC_SEMICOLON) // :
+#define KC_COLN KC_COLON
-#define KC_LT LSFT(KC_COMM) // <
+#define KC_PIPE LSFT(KC_BACKSLASH) // |
-#define KC_GT LSFT(KC_DOT) // >
+#define KC_QUESTION LSFT(KC_SLASH) // ?
+#define KC_QUES KC_QUESTION
-#define KC_QUES LSFT(KC_SLSH) // ?
-#define KC_QUESTION KC_QUES
-
-#define KC_DQT LSFT(KC_QUOT) // "
-#define KC_DOUBLE_QUOTE KC_DQT
-#define KC_DQUO KC_DQT
+#define KC_DOUBLE_QUOTE LSFT(KC_QUOTE) // "
+#define KC_DQUO KC_DOUBLE_QUOTE
+#define KC_DQT KC_DOUBLE_QUOTE
#define KC_DELT KC_DELETE // Del key (four letter code)
@@ -777,12 +848,12 @@ enum quantum_keycodes {
#define CMD_T(kc) LCMD_T(kc)
#define WIN_T(kc) LWIN_T(kc)
-#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal
-#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt
-#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI
-#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI
+#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal
+#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt
+#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI
+#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI
#define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
-#define LSG_T(kc) MT(MOD_LSFT | MOD_LGUI, kc) // Left Shift + GUI
+#define LSG_T(kc) MT(MOD_LSFT | MOD_LGUI, kc) // Left Shift + GUI
#define SGUI_T(kc) LSG_T(kc)
#define SCMD_T(kc) LSG_T(kc)
#define SWIN_T(kc) LSG_T(kc)
@@ -813,7 +884,7 @@ enum quantum_keycodes {
#define UC_M_MA UNICODE_MODE_MAC
#define UNICODE_MODE_OSX UNICODE_MODE_MAC // Deprecated alias
-#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias
+#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias
#define UC_M_LN UNICODE_MODE_LNX
#define UC_M_WI UNICODE_MODE_WIN
#define UC_M_BS UNICODE_MODE_BSD
@@ -856,3 +927,39 @@ enum quantum_keycodes {
#define OS_TOGG ONESHOT_TOGGLE
#define OS_ON ONESHOT_ENABLE
#define OS_OFF ONESHOT_DISABLE
+
+// Programmable Button aliases
+#define PB_1 PROGRAMMABLE_BUTTON_1
+#define PB_2 PROGRAMMABLE_BUTTON_2
+#define PB_3 PROGRAMMABLE_BUTTON_3
+#define PB_4 PROGRAMMABLE_BUTTON_4
+#define PB_5 PROGRAMMABLE_BUTTON_5
+#define PB_6 PROGRAMMABLE_BUTTON_6
+#define PB_7 PROGRAMMABLE_BUTTON_7
+#define PB_8 PROGRAMMABLE_BUTTON_8
+#define PB_9 PROGRAMMABLE_BUTTON_9
+#define PB_10 PROGRAMMABLE_BUTTON_10
+#define PB_11 PROGRAMMABLE_BUTTON_11
+#define PB_12 PROGRAMMABLE_BUTTON_12
+#define PB_13 PROGRAMMABLE_BUTTON_13
+#define PB_14 PROGRAMMABLE_BUTTON_14
+#define PB_15 PROGRAMMABLE_BUTTON_15
+#define PB_16 PROGRAMMABLE_BUTTON_16
+#define PB_17 PROGRAMMABLE_BUTTON_17
+#define PB_18 PROGRAMMABLE_BUTTON_18
+#define PB_19 PROGRAMMABLE_BUTTON_19
+#define PB_20 PROGRAMMABLE_BUTTON_20
+#define PB_21 PROGRAMMABLE_BUTTON_21
+#define PB_22 PROGRAMMABLE_BUTTON_22
+#define PB_23 PROGRAMMABLE_BUTTON_23
+#define PB_24 PROGRAMMABLE_BUTTON_24
+#define PB_25 PROGRAMMABLE_BUTTON_25
+#define PB_26 PROGRAMMABLE_BUTTON_26
+#define PB_27 PROGRAMMABLE_BUTTON_27
+#define PB_28 PROGRAMMABLE_BUTTON_28
+#define PB_29 PROGRAMMABLE_BUTTON_29
+#define PB_30 PROGRAMMABLE_BUTTON_30
+#define PB_31 PROGRAMMABLE_BUTTON_31
+#define PB_32 PROGRAMMABLE_BUTTON_32
+#define PROGRAMMABLE_BUTTON_MIN PROGRAMMABLE_BUTTON_1
+#define PROGRAMMABLE_BUTTON_MAX PROGRAMMABLE_BUTTON_32
diff --git a/tmk_core/common/raw_hid.h b/quantum/raw_hid.h
index 6d60ab2bff..6d60ab2bff 100644
--- a/tmk_core/common/raw_hid.h
+++ b/quantum/raw_hid.h
diff --git a/quantum/rgb_matrix/animations/alpha_mods_anim.h b/quantum/rgb_matrix/animations/alpha_mods_anim.h
index 3f2c9b799a..d6136f1ba4 100644
--- a/quantum/rgb_matrix/animations/alpha_mods_anim.h
+++ b/quantum/rgb_matrix/animations/alpha_mods_anim.h
@@ -19,8 +19,8 @@ bool ALPHAS_MODS(effect_params_t* params) {
rgb_matrix_set_color(i, rgb1.r, rgb1.g, rgb1.b);
}
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_ALPHAS_MODS
+#endif // ENABLE_RGB_MATRIX_ALPHAS_MODS
diff --git a/quantum/rgb_matrix/animations/breathing_anim.h b/quantum/rgb_matrix/animations/breathing_anim.h
index a00ccb83a2..29187e1543 100644
--- a/quantum/rgb_matrix/animations/breathing_anim.h
+++ b/quantum/rgb_matrix/animations/breathing_anim.h
@@ -13,8 +13,8 @@ bool BREATHING(effect_params_t* params) {
RGB_MATRIX_TEST_LED_FLAGS();
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BREATHING
+#endif // ENABLE_RGB_MATRIX_BREATHING
diff --git a/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
index ac95789228..0375d4937d 100644
--- a/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
@@ -10,4 +10,4 @@ static HSV BAND_PINWHEEL_SAT_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time)
bool BAND_PINWHEEL_SAT(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_SAT_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
+#endif // ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
diff --git a/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
index f7fe4b76e9..e40bf4cd1f 100644
--- a/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
@@ -10,4 +10,4 @@ static HSV BAND_PINWHEEL_VAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time)
bool BAND_PINWHEEL_VAL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_VAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
+#endif // ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
diff --git a/quantum/rgb_matrix/animations/colorband_sat_anim.h b/quantum/rgb_matrix/animations/colorband_sat_anim.h
index 96a6cbf5cd..1c4f7de575 100644
--- a/quantum/rgb_matrix/animations/colorband_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_sat_anim.h
@@ -11,4 +11,4 @@ static HSV BAND_SAT_math(HSV hsv, uint8_t i, uint8_t time) {
bool BAND_SAT(effect_params_t* params) { return effect_runner_i(params, &BAND_SAT_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_SAT
+#endif // ENABLE_RGB_MATRIX_BAND_SAT
diff --git a/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
index 52f6040d81..cdd02b3797 100644
--- a/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
@@ -10,4 +10,4 @@ static HSV BAND_SPIRAL_SAT_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, u
bool BAND_SPIRAL_SAT(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_SAT_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
+#endif // ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
diff --git a/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
index d5752e27fb..e1331eaebe 100644
--- a/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
@@ -10,4 +10,4 @@ static HSV BAND_SPIRAL_VAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, u
bool BAND_SPIRAL_VAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_VAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_SPIRAL_VAL
+#endif // ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
diff --git a/quantum/rgb_matrix/animations/colorband_val_anim.h b/quantum/rgb_matrix/animations/colorband_val_anim.h
index 32bc6f52a5..02ee4add67 100644
--- a/quantum/rgb_matrix/animations/colorband_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_val_anim.h
@@ -11,4 +11,4 @@ static HSV BAND_VAL_math(HSV hsv, uint8_t i, uint8_t time) {
bool BAND_VAL(effect_params_t* params) { return effect_runner_i(params, &BAND_VAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_VAL
+#endif // ENABLE_RGB_MATRIX_BAND_VAL
diff --git a/quantum/rgb_matrix/animations/cycle_all_anim.h b/quantum/rgb_matrix/animations/cycle_all_anim.h
index 20af94b6ba..3b73b9d385 100644
--- a/quantum/rgb_matrix/animations/cycle_all_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_all_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_ALL_math(HSV hsv, uint8_t i, uint8_t time) {
bool CYCLE_ALL(effect_params_t* params) { return effect_runner_i(params, &CYCLE_ALL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_ALL
+#endif // ENABLE_RGB_MATRIX_CYCLE_ALL
diff --git a/quantum/rgb_matrix/animations/cycle_left_right_anim.h b/quantum/rgb_matrix/animations/cycle_left_right_anim.h
index 7f84f4bd59..bf6a574069 100644
--- a/quantum/rgb_matrix/animations/cycle_left_right_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_left_right_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_LEFT_RIGHT_math(HSV hsv, uint8_t i, uint8_t time) {
bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+#endif // ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
diff --git a/quantum/rgb_matrix/animations/cycle_out_in_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_anim.h
index 2277f16a2f..2bdb9d9375 100644
--- a/quantum/rgb_matrix/animations/cycle_out_in_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_out_in_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_OUT_IN_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint
bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_OUT_IN
+#endif // ENABLE_RGB_MATRIX_CYCLE_OUT_IN
diff --git a/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h
index 981c0afd05..51979c44fe 100644
--- a/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h
@@ -12,4 +12,4 @@ static HSV CYCLE_OUT_IN_DUAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time)
bool CYCLE_OUT_IN_DUAL(effect_params_t* params) { return effect_runner_dx_dy(params, &CYCLE_OUT_IN_DUAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
+#endif // ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
diff --git a/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
index 1a7db4a4c7..10ba2b7c2c 100644
--- a/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_PINWHEEL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time) {
bool CYCLE_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &CYCLE_PINWHEEL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_PINWHEEL
+#endif // ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
diff --git a/quantum/rgb_matrix/animations/cycle_spiral_anim.h b/quantum/rgb_matrix/animations/cycle_spiral_anim.h
index 245cdc237f..482c7e7da6 100644
--- a/quantum/rgb_matrix/animations/cycle_spiral_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_spiral_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_SPIRAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint
bool CYCLE_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_SPIRAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_SPIRAL
+#endif // ENABLE_RGB_MATRIX_CYCLE_SPIRAL
diff --git a/quantum/rgb_matrix/animations/cycle_up_down_anim.h b/quantum/rgb_matrix/animations/cycle_up_down_anim.h
index c9b5a54133..277edccb2f 100644
--- a/quantum/rgb_matrix/animations/cycle_up_down_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_up_down_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_UP_DOWN_math(HSV hsv, uint8_t i, uint8_t time) {
bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_UP_DOWN
+#endif // ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
diff --git a/quantum/rgb_matrix/animations/digital_rain_anim.h b/quantum/rgb_matrix/animations/digital_rain_anim.h
index 1de45f8e8d..8ce8fd7039 100644
--- a/quantum/rgb_matrix/animations/digital_rain_anim.h
+++ b/quantum/rgb_matrix/animations/digital_rain_anim.h
@@ -1,4 +1,4 @@
-#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_DIGITAL_RAIN)
+#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_DIGITAL_RAIN)
RGB_MATRIX_EFFECT(DIGITAL_RAIN)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
@@ -72,4 +72,4 @@ bool DIGITAL_RAIN(effect_params_t* params) {
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_DIGITAL_RAIN)
+#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(ENABLE_RGB_MATRIX_DIGITAL_RAIN)
diff --git a/quantum/rgb_matrix/animations/dual_beacon_anim.h b/quantum/rgb_matrix/animations/dual_beacon_anim.h
index 5c06080a26..dbe9b3ecf1 100644
--- a/quantum/rgb_matrix/animations/dual_beacon_anim.h
+++ b/quantum/rgb_matrix/animations/dual_beacon_anim.h
@@ -10,4 +10,4 @@ static HSV DUAL_BEACON_math(HSV hsv, int8_t sin, int8_t cos, uint8_t i, uint8_t
bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_DUAL_BEACON
+#endif // ENABLE_RGB_MATRIX_DUAL_BEACON
diff --git a/quantum/rgb_matrix/animations/gradient_left_right_anim.h b/quantum/rgb_matrix/animations/gradient_left_right_anim.h
index b4f2752ff7..8bb5e570bd 100644
--- a/quantum/rgb_matrix/animations/gradient_left_right_anim.h
+++ b/quantum/rgb_matrix/animations/gradient_left_right_anim.h
@@ -15,8 +15,8 @@ bool GRADIENT_LEFT_RIGHT(effect_params_t* params) {
RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
+#endif // ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
diff --git a/quantum/rgb_matrix/animations/gradient_up_down_anim.h b/quantum/rgb_matrix/animations/gradient_up_down_anim.h
index 3fd45cf99b..a5674583e3 100644
--- a/quantum/rgb_matrix/animations/gradient_up_down_anim.h
+++ b/quantum/rgb_matrix/animations/gradient_up_down_anim.h
@@ -15,8 +15,8 @@ bool GRADIENT_UP_DOWN(effect_params_t* params) {
RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
+#endif // ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
diff --git a/quantum/rgb_matrix/animations/hue_breathing_anim.h b/quantum/rgb_matrix/animations/hue_breathing_anim.h
index 6d974b8c39..82be1a4424 100644
--- a/quantum/rgb_matrix/animations/hue_breathing_anim.h
+++ b/quantum/rgb_matrix/animations/hue_breathing_anim.h
@@ -15,7 +15,7 @@ bool HUE_BREATHING(effect_params_t* params) {
RGB_MATRIX_TEST_LED_FLAGS();
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
index 7d8eafffb9..3ffb57eb35 100644
--- a/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
+++ b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
@@ -22,8 +22,8 @@ bool JELLYBEAN_RAINDROPS(effect_params_t* params) {
for (int i = led_min; i < led_max; i++) {
jellybean_raindrops_set_color(i, params);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
+#endif // ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
diff --git a/quantum/rgb_matrix/animations/pixel_fractal_anim.h b/quantum/rgb_matrix/animations/pixel_fractal_anim.h
new file mode 100644
index 0000000000..8e25ec402c
--- /dev/null
+++ b/quantum/rgb_matrix/animations/pixel_fractal_anim.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2021 @filterpaper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Inspired from 4x12 fractal created by @schwarzgrau
+
+#ifdef ENABLE_RGB_MATRIX_PIXEL_FRACTAL
+RGB_MATRIX_EFFECT(PIXEL_FRACTAL)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+static bool PIXEL_FRACTAL(effect_params_t* params) {
+# define MID_COL MATRIX_COLS / 2
+ static bool led[MATRIX_ROWS][MATRIX_COLS];
+
+ static uint32_t wait_timer = 0;
+ if (wait_timer > g_rgb_timer) {
+ return false;
+ }
+
+ inline uint32_t interval(void) { return 3000 / scale16by8(qadd8(rgb_matrix_config.speed, 16), 16); }
+
+ RGB rgb = rgb_matrix_hsv_to_rgb(rgb_matrix_config.hsv);
+ for (uint8_t h = 0; h < MATRIX_ROWS; ++h) {
+ for (uint8_t l = 0; l < MID_COL - 1; ++l) { // Light and move left columns outwards
+ if (led[h][l]) {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][l], rgb.r, rgb.g, rgb.b);
+ } else {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][l], 0, 0, 0);
+ }
+ led[h][l] = led[h][l + 1];
+ }
+
+ for (uint8_t r = MATRIX_COLS - 1; r > MID_COL; --r) { // Light and move right columns outwards
+ if (led[h][r]) {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][r], rgb.r, rgb.g, rgb.b);
+ } else {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][r], 0, 0, 0);
+ }
+ led[h][r] = led[h][r - 1];
+ }
+
+ // Light both middle columns
+ if (led[h][MID_COL]) {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL], rgb.r, rgb.g, rgb.b);
+ } else {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL], 0, 0, 0);
+ }
+ if (led[h][MID_COL - 1]) {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], rgb.r, rgb.g, rgb.b);
+ } else {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], 0, 0, 0);
+ }
+
+ // Generate new random fractal columns
+ led[h][MID_COL] = led[h][MID_COL - 1] = (random8() & 3) ? false : true;
+ }
+
+ wait_timer = g_rgb_timer + interval();
+ return false;
+}
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_PIXEL_FRACTAL
diff --git a/quantum/rgb_matrix/animations/pixel_rain_anim.h b/quantum/rgb_matrix/animations/pixel_rain_anim.h
new file mode 100644
index 0000000000..001649aa6e
--- /dev/null
+++ b/quantum/rgb_matrix/animations/pixel_rain_anim.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2021 @filterpaper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef ENABLE_RGB_MATRIX_PIXEL_RAIN
+RGB_MATRIX_EFFECT(PIXEL_RAIN)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+static bool PIXEL_RAIN(effect_params_t* params) {
+ static uint32_t wait_timer = 0;
+ if (wait_timer > g_rgb_timer) {
+ return false;
+ }
+
+ inline uint32_t interval(void) { return 500 / scale16by8(qadd8(rgb_matrix_config.speed, 16), 16); }
+
+ bool rain_pixel(uint8_t i, effect_params_t * params, bool off) {
+ if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) {
+ return true;
+ }
+ if (off) {
+ rgb_matrix_set_color(i, 0, 0, 0);
+ } else {
+ HSV hsv = {random8(), qadd8(random8() >> 1, 127), rgb_matrix_config.hsv.v};
+ RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
+ rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
+ }
+ wait_timer = g_rgb_timer + interval();
+ return false;
+ }
+
+ return rain_pixel(mod8(random8(), DRIVER_LED_TOTAL), params, random8() & 2);
+}
+
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_PIXEL_RAIN
diff --git a/quantum/rgb_matrix/animations/rainbow_beacon_anim.h b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
index b54d997f63..cd529958db 100644
--- a/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
@@ -10,4 +10,4 @@ static HSV RAINBOW_BEACON_math(HSV hsv, int8_t sin, int8_t cos, uint8_t i, uint8
bool RAINBOW_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &RAINBOW_BEACON_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_RAINBOW_BEACON
+#endif // ENABLE_RGB_MATRIX_RAINBOW_BEACON
diff --git a/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
index 50db922014..2f3de64e9d 100644
--- a/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
@@ -10,4 +10,4 @@ static HSV RAINBOW_MOVING_CHEVRON_math(HSV hsv, uint8_t i, uint8_t time) {
bool RAINBOW_MOVING_CHEVRON(effect_params_t* params) { return effect_runner_i(params, &RAINBOW_MOVING_CHEVRON_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
+#endif // ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
diff --git a/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
index 3299f15df1..dae2b5d190 100644
--- a/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
@@ -10,4 +10,4 @@ static HSV RAINBOW_PINWHEELS_math(HSV hsv, int8_t sin, int8_t cos, uint8_t i, ui
bool RAINBOW_PINWHEELS(effect_params_t* params) { return effect_runner_sin_cos_i(params, &RAINBOW_PINWHEELS_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS
+#endif // ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
diff --git a/quantum/rgb_matrix/animations/raindrops_anim.h b/quantum/rgb_matrix/animations/raindrops_anim.h
index c01688e2c7..4b1b9dd9ec 100644
--- a/quantum/rgb_matrix/animations/raindrops_anim.h
+++ b/quantum/rgb_matrix/animations/raindrops_anim.h
@@ -32,8 +32,8 @@ bool RAINDROPS(effect_params_t* params) {
for (int i = led_min; i < led_max; i++) {
raindrops_set_color(i, params);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_RAINDROPS
+#endif // ENABLE_RGB_MATRIX_RAINDROPS
diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
index 302ad79c04..27ce347235 100644
--- a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
+++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
@@ -26,6 +26,8 @@
#include "hue_breathing_anim.h"
#include "hue_pendulum_anim.h"
#include "hue_wave_anim.h"
+#include "pixel_rain_anim.h"
+#include "pixel_fractal_anim.h"
#include "typing_heatmap_anim.h"
#include "digital_rain_anim.h"
#include "solid_reactive_simple_anim.h"
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
index 4867609c81..2ad0f22c28 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
@@ -13,5 +13,5 @@ bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) {
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, time));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
index 9545b418d9..bcae7c79b6 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
@@ -14,5 +14,5 @@ bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func)
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, dist, time));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_i.h
index 1881cd6c60..b4de2992b6 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_i.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_i.h
@@ -11,5 +11,5 @@ bool effect_runner_i(effect_params_t* params, i_f effect_func) {
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, i, time));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
index 75b7c0df4e..d5c1a26cef 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
@@ -23,7 +23,7 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) {
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, offset));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
index 2e46ffb350..d3a6e4e72f 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
@@ -23,7 +23,7 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react
RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
index 02351de51e..7776491d51 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
@@ -13,5 +13,5 @@ bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) {
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, cos_value, sin_value, i, time));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/rgb_matrix/animations/solid_color_anim.h b/quantum/rgb_matrix/animations/solid_color_anim.h
index 79d63cf133..4209959468 100644
--- a/quantum/rgb_matrix/animations/solid_color_anim.h
+++ b/quantum/rgb_matrix/animations/solid_color_anim.h
@@ -9,7 +9,7 @@ bool SOLID_COLOR(effect_params_t* params) {
RGB_MATRIX_TEST_LED_FLAGS();
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
#endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/quantum/rgb_matrix/animations/solid_reactive_anim.h b/quantum/rgb_matrix/animations/solid_reactive_anim.h
index d45bb961bc..360d05a67a 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_anim.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_anim.h
@@ -1,5 +1,5 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE
RGB_MATRIX_EFFECT(SOLID_REACTIVE)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
@@ -11,5 +11,5 @@ static HSV SOLID_REACTIVE_math(HSV hsv, uint16_t offset) {
bool SOLID_REACTIVE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // DISABLE_RGB_MATRIX_SOLID_REACTIVE
+# endif // ENABLE_RGB_MATRIX_SOLID_REACTIVE
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_reactive_cross.h b/quantum/rgb_matrix/animations/solid_reactive_cross.h
index f76c68e8c7..496651f8a5 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_cross.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_cross.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS)
+# if defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS)
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_CROSS)
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTICROSS)
# endif
@@ -23,14 +23,14 @@ static HSV SOLID_REACTIVE_CROSS_math(HSV hsv, int16_t dx, int16_t dy, uint8_t di
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
bool SOLID_REACTIVE_CROSS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_CROSS_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_CROSS_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS)
+# endif // !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_reactive_nexus.h b/quantum/rgb_matrix/animations/solid_reactive_nexus.h
index 17f94e3c18..3562e74a72 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_nexus.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_nexus.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS)
+# if defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS)
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_NEXUS)
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTINEXUS)
# endif
@@ -21,14 +21,14 @@ static HSV SOLID_REACTIVE_NEXUS_math(HSV hsv, int16_t dx, int16_t dy, uint8_t di
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
bool SOLID_REACTIVE_NEXUS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_NEXUS_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_NEXUS_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS)
+# endif // !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
index 12eb248cc0..69189f636b 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
@@ -1,5 +1,5 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
RGB_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
@@ -11,5 +11,5 @@ static HSV SOLID_REACTIVE_SIMPLE_math(HSV hsv, uint16_t offset) {
bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
+# endif // ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_reactive_wide.h b/quantum/rgb_matrix/animations/solid_reactive_wide.h
index 1cc4dca728..a613c7ff5f 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_wide.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_wide.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE)
+# if defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE)
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
RGB_MATRIX_EFFECT(SOLID_REACTIVE_WIDE)
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTIWIDE)
# endif
@@ -18,14 +18,14 @@ static HSV SOLID_REACTIVE_WIDE_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dis
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
bool SOLID_REACTIVE_WIDE(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_WIDE_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_WIDE_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE)
+# endif // !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_splash_anim.h b/quantum/rgb_matrix/animations/solid_splash_anim.h
index 99efb4996a..bd9c1cfe2b 100644
--- a/quantum/rgb_matrix/animations/solid_splash_anim.h
+++ b/quantum/rgb_matrix/animations/solid_splash_anim.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SOLID_SPLASH) || !defined(DISABLE_RGB_MATRIX_SOLID_MULTISPLASH)
+# if defined(ENABLE_RGB_MATRIX_SOLID_SPLASH) || defined(ENABLE_RGB_MATRIX_SOLID_MULTISPLASH)
-# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
+# ifdef ENABLE_RGB_MATRIX_SOLID_SPLASH
RGB_MATRIX_EFFECT(SOLID_SPLASH)
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
+# ifdef ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
RGB_MATRIX_EFFECT(SOLID_MULTISPLASH)
# endif
@@ -18,14 +18,14 @@ HSV SOLID_SPLASH_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t ti
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
+# ifdef ENABLE_RGB_MATRIX_SOLID_SPLASH
bool SOLID_SPLASH(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_SPLASH_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
+# ifdef ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SPLASH) && !defined(DISABLE_RGB_MATRIX_MULTISPLASH)
+# endif // !defined(ENABLE_RGB_MATRIX_SPLASH) && !defined(ENABLE_RGB_MATRIX_MULTISPLASH)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/splash_anim.h b/quantum/rgb_matrix/animations/splash_anim.h
index 1415bcc0fa..382355e9ed 100644
--- a/quantum/rgb_matrix/animations/splash_anim.h
+++ b/quantum/rgb_matrix/animations/splash_anim.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SPLASH) || !defined(DISABLE_RGB_MATRIX_MULTISPLASH)
+# if defined(ENABLE_RGB_MATRIX_SPLASH) || defined(ENABLE_RGB_MATRIX_MULTISPLASH)
-# ifndef DISABLE_RGB_MATRIX_SPLASH
+# ifdef ENABLE_RGB_MATRIX_SPLASH
RGB_MATRIX_EFFECT(SPLASH)
# endif
-# ifndef DISABLE_RGB_MATRIX_MULTISPLASH
+# ifdef ENABLE_RGB_MATRIX_MULTISPLASH
RGB_MATRIX_EFFECT(MULTISPLASH)
# endif
@@ -19,14 +19,14 @@ HSV SPLASH_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) {
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SPLASH
+# ifdef ENABLE_RGB_MATRIX_SPLASH
bool SPLASH(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SPLASH_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_MULTISPLASH
+# ifdef ENABLE_RGB_MATRIX_MULTISPLASH
bool MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SPLASH_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SPLASH) || !defined(DISABLE_RGB_MATRIX_MULTISPLASH)
+# endif // !defined(ENABLE_RGB_MATRIX_SPLASH) || !defined(ENABLE_RGB_MATRIX_MULTISPLASH)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/typing_heatmap_anim.h b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
index 28f040109d..b66667b9b8 100644
--- a/quantum/rgb_matrix/animations/typing_heatmap_anim.h
+++ b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
@@ -83,4 +83,4 @@ bool TYPING_HEATMAP(effect_params_t* params) {
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_TYPING_HEATMAP)
+#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_TYPING_HEATMAP)
diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c
index 8f00b40877..558c7bd41a 100644
--- a/quantum/rgb_matrix/rgb_matrix.c
+++ b/quantum/rgb_matrix/rgb_matrix.c
@@ -31,14 +31,6 @@ const led_point_t k_rgb_matrix_center = {112, 32};
const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER;
#endif
-// clang-format off
-#ifndef RGB_MATRIX_IMMEDIATE_EEPROM
-# define rgb_eeconfig_update(v) rgb_update_eeprom |= v
-#else
-# define rgb_eeconfig_update(v) if (v) eeconfig_update_rgb_matrix()
-#endif
-// clang-format on
-
__attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); }
// Generic effect runners
@@ -128,7 +120,6 @@ last_hit_t g_last_hit_tracker;
// internals
static bool suspend_state = false;
-static bool rgb_update_eeprom = false;
static uint8_t rgb_last_enable = UINT8_MAX;
static uint8_t rgb_last_effect = UINT8_MAX;
static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false};
@@ -148,9 +139,9 @@ static last_hit_t last_hit_buffer;
const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
#endif
-void eeconfig_read_rgb_matrix(void) { eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); }
+EECONFIG_DEBOUNCE_HELPER(rgb_matrix, EECONFIG_RGB_MATRIX, rgb_matrix_config);
-void eeconfig_update_rgb_matrix(void) { eeprom_update_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); }
+void eeconfig_update_rgb_matrix(void) { eeconfig_flush_rgb_matrix(true); }
void eeconfig_update_rgb_matrix_default(void) {
dprintf("eeconfig_update_rgb_matrix_default\n");
@@ -159,7 +150,7 @@ void eeconfig_update_rgb_matrix_default(void) {
rgb_matrix_config.hsv = (HSV){RGB_MATRIX_STARTUP_HUE, RGB_MATRIX_STARTUP_SAT, RGB_MATRIX_STARTUP_VAL};
rgb_matrix_config.speed = RGB_MATRIX_STARTUP_SPD;
rgb_matrix_config.flags = LED_FLAG_ALL;
- eeconfig_update_rgb_matrix();
+ eeconfig_flush_rgb_matrix(true);
}
void eeconfig_debug_rgb_matrix(void) {
@@ -187,14 +178,7 @@ uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l
void rgb_matrix_update_pwm_buffers(void) { rgb_matrix_driver.flush(); }
-void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
-#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
- if (!is_keyboard_left() && index >= k_rgb_matrix_split[0])
- rgb_matrix_driver.set_color(index - k_rgb_matrix_split[0], red, green, blue);
- else if (is_keyboard_left() && index < k_rgb_matrix_split[0])
-#endif
- rgb_matrix_driver.set_color(index, red, green, blue);
-}
+void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color(index, red, green, blue); }
void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
@@ -314,9 +298,8 @@ static void rgb_task_timers(void) {
}
static void rgb_task_sync(void) {
+ eeconfig_flush_rgb_matrix(false);
// next task
- if (rgb_update_eeprom) eeconfig_update_rgb_matrix();
- rgb_update_eeprom = false;
if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING;
}
@@ -491,7 +474,7 @@ void rgb_matrix_init(void) {
eeconfig_update_rgb_matrix_default();
}
- eeconfig_read_rgb_matrix();
+ eeconfig_init_rgb_matrix();
if (!rgb_matrix_config.mode) {
dprintf("rgb_matrix_init_drivers rgb_matrix_config.mode = 0. Write default values to EEPROM.\n");
eeconfig_update_rgb_matrix_default();
@@ -514,7 +497,7 @@ bool rgb_matrix_get_suspend_state(void) { return suspend_state; }
void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
rgb_matrix_config.enable ^= 1;
rgb_task_state = STARTING;
- rgb_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_rgb_matrix(write_to_eeprom);
dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable);
}
void rgb_matrix_toggle_noeeprom(void) { rgb_matrix_toggle_eeprom_helper(false); }
@@ -522,7 +505,7 @@ void rgb_matrix_toggle(void) { rgb_matrix_toggle_eeprom_helper(true); }
void rgb_matrix_enable(void) {
rgb_matrix_enable_noeeprom();
- rgb_eeconfig_update(true);
+ eeconfig_flag_rgb_matrix(true);
}
void rgb_matrix_enable_noeeprom(void) {
@@ -532,7 +515,7 @@ void rgb_matrix_enable_noeeprom(void) {
void rgb_matrix_disable(void) {
rgb_matrix_disable_noeeprom();
- rgb_eeconfig_update(true);
+ eeconfig_flag_rgb_matrix(true);
}
void rgb_matrix_disable_noeeprom(void) {
@@ -554,7 +537,7 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
rgb_matrix_config.mode = mode;
}
rgb_task_state = STARTING;
- rgb_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_rgb_matrix(write_to_eeprom);
dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode);
}
void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); }
@@ -583,7 +566,7 @@ void rgb_matrix_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, boo
rgb_matrix_config.hsv.h = hue;
rgb_matrix_config.hsv.s = sat;
rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val;
- rgb_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_rgb_matrix(write_to_eeprom);
dprintf("rgb matrix set hsv [%s]: %u,%u,%u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v);
}
void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); }
@@ -620,7 +603,7 @@ void rgb_matrix_decrease_val(void) { rgb_matrix_decrease_val_helper(true); }
void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
rgb_matrix_config.speed = speed;
- rgb_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_rgb_matrix(write_to_eeprom);
dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed);
}
void rgb_matrix_set_speed_noeeprom(uint8_t speed) { rgb_matrix_set_speed_eeprom_helper(speed, false); }
diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h
index f53e011c1b..a804d99abc 100644
--- a/quantum/rgb_matrix/rgb_matrix.h
+++ b/quantum/rgb_matrix/rgb_matrix.h
@@ -23,7 +23,6 @@
#include "rgb_matrix_types.h"
#include "color.h"
#include "quantum.h"
-#include "rgb_matrix_legacy_enables.h"
#ifdef IS31FL3731
# include "is31fl3731.h"
@@ -33,6 +32,8 @@
# include "is31fl3737.h"
#elif defined(IS31FL3741)
# include "is31fl3741.h"
+#elif defined(CKLED2001)
+# include "ckled2001.h"
#elif defined(AW20216)
# include "aw20216.h"
#elif defined(WS2812)
@@ -48,14 +49,33 @@
#endif
#if defined(RGB_MATRIX_LED_PROCESS_LIMIT) && RGB_MATRIX_LED_PROCESS_LIMIT > 0 && RGB_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL
-# define RGB_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter; \
- uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \
- if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
+# if defined(RGB_MATRIX_SPLIT)
+# define RGB_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter; \
+ uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \
+ if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; \
+ uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; \
+ if (is_keyboard_left() && (max > k_rgb_matrix_split[0])) max = k_rgb_matrix_split[0]; \
+ if (!(is_keyboard_left()) && (min < k_rgb_matrix_split[0])) min = k_rgb_matrix_split[0];
+# else
+# define RGB_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter; \
+ uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \
+ if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
+# endif
#else
-# define RGB_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = 0; \
- uint8_t max = DRIVER_LED_TOTAL;
+# if defined(RGB_MATRIX_SPLIT)
+# define RGB_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = 0; \
+ uint8_t max = DRIVER_LED_TOTAL; \
+ const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; \
+ if (is_keyboard_left() && (max > k_rgb_matrix_split[0])) max = k_rgb_matrix_split[0]; \
+ if (!(is_keyboard_left()) && (min < k_rgb_matrix_split[0])) min = k_rgb_matrix_split[0];
+# else
+# define RGB_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = 0; \
+ uint8_t max = DRIVER_LED_TOTAL;
+# endif
#endif
#define RGB_MATRIX_INDICATOR_SET_COLOR(i, r, g, b) \
@@ -214,6 +234,18 @@ typedef struct {
void (*flush)(void);
} rgb_matrix_driver_t;
+static inline bool rgb_matrix_check_finished_leds(uint8_t led_idx) {
+#if defined(RGB_MATRIX_SPLIT)
+ if (is_keyboard_left()) {
+ uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
+ return led_idx < k_rgb_matrix_split[0];
+ } else
+ return led_idx < DRIVER_LED_TOTAL;
+#else
+ return led_idx < DRIVER_LED_TOTAL;
+#endif
+}
+
extern const rgb_matrix_driver_t rgb_matrix_driver;
extern rgb_config_t rgb_matrix_config;
diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c
index 2cec162e22..130ca47a63 100644
--- a/quantum/rgb_matrix/rgb_matrix_drivers.c
+++ b/quantum/rgb_matrix/rgb_matrix_drivers.c
@@ -23,111 +23,153 @@
* be here if shared between boards.
*/
-#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3737) || defined(IS31FL3741)
-
+#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3737) || defined(IS31FL3741) || defined(CKLED2001)
# include "i2c_master.h"
+// TODO: Remove this at some later date
+# if defined(DRIVER_ADDR_1) && defined(DRIVER_ADDR_2)
+# if DRIVER_ADDR_1 == DRIVER_ADDR_2
+# error "Setting DRIVER_ADDR_2 == DRIVER_ADDR_1 is obsolete. If you are only using one ISSI driver, set DRIVER_COUNT to 1 and remove DRIVER_ADDR_2"
+# endif
+# endif
+
static void init(void) {
i2c_init();
-# ifdef IS31FL3731
+
+# if defined(IS31FL3731)
IS31FL3731_init(DRIVER_ADDR_1);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3731_init(DRIVER_ADDR_2);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3731_init(DRIVER_ADDR_3);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3731_init(DRIVER_ADDR_4);
+# endif
+# endif
# endif
+
# elif defined(IS31FL3733)
-# ifndef DRIVER_SYNC_1
+# if !defined(DRIVER_SYNC_1)
# define DRIVER_SYNC_1 0
# endif
IS31FL3733_init(DRIVER_ADDR_1, DRIVER_SYNC_1);
-# if defined DRIVER_ADDR_2 && (DRIVER_ADDR_1 != DRIVER_ADDR_2)
-# ifndef DRIVER_SYNC_2
+# if defined(DRIVER_ADDR_2)
+# if !defined(DRIVER_SYNC_2)
# define DRIVER_SYNC_2 0
# endif
IS31FL3733_init(DRIVER_ADDR_2, DRIVER_SYNC_2);
-# endif
-# ifdef DRIVER_ADDR_3
-# ifndef DRIVER_SYNC_3
-# define DRIVER_SYNC_3 0
-# endif
+# if defined(DRIVER_ADDR_3)
+# if !defined(DRIVER_SYNC_3)
+# define DRIVER_SYNC_3 0
+# endif
IS31FL3733_init(DRIVER_ADDR_3, DRIVER_SYNC_3);
-# endif
-# ifdef DRIVER_ADDR_4
-# ifndef DRIVER_SYNC_4
-# define DRIVER_SYNC_4 0
-# endif
+# if defined(DRIVER_ADDR_4)
+# if !defined(DRIVER_SYNC_4)
+# define DRIVER_SYNC_4 0
+# endif
IS31FL3733_init(DRIVER_ADDR_4, DRIVER_SYNC_4);
+# endif
+# endif
# endif
+
# elif defined(IS31FL3737)
IS31FL3737_init(DRIVER_ADDR_1);
-# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
+# if defined(DRIVER_ADDR_2)
IS31FL3737_init(DRIVER_ADDR_2);
# endif
-# else
+
+# elif defined(IS31FL3741)
IS31FL3741_init(DRIVER_ADDR_1);
+
+# elif defined(CKLED2001)
+ CKLED2001_init(DRIVER_ADDR_1);
+# if defined(DRIVER_ADDR_2)
+ CKLED2001_init(DRIVER_ADDR_2);
+# if defined(DRIVER_ADDR_3)
+ CKLED2001_init(DRIVER_ADDR_3);
+# if defined(DRIVER_ADDR_4)
+ CKLED2001_init(DRIVER_ADDR_4);
+# endif
+# endif
+# endif
# endif
+
for (int index = 0; index < DRIVER_LED_TOTAL; index++) {
bool enabled = true;
+
// This only caches it for later
-# ifdef IS31FL3731
+# if defined(IS31FL3731)
IS31FL3731_set_led_control_register(index, enabled, enabled, enabled);
# elif defined(IS31FL3733)
IS31FL3733_set_led_control_register(index, enabled, enabled, enabled);
# elif defined(IS31FL3737)
IS31FL3737_set_led_control_register(index, enabled, enabled, enabled);
-# else
+# elif defined(IS31FL3741)
IS31FL3741_set_led_control_register(index, enabled, enabled, enabled);
+# elif defined(CKLED2001)
+ CKLED2001_set_led_control_register(index, enabled, enabled, enabled);
# endif
}
+
// This actually updates the LED drivers
-# ifdef IS31FL3731
+# if defined(IS31FL3731)
IS31FL3731_update_led_control_registers(DRIVER_ADDR_1, 0);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3731_update_led_control_registers(DRIVER_ADDR_2, 1);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3731_update_led_control_registers(DRIVER_ADDR_3, 2);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3731_update_led_control_registers(DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
+
# elif defined(IS31FL3733)
IS31FL3733_update_led_control_registers(DRIVER_ADDR_1, 0);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3733_update_led_control_registers(DRIVER_ADDR_2, 1);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3733_update_led_control_registers(DRIVER_ADDR_3, 2);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
+
# elif defined(IS31FL3737)
IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
+# if defined(DRIVER_ADDR_2)
IS31FL3737_update_led_control_registers(DRIVER_ADDR_2, 1);
# endif
-# else
+
+# elif defined(IS31FL3741)
IS31FL3741_update_led_control_registers(DRIVER_ADDR_1, 0);
+
+# elif defined(CKLED2001)
+ CKLED2001_update_led_control_registers(DRIVER_ADDR_1, 0);
+# if defined(DRIVER_ADDR_2)
+ CKLED2001_update_led_control_registers(DRIVER_ADDR_2, 1);
+# if defined(DRIVER_ADDR_3)
+ CKLED2001_update_led_control_registers(DRIVER_ADDR_3, 2);
+# if defined(DRIVER_ADDR_4)
+ CKLED2001_update_led_control_registers(DRIVER_ADDR_4, 3);
+# endif
+# endif
+# endif
# endif
}
-# ifdef IS31FL3731
+# if defined(IS31FL3731)
static void flush(void) {
IS31FL3731_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3731_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3731_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3731_update_pwm_buffers(DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
}
@@ -137,17 +179,18 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = IS31FL3731_set_color,
.set_color_all = IS31FL3731_set_color_all,
};
+
# elif defined(IS31FL3733)
static void flush(void) {
IS31FL3733_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3733_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3733_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3733_update_pwm_buffers(DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
}
@@ -157,10 +200,11 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = IS31FL3733_set_color,
.set_color_all = IS31FL3733_set_color_all,
};
+
# elif defined(IS31FL3737)
static void flush(void) {
IS31FL3737_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
+# if defined(DRIVER_ADDR_2)
IS31FL3737_update_pwm_buffers(DRIVER_ADDR_2, 1);
# endif
}
@@ -171,10 +215,11 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = IS31FL3737_set_color,
.set_color_all = IS31FL3737_set_color_all,
};
-# else
+
+# elif defined(IS31FL3741)
static void flush(void) {
IS31FL3741_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
+# if defined(DRIVER_ADDR_2)
IS31FL3741_update_pwm_buffers(DRIVER_ADDR_2, 1);
# endif
}
@@ -185,21 +230,44 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = IS31FL3741_set_color,
.set_color_all = IS31FL3741_set_color_all,
};
+
+# elif defined(CKLED2001)
+static void flush(void) {
+ CKLED2001_update_pwm_buffers(DRIVER_ADDR_1, 0);
+# if defined(DRIVER_ADDR_2)
+ CKLED2001_update_pwm_buffers(DRIVER_ADDR_2, 1);
+# if defined(DRIVER_ADDR_3)
+ CKLED2001_update_pwm_buffers(DRIVER_ADDR_3, 2);
+# if defined(DRIVER_ADDR_4)
+ CKLED2001_update_pwm_buffers(DRIVER_ADDR_4, 3);
+# endif
+# endif
+# endif
+}
+
+const rgb_matrix_driver_t rgb_matrix_driver = {
+ .init = init,
+ .flush = flush,
+ .set_color = CKLED2001_set_color,
+ .set_color_all = CKLED2001_set_color_all,
+};
# endif
#elif defined(AW20216)
# include "spi_master.h"
+
static void init(void) {
spi_init();
+
AW20216_init(DRIVER_1_CS, DRIVER_1_EN);
-# ifdef DRIVER_2_CS
+# if defined(DRIVER_2_CS)
AW20216_init(DRIVER_2_CS, DRIVER_2_EN);
# endif
}
static void flush(void) {
AW20216_update_pwm_buffers(DRIVER_1_CS, 0);
-# ifdef DRIVER_2_CS
+# if defined(DRIVER_2_CS)
AW20216_update_pwm_buffers(DRIVER_2_CS, 1);
# endif
}
@@ -229,6 +297,14 @@ static void flush(void) {
// Set an led in the buffer to a color
static inline void setled(int i, uint8_t r, uint8_t g, uint8_t b) {
+# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
+ const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
+ if (!is_keyboard_left() && (i >= k_rgb_matrix_split[0])) {
+ i -= k_rgb_matrix_split[0];
+ } else if (is_keyboard_left() && (i >= k_rgb_matrix_split[0]))
+ return;
+# endif
+
rgb_matrix_ws2812_array[i].r = r;
rgb_matrix_ws2812_array[i].g = g;
rgb_matrix_ws2812_array[i].b = b;
diff --git a/quantum/rgb_matrix/rgb_matrix_legacy_enables.h b/quantum/rgb_matrix/rgb_matrix_legacy_enables.h
deleted file mode 100644
index 398858ebc8..0000000000
--- a/quantum/rgb_matrix/rgb_matrix_legacy_enables.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* Copyright 2021 QMK
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-// to-do: remove this
-
-#pragma once
-
-#ifndef DISABLE_RGB_MATRIX_ALPHAS_MODS
-# define ENABLE_RGB_MATRIX_ALPHAS_MODS
-#endif
-#ifndef DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
-# define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
-#endif
-#ifndef DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
-# define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
-#endif
-#ifndef DISABLE_RGB_MATRIX_BREATHING
-# define ENABLE_RGB_MATRIX_BREATHING
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_SAT
-# define ENABLE_RGB_MATRIX_BAND_SAT
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_VAL
-# define ENABLE_RGB_MATRIX_BAND_VAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
-# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
-# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
-# define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_SPIRAL_VAL
-# define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_ALL
-# define ENABLE_RGB_MATRIX_CYCLE_ALL
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
-# define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_UP_DOWN
-# define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
-#endif
-#ifndef DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
-# define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_OUT_IN
-# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
-# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_PINWHEEL
-# define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_SPIRAL
-# define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_DUAL_BEACON
-# define ENABLE_RGB_MATRIX_DUAL_BEACON
-#endif
-#ifndef DISABLE_RGB_MATRIX_RAINBOW_BEACON
-# define ENABLE_RGB_MATRIX_RAINBOW_BEACON
-#endif
-#ifndef DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS
-# define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
-#endif
-#ifndef DISABLE_RGB_MATRIX_RAINDROPS
-# define ENABLE_RGB_MATRIX_RAINDROPS
-#endif
-#ifndef DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
-# define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
-#endif
-#ifndef DISABLE_RGB_MATRIX_HUE_BREATHING
-# define ENABLE_RGB_MATRIX_HUE_BREATHING
-#endif
-#ifndef DISABLE_RGB_MATRIX_HUE_PENDULUM
-# define ENABLE_RGB_MATRIX_HUE_PENDULUM
-#endif
-#ifndef DISABLE_RGB_MATRIX_HUE_WAVE
-# define ENABLE_RGB_MATRIX_HUE_WAVE
-#endif
-#ifndef DISABLE_RGB_MATRIX_PIXEL_RAIN
-# define ENABLE_RGB_MATRIX_PIXEL_RAIN
-#endif
-#ifndef DISABLE_RGB_MATRIX_PIXEL_FLOW
-# define ENABLE_RGB_MATRIX_PIXEL_FLOW
-#endif
-#ifndef DISABLE_RGB_MATRIX_PIXEL_FRACTAL
-# define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
-#endif
-#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS)
-# ifndef DISABLE_RGB_MATRIX_TYPING_HEATMAP
-# define ENABLE_RGB_MATRIX_TYPING_HEATMAP
-# endif
-# ifndef DISABLE_RGB_MATRIX_DIGITAL_RAIN
-# define ENABLE_RGB_MATRIX_DIGITAL_RAIN
-# endif
-#endif
-#if defined(RGB_MATRIX_KEYREACTIVE_ENABLED)
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
-# endif
-# ifndef DISABLE_RGB_MATRIX_SPLASH
-# define ENABLE_RGB_MATRIX_SPLASH
-# endif
-# ifndef DISABLE_RGB_MATRIX_MULTISPLASH
-# define ENABLE_RGB_MATRIX_MULTISPLASH
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
-# define ENABLE_RGB_MATRIX_SOLID_SPLASH
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
-# define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
-# endif
-#endif
diff --git a/quantum/sequencer/tests/rules.mk b/quantum/sequencer/tests/rules.mk
index 76c221cf92..a3bbd80513 100644
--- a/quantum/sequencer/tests/rules.mk
+++ b/quantum/sequencer/tests/rules.mk
@@ -1,5 +1,5 @@
# The letter case of these variables might seem odd. However:
-# - it is consistent with the serial_link example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features)
+# - it is consistent with the example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features)
# - Neither `make test:sequencer` or `make test:SEQUENCER` work when using SCREAMING_SNAKE_CASE
sequencer_DEFS := -DNO_DEBUG -DMIDI_MOCKED
@@ -8,4 +8,4 @@ sequencer_SRC := \
$(QUANTUM_PATH)/sequencer/tests/midi_mock.c \
$(QUANTUM_PATH)/sequencer/tests/sequencer_tests.cpp \
$(QUANTUM_PATH)/sequencer/sequencer.c \
- $(TMK_PATH)/common/test/timer.c
+ $(PLATFORM_PATH)/$(PLATFORM_KEY)/timer.c
diff --git a/quantum/serial_link/LICENSE b/quantum/serial_link/LICENSE
deleted file mode 100644
index d13cc4b26a..0000000000
--- a/quantum/serial_link/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-The MIT License (MIT)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/quantum/serial_link/README.md b/quantum/serial_link/README.md
deleted file mode 100644
index 05871dbdf7..0000000000
--- a/quantum/serial_link/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# qmk_serial_link
diff --git a/quantum/serial_link/protocol/byte_stuffer.c b/quantum/serial_link/protocol/byte_stuffer.c
deleted file mode 100644
index d3a91d8286..0000000000
--- a/quantum/serial_link/protocol/byte_stuffer.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/byte_stuffer.h"
-#include "serial_link/protocol/frame_validator.h"
-#include "serial_link/protocol/physical.h"
-#include <stdbool.h>
-
-// This implements the "Consistent overhead byte stuffing protocol"
-// https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
-// http://www.stuartcheshire.org/papers/COBSforToN.pdf
-
-typedef struct byte_stuffer_state {
- uint16_t next_zero;
- uint16_t data_pos;
- bool long_frame;
- uint8_t data[MAX_FRAME_SIZE];
-} byte_stuffer_state_t;
-
-static byte_stuffer_state_t states[NUM_LINKS];
-
-void init_byte_stuffer_state(byte_stuffer_state_t* state) {
- state->next_zero = 0;
- state->data_pos = 0;
- state->long_frame = false;
-}
-
-void init_byte_stuffer(void) {
- int i;
- for (i = 0; i < NUM_LINKS; i++) {
- init_byte_stuffer_state(&states[i]);
- }
-}
-
-void byte_stuffer_recv_byte(uint8_t link, uint8_t data) {
- byte_stuffer_state_t* state = &states[link];
- // Start of a new frame
- if (state->next_zero == 0) {
- state->next_zero = data;
- state->long_frame = data == 0xFF;
- state->data_pos = 0;
- return;
- }
-
- state->next_zero--;
- if (data == 0) {
- if (state->next_zero == 0) {
- // The frame is completed
- if (state->data_pos > 0) {
- validator_recv_frame(link, state->data, state->data_pos);
- }
- } else {
- // The frame is invalid, so reset
- init_byte_stuffer_state(state);
- }
- } else {
- if (state->data_pos == MAX_FRAME_SIZE) {
- // We exceeded our maximum frame size
- // therefore there's nothing else to do than reset to a new frame
- state->next_zero = data;
- state->long_frame = data == 0xFF;
- state->data_pos = 0;
- } else if (state->next_zero == 0) {
- if (state->long_frame) {
- // This is part of a long frame, so continue
- state->next_zero = data;
- state->long_frame = data == 0xFF;
- } else {
- // Special case for zeroes
- state->next_zero = data;
- state->data[state->data_pos++] = 0;
- }
- } else {
- state->data[state->data_pos++] = data;
- }
- }
-}
-
-static void send_block(uint8_t link, uint8_t* start, uint8_t* end, uint8_t num_non_zero) {
- send_data(link, &num_non_zero, 1);
- if (end > start) {
- send_data(link, start, end - start);
- }
-}
-
-void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
- const uint8_t zero = 0;
- if (size > 0) {
- uint16_t num_non_zero = 1;
- uint8_t* end = data + size;
- uint8_t* start = data;
- while (data < end) {
- if (num_non_zero == 0xFF) {
- // There's more data after big non-zero block
- // So send it, and start a new block
- send_block(link, start, data, num_non_zero);
- start = data;
- num_non_zero = 1;
- } else {
- if (*data == 0) {
- // A zero encountered, so send the block
- send_block(link, start, data, num_non_zero);
- start = data + 1;
- num_non_zero = 1;
- } else {
- num_non_zero++;
- }
- ++data;
- }
- }
- send_block(link, start, data, num_non_zero);
- send_data(link, &zero, 1);
- }
-}
diff --git a/quantum/serial_link/protocol/byte_stuffer.h b/quantum/serial_link/protocol/byte_stuffer.h
deleted file mode 100644
index 397ed3baae..0000000000
--- a/quantum/serial_link/protocol/byte_stuffer.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-
-#define MAX_FRAME_SIZE 1024
-#define NUM_LINKS 2
-
-void init_byte_stuffer(void);
-void byte_stuffer_recv_byte(uint8_t link, uint8_t data);
-void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/frame_router.c b/quantum/serial_link/protocol/frame_router.c
deleted file mode 100644
index 5292673700..0000000000
--- a/quantum/serial_link/protocol/frame_router.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/frame_router.h"
-#include "serial_link/protocol/transport.h"
-#include "serial_link/protocol/frame_validator.h"
-
-static bool is_master;
-
-void router_set_master(bool master) { is_master = master; }
-
-void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) {
- if (is_master) {
- if (link == DOWN_LINK) {
- transport_recv_frame(data[size - 1], data, size - 1);
- }
- } else {
- if (link == UP_LINK) {
- if (data[size - 1] & 1) {
- transport_recv_frame(0, data, size - 1);
- }
- data[size - 1] >>= 1;
- validator_send_frame(DOWN_LINK, data, size);
- } else {
- data[size - 1]++;
- validator_send_frame(UP_LINK, data, size);
- }
- }
-}
-
-void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
- if (destination == 0) {
- if (!is_master) {
- data[size] = 1;
- validator_send_frame(UP_LINK, data, size + 1);
- }
- } else {
- if (is_master) {
- data[size] = destination;
- validator_send_frame(DOWN_LINK, data, size + 1);
- }
- }
-}
diff --git a/quantum/serial_link/protocol/frame_router.h b/quantum/serial_link/protocol/frame_router.h
deleted file mode 100644
index 9325fe4eed..0000000000
--- a/quantum/serial_link/protocol/frame_router.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#define UP_LINK 0
-#define DOWN_LINK 1
-
-void router_set_master(bool master);
-void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size);
-void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/frame_validator.c b/quantum/serial_link/protocol/frame_validator.c
deleted file mode 100644
index bc9136f70b..0000000000
--- a/quantum/serial_link/protocol/frame_validator.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/frame_validator.h"
-#include "serial_link/protocol/frame_router.h"
-#include "serial_link/protocol/byte_stuffer.h"
-#include <string.h>
-
-const uint32_t poly8_lookup[256] = {0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
- 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
- 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
- 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
-
-static uint32_t crc32_byte(uint8_t* p, uint32_t bytelength) {
- uint32_t crc = 0xffffffff;
- while (bytelength-- != 0) crc = poly8_lookup[((uint8_t)crc ^ *(p++))] ^ (crc >> 8);
- // return (~crc); also works
- return (crc ^ 0xffffffff);
-}
-
-void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) {
- if (size > 4) {
- uint32_t frame_crc;
- memcpy(&frame_crc, data + size - 4, 4);
- uint32_t expected_crc = crc32_byte(data, size - 4);
- if (frame_crc == expected_crc) {
- route_incoming_frame(link, data, size - 4);
- }
- }
-}
-
-void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
- uint32_t crc = crc32_byte(data, size);
- memcpy(data + size, &crc, 4);
- byte_stuffer_send_frame(link, data, size + 4);
-}
diff --git a/quantum/serial_link/protocol/frame_validator.h b/quantum/serial_link/protocol/frame_validator.h
deleted file mode 100644
index 0f78768a00..0000000000
--- a/quantum/serial_link/protocol/frame_validator.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-
-void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size);
-// The buffer pointed to by the data needs 4 additional bytes
-void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/physical.h b/quantum/serial_link/protocol/physical.h
deleted file mode 100644
index 399c9d1f76..0000000000
--- a/quantum/serial_link/protocol/physical.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-void send_data(uint8_t link, const uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/transport.c b/quantum/serial_link/protocol/transport.c
deleted file mode 100644
index 73b8dc62e9..0000000000
--- a/quantum/serial_link/protocol/transport.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/transport.h"
-#include "serial_link/protocol/frame_router.h"
-#include "serial_link/protocol/triple_buffered_object.h"
-#include <string.h>
-
-#define MAX_REMOTE_OBJECTS 16
-static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS];
-static uint32_t num_remote_objects = 0;
-
-void reinitialize_serial_link_transport(void) { num_remote_objects = 0; }
-
-void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) {
- unsigned int i;
- for (i = 0; i < _num_remote_objects; i++) {
- remote_object_t* obj = _remote_objects[i];
- remote_objects[num_remote_objects++] = obj;
- if (obj->object_type == MASTER_TO_ALL_SLAVES) {
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer;
- triple_buffer_init(tb);
- uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
- tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- } else if (obj->object_type == MASTER_TO_SINGLE_SLAVE) {
- uint8_t* start = obj->buffer;
- unsigned int j;
- for (j = 0; j < NUM_SLAVES; j++) {
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- start += LOCAL_OBJECT_SIZE(obj->object_size);
- }
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- } else {
- uint8_t* start = obj->buffer;
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- start += LOCAL_OBJECT_SIZE(obj->object_size);
- unsigned int j;
- for (j = 0; j < NUM_SLAVES; j++) {
- tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- start += REMOTE_OBJECT_SIZE(obj->object_size);
- }
- }
- }
-}
-
-void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) {
- uint8_t id = data[size - 1];
- if (id < num_remote_objects) {
- remote_object_t* obj = remote_objects[id];
- if (obj->object_size == size - 1) {
- uint8_t* start;
- if (obj->object_type == MASTER_TO_ALL_SLAVES) {
- start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
- } else if (obj->object_type == SLAVE_TO_MASTER) {
- start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
- start += (from - 1) * REMOTE_OBJECT_SIZE(obj->object_size);
- } else {
- start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);
- }
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- void* ptr = triple_buffer_begin_write_internal(obj->object_size, tb);
- memcpy(ptr, data, size - 1);
- triple_buffer_end_write_internal(tb);
- }
- }
-}
-
-void update_transport(void) {
- unsigned int i;
- for (i = 0; i < num_remote_objects; i++) {
- remote_object_t* obj = remote_objects[i];
- if (obj->object_type == MASTER_TO_ALL_SLAVES || obj->object_type == SLAVE_TO_MASTER) {
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer;
- uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb);
- if (ptr) {
- ptr[obj->object_size] = i;
- uint8_t dest = obj->object_type == MASTER_TO_ALL_SLAVES ? 0xFF : 0;
- router_send_frame(dest, ptr, obj->object_size + 1);
- }
- } else {
- uint8_t* start = obj->buffer;
- unsigned int j;
- for (j = 0; j < NUM_SLAVES; j++) {
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb);
- if (ptr) {
- ptr[obj->object_size] = i;
- uint8_t dest = j + 1;
- router_send_frame(dest, ptr, obj->object_size + 1);
- }
- start += LOCAL_OBJECT_SIZE(obj->object_size);
- }
- }
- }
-}
diff --git a/quantum/serial_link/protocol/transport.h b/quantum/serial_link/protocol/transport.h
deleted file mode 100644
index 3ce0c9fe4e..0000000000
--- a/quantum/serial_link/protocol/transport.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include "serial_link/protocol/triple_buffered_object.h"
-#include "serial_link/system/serial_link.h"
-
-#define NUM_SLAVES 8
-#define LOCAL_OBJECT_EXTRA 16
-
-// master -> slave = 1 local(target all), 1 remote object
-// slave -> master = 1 local(target 0), multiple remote objects
-// master -> single slave (multiple local, target id), 1 remote object
-typedef enum {
- MASTER_TO_ALL_SLAVES,
- MASTER_TO_SINGLE_SLAVE,
- SLAVE_TO_MASTER,
-} remote_object_type;
-
-typedef struct {
- remote_object_type object_type;
- uint16_t object_size;
- uint8_t buffer[] __attribute__((aligned(4)));
-} remote_object_t;
-
-#define REMOTE_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + objectsize * 3)
-#define LOCAL_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + (objectsize + LOCAL_OBJECT_EXTRA) * 3)
-
-#define REMOTE_OBJECT_HELPER(name, type, num_local, num_remote) \
- typedef struct { \
- remote_object_t object; \
- uint8_t buffer[num_remote * REMOTE_OBJECT_SIZE(sizeof(type)) + num_local * LOCAL_OBJECT_SIZE(sizeof(type))]; \
- } remote_object_##name##_t;
-
-#define MASTER_TO_ALL_SLAVES_OBJECT(name, type) \
- REMOTE_OBJECT_HELPER(name, type, 1, 1) \
- remote_object_##name##_t remote_object_##name = {.object = { \
- .object_type = MASTER_TO_ALL_SLAVES, \
- .object_size = sizeof(type), \
- }}; \
- type* begin_write_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
- return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
- } \
- void end_write_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
- triple_buffer_end_write_internal(tb); \
- signal_data_written(); \
- } \
- type* read_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return (type*)triple_buffer_read_internal(obj->object_size, tb); \
- }
-
-#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \
- REMOTE_OBJECT_HELPER(name, type, NUM_SLAVES, 1) \
- remote_object_##name##_t remote_object_##name = {.object = { \
- .object_type = MASTER_TO_SINGLE_SLAVE, \
- .object_size = sizeof(type), \
- }}; \
- type* begin_write_##name(uint8_t slave) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer; \
- start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
- } \
- void end_write_##name(uint8_t slave) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer; \
- start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- triple_buffer_end_write_internal(tb); \
- signal_data_written(); \
- } \
- type* read_##name() { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return (type*)triple_buffer_read_internal(obj->object_size, tb); \
- }
-
-#define SLAVE_TO_MASTER_OBJECT(name, type) \
- REMOTE_OBJECT_HELPER(name, type, 1, NUM_SLAVES) \
- remote_object_##name##_t remote_object_##name = {.object = { \
- .object_type = SLAVE_TO_MASTER, \
- .object_size = sizeof(type), \
- }}; \
- type* begin_write_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
- return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
- } \
- void end_write_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
- triple_buffer_end_write_internal(tb); \
- signal_data_written(); \
- } \
- type* read_##name(uint8_t slave) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \
- start += slave * REMOTE_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return (type*)triple_buffer_read_internal(obj->object_size, tb); \
- }
-
-#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name
-
-void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects);
-void reinitialize_serial_link_transport(void);
-void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size);
-void update_transport(void);
diff --git a/quantum/serial_link/protocol/triple_buffered_object.c b/quantum/serial_link/protocol/triple_buffered_object.c
deleted file mode 100644
index e0c6d702a5..0000000000
--- a/quantum/serial_link/protocol/triple_buffered_object.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/triple_buffered_object.h"
-#include "serial_link/system/serial_link.h"
-#include <stdbool.h>
-#include <stddef.h>
-
-#define GET_READ_INDEX() object->state & 3
-#define GET_WRITE_INDEX() (object->state >> 2) & 3
-#define GET_SHARED_INDEX() (object->state >> 4) & 3
-#define GET_DATA_AVAILABLE() (object->state >> 6) & 1
-
-#define SET_READ_INDEX(i) object->state = ((object->state & ~3) | i)
-#define SET_WRITE_INDEX(i) object->state = ((object->state & ~(3 << 2)) | (i << 2))
-#define SET_SHARED_INDEX(i) object->state = ((object->state & ~(3 << 4)) | (i << 4))
-#define SET_DATA_AVAILABLE(i) object->state = ((object->state & ~(1 << 6)) | (i << 6))
-
-void triple_buffer_init(triple_buffer_object_t* object) {
- object->state = 0;
- SET_WRITE_INDEX(0);
- SET_READ_INDEX(1);
- SET_SHARED_INDEX(2);
- SET_DATA_AVAILABLE(0);
-}
-
-void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object) {
- serial_link_lock();
- if (GET_DATA_AVAILABLE()) {
- uint8_t shared_index = GET_SHARED_INDEX();
- uint8_t read_index = GET_READ_INDEX();
- SET_READ_INDEX(shared_index);
- SET_SHARED_INDEX(read_index);
- SET_DATA_AVAILABLE(false);
- serial_link_unlock();
- return object->buffer + object_size * shared_index;
- } else {
- serial_link_unlock();
- return NULL;
- }
-}
-
-void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object) {
- uint8_t write_index = GET_WRITE_INDEX();
- return object->buffer + object_size * write_index;
-}
-
-void triple_buffer_end_write_internal(triple_buffer_object_t* object) {
- serial_link_lock();
- uint8_t shared_index = GET_SHARED_INDEX();
- uint8_t write_index = GET_WRITE_INDEX();
- SET_SHARED_INDEX(write_index);
- SET_WRITE_INDEX(shared_index);
- SET_DATA_AVAILABLE(true);
- serial_link_unlock();
-}
diff --git a/quantum/serial_link/protocol/triple_buffered_object.h b/quantum/serial_link/protocol/triple_buffered_object.h
deleted file mode 100644
index 717d6d7b8b..0000000000
--- a/quantum/serial_link/protocol/triple_buffered_object.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-
-typedef struct {
- uint8_t state;
- uint8_t buffer[] __attribute__((aligned(4)));
-} triple_buffer_object_t;
-
-void triple_buffer_init(triple_buffer_object_t* object);
-
-#define triple_buffer_begin_write(object) (typeof(*object.buffer[0])*)triple_buffer_begin_write_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object)
-
-#define triple_buffer_end_write(object) triple_buffer_end_write_internal((triple_buffer_object_t*)object)
-
-#define triple_buffer_read(object) (typeof(*object.buffer[0])*)triple_buffer_read_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object)
-
-void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object);
-void triple_buffer_end_write_internal(triple_buffer_object_t* object);
-void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object);
diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c
deleted file mode 100644
index 6363f8ff3b..0000000000
--- a/quantum/serial_link/system/serial_link.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-#include "report.h"
-#include "host_driver.h"
-#include "serial_link/system/serial_link.h"
-#include <hal.h>
-#include "serial_link/protocol/byte_stuffer.h"
-#include "serial_link/protocol/transport.h"
-#include "serial_link/protocol/frame_router.h"
-#include "matrix.h"
-#include "sync_timer.h"
-#include <stdbool.h>
-#include "print.h"
-#include "config.h"
-
-#define SYNC_TIMER_OFFSET 2
-
-static event_source_t new_data_event;
-static bool serial_link_connected;
-static bool is_master = false;
-
-static uint8_t keyboard_leds(void);
-static void send_keyboard(report_keyboard_t* report);
-static void send_mouse(report_mouse_t* report);
-static void send_system(uint16_t data);
-static void send_consumer(uint16_t data);
-
-host_driver_t serial_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
-
-// Define these in your Config.h file
-#ifndef SERIAL_LINK_BAUD
-# error "Serial link baud is not set"
-#endif
-
-#ifndef SERIAL_LINK_THREAD_PRIORITY
-# error "Serial link thread priority not set"
-#endif
-
-static SerialConfig config = {.sc_speed = SERIAL_LINK_BAUD};
-
-//#define DEBUG_LINK_ERRORS
-
-static uint32_t read_from_serial(SerialDriver* driver, uint8_t link) {
- const uint32_t buffer_size = 16;
- uint8_t buffer[buffer_size];
- uint32_t bytes_read = sdAsynchronousRead(driver, buffer, buffer_size);
- uint8_t* current = buffer;
- uint8_t* end = current + bytes_read;
- while (current < end) {
- byte_stuffer_recv_byte(link, *current);
- current++;
- }
- return bytes_read;
-}
-
-static void print_error(char* str, eventflags_t flags, SerialDriver* driver) {
-#ifdef DEBUG_LINK_ERRORS
- if (flags & SD_PARITY_ERROR) {
- print(str);
- print(" Parity error\n");
- }
- if (flags & SD_FRAMING_ERROR) {
- print(str);
- print(" Framing error\n");
- }
- if (flags & SD_OVERRUN_ERROR) {
- print(str);
- uint32_t size = qSpaceI(&(driver->iqueue));
- xprintf(" Overrun error, queue size %d\n", size);
- }
- if (flags & SD_NOISE_ERROR) {
- print(str);
- print(" Noise error\n");
- }
- if (flags & SD_BREAK_DETECTED) {
- print(str);
- print(" Break detected\n");
- }
-#else
- (void)str;
- (void)flags;
- (void)driver;
-#endif
-}
-
-bool is_serial_link_master(void) { return is_master; }
-
-// TODO: Optimize the stack size, this is probably way too big
-static THD_WORKING_AREA(serialThreadStack, 1024);
-static THD_FUNCTION(serialThread, arg) {
- (void)arg;
- event_listener_t new_data_listener;
- event_listener_t sd1_listener;
- event_listener_t sd2_listener;
- chEvtRegister(&new_data_event, &new_data_listener, 0);
- eventflags_t events = CHN_INPUT_AVAILABLE | SD_PARITY_ERROR | SD_FRAMING_ERROR | SD_OVERRUN_ERROR | SD_NOISE_ERROR | SD_BREAK_DETECTED;
- chEvtRegisterMaskWithFlags(chnGetEventSource(&SD1), &sd1_listener, EVENT_MASK(1), events);
- chEvtRegisterMaskWithFlags(chnGetEventSource(&SD2), &sd2_listener, EVENT_MASK(2), events);
- bool need_wait = false;
- while (true) {
- eventflags_t flags1 = 0;
- eventflags_t flags2 = 0;
- if (need_wait) {
- eventmask_t mask = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(1000));
- if (mask & EVENT_MASK(1)) {
- flags1 = chEvtGetAndClearFlags(&sd1_listener);
- print_error("DOWNLINK", flags1, &SD1);
- }
- if (mask & EVENT_MASK(2)) {
- flags2 = chEvtGetAndClearFlags(&sd2_listener);
- print_error("UPLINK", flags2, &SD2);
- }
- }
-
- // Always stay as master, even if the USB goes into sleep mode
- is_master |= usbGetDriverStateI(&USBD1) == USB_ACTIVE;
- router_set_master(is_master);
-
- need_wait = true;
- need_wait &= read_from_serial(&SD2, UP_LINK) == 0;
- need_wait &= read_from_serial(&SD1, DOWN_LINK) == 0;
- update_transport();
- }
-}
-
-void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
- if (link == DOWN_LINK) {
- sdWrite(&SD1, data, size);
- } else {
- sdWrite(&SD2, data, size);
- }
-}
-
-static systime_t last_update = 0;
-
-typedef struct {
- matrix_row_t rows[MATRIX_ROWS];
-} matrix_object_t;
-
-static matrix_object_t last_matrix = {};
-
-SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t);
-MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool);
-#ifndef DISABLE_SYNC_TIMER
-MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t);
-#endif
-
-static remote_object_t* remote_objects[] = {
- REMOTE_OBJECT(serial_link_connected),
- REMOTE_OBJECT(keyboard_matrix),
-#ifndef DISABLE_SYNC_TIMER
- REMOTE_OBJECT(sync_timer),
-#endif
-};
-
-void init_serial_link(void) {
- serial_link_connected = false;
- init_serial_link_hal();
- add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*));
- init_byte_stuffer();
- sdStart(&SD1, &config);
- sdStart(&SD2, &config);
- chEvtObjectInit(&new_data_event);
- (void)chThdCreateStatic(serialThreadStack, sizeof(serialThreadStack), SERIAL_LINK_THREAD_PRIORITY, serialThread, NULL);
-}
-
-void matrix_set_remote(matrix_row_t* rows, uint8_t index);
-
-void serial_link_update(void) {
- if (read_serial_link_connected()) {
- serial_link_connected = true;
- }
-
- matrix_object_t matrix;
- bool changed = false;
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- matrix.rows[i] = matrix_get_row(i);
- changed |= matrix.rows[i] != last_matrix.rows[i];
- }
-
- systime_t current_time = chVTGetSystemTimeX();
- systime_t delta = current_time - last_update;
- if (changed || delta > TIME_US2I(5000)) {
- last_update = current_time;
- last_matrix = matrix;
- matrix_object_t* m = begin_write_keyboard_matrix();
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- m->rows[i] = matrix.rows[i];
- }
- end_write_keyboard_matrix();
-
- *begin_write_serial_link_connected() = true;
- end_write_serial_link_connected();
-
-#ifndef DISABLE_SYNC_TIMER
- *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET;
- end_write_sync_timer();
-#endif
- }
-
- matrix_object_t* m = read_keyboard_matrix(0);
- if (m) {
- matrix_set_remote(m->rows, 0);
- }
-
-#ifndef DISABLE_SYNC_TIMER
- uint32_t* t = read_sync_timer();
- if (t) {
- sync_timer_update(*t);
- }
-#endif
-}
-
-void signal_data_written(void) { chEvtBroadcast(&new_data_event); }
-
-bool is_serial_link_connected(void) { return serial_link_connected; }
-
-host_driver_t* get_serial_link_driver(void) { return &serial_driver; }
-
-// NOTE: The driver does nothing, because the master handles everything
-uint8_t keyboard_leds(void) { return 0; }
-
-void send_keyboard(report_keyboard_t* report) { (void)report; }
-
-void send_mouse(report_mouse_t* report) { (void)report; }
-
-void send_system(uint16_t data) { (void)data; }
-
-void send_consumer(uint16_t data) { (void)data; }
diff --git a/quantum/serial_link/system/serial_link.h b/quantum/serial_link/system/serial_link.h
deleted file mode 100644
index adc1f6e93d..0000000000
--- a/quantum/serial_link/system/serial_link.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include "host_driver.h"
-#include <stdbool.h>
-
-void init_serial_link(void);
-void init_serial_link_hal(void);
-bool is_serial_link_connected(void);
-bool is_serial_link_master(void);
-host_driver_t* get_serial_link_driver(void);
-void serial_link_update(void);
-
-#if defined(PROTOCOL_CHIBIOS)
-# include <ch.h>
-
-static inline void serial_link_lock(void) { chSysLock(); }
-
-static inline void serial_link_unlock(void) { chSysUnlock(); }
-
-void signal_data_written(void);
-
-#else
-
-inline void serial_link_lock(void) {}
-
-inline void serial_link_unlock(void) {}
-
-void signal_data_written(void);
-
-#endif
diff --git a/quantum/serial_link/tests/Makefile b/quantum/serial_link/tests/Makefile
deleted file mode 100644
index 11dd355b22..0000000000
--- a/quantum/serial_link/tests/Makefile
+++ /dev/null
@@ -1,61 +0,0 @@
-# The MIT License (MIT)
-#
-# Copyright (c) 2016 Fred Sundvik
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-CC = gcc
-CFLAGS =
-INCLUDES = -I. -I../../
-LDFLAGS = -L$(BUILDDIR)/cgreen/build-c/src -shared
-LDLIBS = -lcgreen
-UNITOBJ = $(BUILDDIR)/serialtest/unitobj
-DEPDIR = $(BUILDDIR)/serialtest/unit.d
-UNITTESTS = $(BUILDDIR)/serialtest/unittests
-DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
-EXT = .so
-UNAME := $(shell uname)
-ifneq (, $(findstring MINGW, $(UNAME)))
- EXT = .dll
-endif
-ifneq (, $(findstring CYGWIN, $(UNAME)))
- EXT = .dll
-endif
-
-SRC = $(wildcard *.c)
-TESTFILES = $(patsubst %.c, $(UNITTESTS)/%$(EXT), $(SRC))
-$(shell mkdir -p $(DEPDIR) >/dev/null)
-
-test: $(TESTFILES)
- @$(BUILDDIR)/cgreen/build-c/tools/cgreen-runner --color $(TESTFILES)
-
-$(UNITTESTS)/%$(EXT): $(UNITOBJ)/%.o
- @mkdir -p $(UNITTESTS)
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-$(UNITOBJ)/%.o : %.c
-$(UNITOBJ)/%.o: %.c $(DEPDIR)/%.d
- @mkdir -p $(UNITOBJ)
- $(CC) $(CFLAGS) $(DEPFLAGS) $(INCLUDES) -c $< -o $@
- @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
-
-$(DEPDIR)/%.d: ;
-.PRECIOUS: $(DEPDIR)/%.d
-
--include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRC)))
diff --git a/quantum/serial_link/tests/byte_stuffer_tests.cpp b/quantum/serial_link/tests/byte_stuffer_tests.cpp
deleted file mode 100644
index 9e4e1768f4..0000000000
--- a/quantum/serial_link/tests/byte_stuffer_tests.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-#include "gmock/gmock.h"
-#include <vector>
-#include <algorithm>
-extern "C" {
-#include "serial_link/protocol/byte_stuffer.h"
-#include "serial_link/protocol/frame_validator.h"
-#include "serial_link/protocol/physical.h"
-}
-
-using testing::_;
-using testing::Args;
-using testing::ElementsAreArray;
-
-class ByteStuffer : public ::testing::Test {
- public:
- ByteStuffer() {
- Instance = this;
- init_byte_stuffer();
- }
-
- ~ByteStuffer() { Instance = nullptr; }
-
- MOCK_METHOD3(validator_recv_frame, void(uint8_t link, uint8_t* data, uint16_t size));
-
- void send_data(uint8_t link, const uint8_t* data, uint16_t size) { std::copy(data, data + size, std::back_inserter(sent_data)); }
- std::vector<uint8_t> sent_data;
-
- static ByteStuffer* Instance;
-};
-
-ByteStuffer* ByteStuffer::Instance = nullptr;
-
-extern "C" {
-void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) { ByteStuffer::Instance->validator_recv_frame(link, data, size); }
-
-void send_data(uint8_t link, const uint8_t* data, uint16_t size) { ByteStuffer::Instance->send_data(link, data, size); }
-}
-
-TEST_F(ByteStuffer, receives_no_frame_for_a_single_zero_byte) {
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_no_frame_for_a_single_FF_byte) {
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- byte_stuffer_recv_byte(0, 0xFF);
-}
-
-TEST_F(ByteStuffer, receives_no_frame_for_a_single_random_byte) {
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- byte_stuffer_recv_byte(0, 0x4A);
-}
-
-TEST_F(ByteStuffer, receives_no_frame_for_a_zero_length_frame) {
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_single_byte_valid_frame) {
- uint8_t expected[] = {0x37};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 0x37);
- byte_stuffer_recv_byte(0, 0);
-}
-TEST_F(ByteStuffer, receives_three_bytes_valid_frame) {
- uint8_t expected[] = {0x37, 0x99, 0xFF};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 4);
- byte_stuffer_recv_byte(0, 0x37);
- byte_stuffer_recv_byte(0, 0x99);
- byte_stuffer_recv_byte(0, 0xFF);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_single_zero_valid_frame) {
- uint8_t expected[] = {0};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_valid_frame_with_zeroes) {
- uint8_t expected[] = {5, 0, 3, 0};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 5);
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 3);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_two_valid_frames) {
- uint8_t expected1[] = {5, 0};
- uint8_t expected2[] = {3};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected1)));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected2)));
- byte_stuffer_recv_byte(1, 2);
- byte_stuffer_recv_byte(1, 5);
- byte_stuffer_recv_byte(1, 1);
- byte_stuffer_recv_byte(1, 0);
- byte_stuffer_recv_byte(1, 2);
- byte_stuffer_recv_byte(1, 3);
- byte_stuffer_recv_byte(1, 0);
-}
-
-TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_zero) {
- uint8_t expected[] = {5, 7};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(1, 3);
- byte_stuffer_recv_byte(1, 1);
- byte_stuffer_recv_byte(1, 0);
- byte_stuffer_recv_byte(1, 3);
- byte_stuffer_recv_byte(1, 5);
- byte_stuffer_recv_byte(1, 7);
- byte_stuffer_recv_byte(1, 0);
-}
-
-TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) {
- uint8_t expected[] = {5, 7};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 9);
- byte_stuffer_recv_byte(0, 4); // This should have been zero
- byte_stuffer_recv_byte(0, 0);
- byte_stuffer_recv_byte(0, 3);
- byte_stuffer_recv_byte(0, 5);
- byte_stuffer_recv_byte(0, 7);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) {
- uint8_t expected[254];
- int i;
- for (i = 0; i < 254; i++) {
- expected[i] = i + 1;
- }
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) {
- uint8_t expected[255];
- int i;
- for (i = 0; i < 254; i++) {
- expected[i] = i + 1;
- }
- expected[254] = 7;
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 7);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) {
- uint8_t expected[255];
- int i;
- for (i = 0; i < 254; i++) {
- expected[i] = i + 1;
- }
- expected[254] = 0;
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_two_long_frames_and_some_more) {
- uint8_t expected[515];
- int i;
- int j;
- for (j = 0; j < 2; j++) {
- for (i = 0; i < 254; i++) {
- expected[i + 254 * j] = i + 1;
- }
- }
- for (i = 0; i < 7; i++) {
- expected[254 * 2 + i] = i + 1;
- }
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 8);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 3);
- byte_stuffer_recv_byte(0, 4);
- byte_stuffer_recv_byte(0, 5);
- byte_stuffer_recv_byte(0, 6);
- byte_stuffer_recv_byte(0, 7);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) {
- uint8_t expected[MAX_FRAME_SIZE] = {};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- int i;
- byte_stuffer_recv_byte(0, 1);
- for (i = 0; i < MAX_FRAME_SIZE; i++) {
- byte_stuffer_recv_byte(0, 1);
- }
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) {
- uint8_t expected[1] = {0};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- int i;
- byte_stuffer_recv_byte(0, 1);
- for (i = 0; i < MAX_FRAME_SIZE; i++) {
- byte_stuffer_recv_byte(0, 1);
- }
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, received_frame_is_aborted_when_its_too_long) {
- uint8_t expected[1] = {1};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- int i;
- byte_stuffer_recv_byte(0, 1);
- for (i = 0; i < MAX_FRAME_SIZE; i++) {
- byte_stuffer_recv_byte(0, 1);
- }
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, does_nothing_when_sending_zero_size_frame) {
- EXPECT_EQ(sent_data.size(), 0);
- byte_stuffer_send_frame(0, NULL, 0);
-}
-
-TEST_F(ByteStuffer, send_one_byte_frame) {
- uint8_t data[] = {5};
- byte_stuffer_send_frame(1, data, 1);
- uint8_t expected[] = {2, 5, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_two_byte_frame) {
- uint8_t data[] = {5, 0x77};
- byte_stuffer_send_frame(0, data, 2);
- uint8_t expected[] = {3, 5, 0x77, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_one_byte_frame_with_zero) {
- uint8_t data[] = {0};
- byte_stuffer_send_frame(0, data, 1);
- uint8_t expected[] = {1, 1, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_zero) {
- uint8_t data[] = {0, 9};
- byte_stuffer_send_frame(1, data, 2);
- uint8_t expected[] = {1, 2, 9, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) {
- uint8_t data[] = {9, 0};
- byte_stuffer_send_frame(1, data, 2);
- uint8_t expected[] = {2, 9, 1, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) {
- uint8_t data[] = {9, 0, 0x68};
- byte_stuffer_send_frame(0, data, 3);
- uint8_t expected[] = {2, 9, 2, 0x68, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_three_byte_frame_data_in_the_middle) {
- uint8_t data[] = {0, 0x55, 0};
- byte_stuffer_send_frame(0, data, 3);
- uint8_t expected[] = {1, 2, 0x55, 1, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_three_byte_frame_with_all_zeroes) {
- uint8_t data[] = {0, 0, 0};
- byte_stuffer_send_frame(0, data, 3);
- uint8_t expected[] = {1, 1, 1, 1, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes) {
- uint8_t data[254];
- int i;
- for (i = 0; i < 254; i++) {
- data[i] = i + 1;
- }
- byte_stuffer_send_frame(0, data, 254);
- uint8_t expected[256];
- expected[0] = 0xFF;
- for (i = 1; i < 255; i++) {
- expected[i] = i;
- }
- expected[255] = 0;
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_frame_with_255_non_zeroes) {
- uint8_t data[255];
- int i;
- for (i = 0; i < 255; i++) {
- data[i] = i + 1;
- }
- byte_stuffer_send_frame(0, data, 255);
- uint8_t expected[258];
- expected[0] = 0xFF;
- for (i = 1; i < 255; i++) {
- expected[i] = i;
- }
- expected[255] = 2;
- expected[256] = 255;
- expected[257] = 0;
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) {
- uint8_t data[255];
- int i;
- for (i = 0; i < 254; i++) {
- data[i] = i + 1;
- }
- data[254] = 0;
- byte_stuffer_send_frame(0, data, 255);
- uint8_t expected[258];
- expected[0] = 0xFF;
- for (i = 1; i < 255; i++) {
- expected[i] = i;
- }
- expected[255] = 1;
- expected[256] = 1;
- expected[257] = 0;
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) {
- uint8_t original_data[] = {1, 2, 3};
- byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- int i;
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) {
- uint8_t original_data[] = {1, 0, 3, 0, 0, 9};
- byte_stuffer_send_frame(1, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- int i;
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) {
- uint8_t original_data[254];
- int i;
- for (i = 0; i < 254; i++) {
- original_data[i] = i + 1;
- }
- byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) {
- uint8_t original_data[256];
- int i;
- for (i = 0; i < 254; i++) {
- original_data[i] = i + 1;
- }
- original_data[254] = 22;
- original_data[255] = 23;
- byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) {
- uint8_t original_data[255];
- int i;
- for (i = 0; i < 254; i++) {
- original_data[i] = i + 1;
- }
- original_data[254] = 0;
- byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
diff --git a/quantum/serial_link/tests/frame_router_tests.cpp b/quantum/serial_link/tests/frame_router_tests.cpp
deleted file mode 100644
index f76dfb33d6..0000000000
--- a/quantum/serial_link/tests/frame_router_tests.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-#include "gmock/gmock.h"
-#include <array>
-extern "C" {
-#include "serial_link/protocol/transport.h"
-#include "serial_link/protocol/byte_stuffer.h"
-#include "serial_link/protocol/frame_router.h"
-}
-
-using testing::_;
-using testing::Args;
-using testing::ElementsAreArray;
-
-class FrameRouter : public testing::Test {
- public:
- FrameRouter() : current_router_buffer(nullptr) {
- Instance = this;
- init_byte_stuffer();
- }
-
- ~FrameRouter() { Instance = nullptr; }
-
- void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
- auto& buffer = current_router_buffer->send_buffers[link];
- std::copy(data, data + size, std::back_inserter(buffer));
- }
-
- void receive_data(uint8_t link, uint8_t* data, uint16_t size) {
- int i;
- for (i = 0; i < size; i++) {
- byte_stuffer_recv_byte(link, data[i]);
- }
- }
-
- void activate_router(uint8_t num) {
- current_router_buffer = router_buffers + num;
- router_set_master(num == 0);
- }
-
- void simulate_transport(uint8_t from, uint8_t to) {
- activate_router(to);
- if (from > to) {
- receive_data(DOWN_LINK, router_buffers[from].send_buffers[UP_LINK].data(), router_buffers[from].send_buffers[UP_LINK].size());
- } else if (to > from) {
- receive_data(UP_LINK, router_buffers[from].send_buffers[DOWN_LINK].data(), router_buffers[from].send_buffers[DOWN_LINK].size());
- }
- }
-
- MOCK_METHOD3(transport_recv_frame, void(uint8_t from, uint8_t* data, uint16_t size));
-
- std::vector<uint8_t> received_data;
-
- struct router_buffer {
- std::vector<uint8_t> send_buffers[2];
- };
-
- router_buffer router_buffers[8];
- router_buffer* current_router_buffer;
-
- static FrameRouter* Instance;
-};
-
-FrameRouter* FrameRouter::Instance = nullptr;
-
-typedef struct {
- std::array<uint8_t, 4> data;
- uint8_t extra[16];
-} frame_buffer_t;
-
-extern "C" {
-void send_data(uint8_t link, const uint8_t* data, uint16_t size) { FrameRouter::Instance->send_data(link, data, size); }
-
-void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) { FrameRouter::Instance->transport_recv_frame(from, data, size); }
-}
-
-TEST_F(FrameRouter, master_broadcast_is_received_by_everyone) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(0);
- router_send_frame(0xFF, (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
- EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(0, 1);
- EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(1, 2);
- EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, master_send_is_received_by_targets) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(0);
- router_send_frame((1 << 1) | (1 << 2), (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
-
- simulate_transport(0, 1);
- EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(1, 2);
- EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(2, 3);
- EXPECT_GT(router_buffers[3].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[3].send_buffers[UP_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, first_link_sends_to_master) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(1);
- router_send_frame(0, (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(1, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(1, 0);
- EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, second_link_sends_to_master) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(2);
- router_send_frame(0, (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[2].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
-
- simulate_transport(2, 1);
- EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(2, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(1, 0);
- EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, master_sends_to_master_does_nothing) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(0);
- router_send_frame(0, (uint8_t*)&data, 4);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, link_sends_to_other_link_does_nothing) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(1);
- router_send_frame(2, (uint8_t*)&data, 4);
- EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, master_receives_on_uplink_does_nothing) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(1);
- router_send_frame(0, (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(_, _, _)).Times(0);
- activate_router(0);
- receive_data(UP_LINK, router_buffers[1].send_buffers[UP_LINK].data(), router_buffers[1].send_buffers[UP_LINK].size());
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
-}
diff --git a/quantum/serial_link/tests/frame_validator_tests.cpp b/quantum/serial_link/tests/frame_validator_tests.cpp
deleted file mode 100644
index 43dc57b633..0000000000
--- a/quantum/serial_link/tests/frame_validator_tests.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-#include "gmock/gmock.h"
-extern "C" {
-#include "serial_link/protocol/frame_validator.h"
-}
-
-using testing::_;
-using testing::Args;
-using testing::ElementsAreArray;
-
-class FrameValidator : public testing::Test {
- public:
- FrameValidator() { Instance = this; }
-
- ~FrameValidator() { Instance = nullptr; }
-
- MOCK_METHOD3(route_incoming_frame, void(uint8_t link, uint8_t* data, uint16_t size));
- MOCK_METHOD3(byte_stuffer_send_frame, void(uint8_t link, uint8_t* data, uint16_t size));
-
- static FrameValidator* Instance;
-};
-
-FrameValidator* FrameValidator::Instance = nullptr;
-
-extern "C" {
-void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->route_incoming_frame(link, data, size); }
-
-void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->byte_stuffer_send_frame(link, data, size); }
-}
-
-TEST_F(FrameValidator, doesnt_validate_frames_under_5_bytes) {
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0);
- uint8_t data[] = {1, 2};
- validator_recv_frame(0, 0, 1);
- validator_recv_frame(0, data, 2);
- validator_recv_frame(0, data, 3);
- validator_recv_frame(0, data, 4);
-}
-
-TEST_F(FrameValidator, validates_one_byte_frame_with_correct_crc) {
- uint8_t data[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 1)));
- validator_recv_frame(0, data, 5);
-}
-
-TEST_F(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) {
- uint8_t data[] = {0x44, 0, 0, 0, 0};
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0);
- validator_recv_frame(1, data, 5);
-}
-
-TEST_F(FrameValidator, validates_four_byte_frame_with_correct_crc) {
- uint8_t data[] = {0x44, 0x10, 0xFF, 0x00, 0x74, 0x4E, 0x30, 0xBA};
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 4)));
- validator_recv_frame(1, data, 8);
-}
-
-TEST_F(FrameValidator, validates_five_byte_frame_with_correct_crc) {
- uint8_t data[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 5)));
- validator_recv_frame(0, data, 9);
-}
-
-TEST_F(FrameValidator, sends_one_byte_with_correct_crc) {
- uint8_t original[] = {0x44, 0, 0, 0, 0};
- uint8_t expected[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
- EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- validator_send_frame(0, original, 1);
-}
-
-TEST_F(FrameValidator, sends_five_bytes_with_correct_crc) {
- uint8_t original[] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
- uint8_t expected[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
- EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- validator_send_frame(0, original, 5);
-}
diff --git a/quantum/serial_link/tests/rules.mk b/quantum/serial_link/tests/rules.mk
deleted file mode 100644
index b81515bc55..0000000000
--- a/quantum/serial_link/tests/rules.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-serial_link_byte_stuffer_SRC :=\
- $(SERIAL_PATH)/tests/byte_stuffer_tests.cpp \
- $(SERIAL_PATH)/protocol/byte_stuffer.c
-
-serial_link_frame_validator_SRC := \
- $(SERIAL_PATH)/tests/frame_validator_tests.cpp \
- $(SERIAL_PATH)/protocol/frame_validator.c
-
-serial_link_frame_router_SRC := \
- $(SERIAL_PATH)/tests/frame_router_tests.cpp \
- $(SERIAL_PATH)/protocol/byte_stuffer.c \
- $(SERIAL_PATH)/protocol/frame_validator.c \
- $(SERIAL_PATH)/protocol/frame_router.c
-
-serial_link_triple_buffered_object_SRC := \
- $(SERIAL_PATH)/tests/triple_buffered_object_tests.cpp \
- $(SERIAL_PATH)/protocol/triple_buffered_object.c
-
-serial_link_transport_SRC := \
- $(SERIAL_PATH)/tests/transport_tests.cpp \
- $(SERIAL_PATH)/protocol/transport.c \
- $(SERIAL_PATH)/protocol/triple_buffered_object.c
diff --git a/quantum/serial_link/tests/testlist.mk b/quantum/serial_link/tests/testlist.mk
deleted file mode 100644
index c5edaf478f..0000000000
--- a/quantum/serial_link/tests/testlist.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-TEST_LIST +=\
- serial_link_byte_stuffer\
- serial_link_frame_validator\
- serial_link_frame_router\
- serial_link_triple_buffered_object\
- serial_link_transport
diff --git a/quantum/serial_link/tests/transport_tests.cpp b/quantum/serial_link/tests/transport_tests.cpp
deleted file mode 100644
index cfd1110460..0000000000
--- a/quantum/serial_link/tests/transport_tests.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-#include "gmock/gmock.h"
-
-using testing::_;
-using testing::Args;
-using testing::ElementsAreArray;
-
-extern "C" {
-#include "serial_link/protocol/transport.h"
-}
-
-struct test_object1 {
- uint32_t test;
-};
-
-struct test_object2 {
- uint32_t test1;
- uint32_t test2;
-};
-
-MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1);
-MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1);
-SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1);
-
-static remote_object_t* test_remote_objects[] = {
- REMOTE_OBJECT(master_to_slave),
- REMOTE_OBJECT(master_to_single_slave),
- REMOTE_OBJECT(slave_to_master),
-};
-
-class Transport : public testing::Test {
- public:
- Transport() {
- Instance = this;
- add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*));
- }
-
- ~Transport() {
- Instance = nullptr;
- reinitialize_serial_link_transport();
- }
-
- MOCK_METHOD0(signal_data_written, void());
- MOCK_METHOD1(router_send_frame, void(uint8_t destination));
-
- void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
- router_send_frame(destination);
- std::copy(data, data + size, std::back_inserter(sent_data));
- }
-
- static Transport* Instance;
-
- std::vector<uint8_t> sent_data;
-};
-
-Transport* Transport::Instance = nullptr;
-
-extern "C" {
-void signal_data_written(void) { Transport::Instance->signal_data_written(); }
-
-void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { Transport::Instance->router_send_frame(destination, data, size); }
-}
-
-TEST_F(Transport, write_to_local_signals_an_event) {
- begin_write_master_to_slave();
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_slave();
- begin_write_slave_to_master();
- EXPECT_CALL(*this, signal_data_written());
- end_write_slave_to_master();
- begin_write_master_to_single_slave(1);
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_single_slave(1);
-}
-
-TEST_F(Transport, writes_from_master_to_all_slaves) {
- update_transport();
- test_object1* obj = begin_write_master_to_slave();
- obj->test = 5;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_slave();
- EXPECT_CALL(*this, router_send_frame(0xFF));
- update_transport();
- transport_recv_frame(0, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_master_to_slave();
- EXPECT_NE(obj2, nullptr);
- EXPECT_EQ(obj2->test, 5);
-}
-
-TEST_F(Transport, writes_from_slave_to_master) {
- update_transport();
- test_object1* obj = begin_write_slave_to_master();
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_slave_to_master();
- EXPECT_CALL(*this, router_send_frame(0));
- update_transport();
- transport_recv_frame(3, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_slave_to_master(2);
- EXPECT_EQ(read_slave_to_master(0), nullptr);
- EXPECT_NE(obj2, nullptr);
- EXPECT_EQ(obj2->test, 7);
-}
-
-TEST_F(Transport, writes_from_master_to_single_slave) {
- update_transport();
- test_object1* obj = begin_write_master_to_single_slave(3);
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_single_slave(3);
- EXPECT_CALL(*this, router_send_frame(4));
- update_transport();
- transport_recv_frame(0, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_master_to_single_slave();
- EXPECT_NE(obj2, nullptr);
- EXPECT_EQ(obj2->test, 7);
-}
-
-TEST_F(Transport, ignores_object_with_invalid_id) {
- update_transport();
- test_object1* obj = begin_write_master_to_single_slave(3);
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_single_slave(3);
- EXPECT_CALL(*this, router_send_frame(4));
- update_transport();
- sent_data[sent_data.size() - 1] = 44;
- transport_recv_frame(0, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_master_to_single_slave();
- EXPECT_EQ(obj2, nullptr);
-}
-
-TEST_F(Transport, ignores_object_with_size_too_small) {
- update_transport();
- test_object1* obj = begin_write_master_to_slave();
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_slave();
- EXPECT_CALL(*this, router_send_frame(_));
- update_transport();
- sent_data[sent_data.size() - 2] = 0;
- transport_recv_frame(0, sent_data.data(), sent_data.size() - 1);
- test_object1* obj2 = read_master_to_slave();
- EXPECT_EQ(obj2, nullptr);
-}
-
-TEST_F(Transport, ignores_object_with_size_too_big) {
- update_transport();
- test_object1* obj = begin_write_master_to_slave();
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_slave();
- EXPECT_CALL(*this, router_send_frame(_));
- update_transport();
- sent_data.resize(sent_data.size() + 22);
- sent_data[sent_data.size() - 1] = 0;
- transport_recv_frame(0, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_master_to_slave();
- EXPECT_EQ(obj2, nullptr);
-}
diff --git a/quantum/serial_link/tests/triple_buffered_object_tests.cpp b/quantum/serial_link/tests/triple_buffered_object_tests.cpp
deleted file mode 100644
index 8de9bfdebf..0000000000
--- a/quantum/serial_link/tests/triple_buffered_object_tests.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-extern "C" {
-#include "serial_link/protocol/triple_buffered_object.h"
-}
-
-struct test_object {
- uint8_t state;
- uint32_t buffer[3];
-};
-
-test_object test_object;
-
-class TripleBufferedObject : public testing::Test {
- public:
- TripleBufferedObject() { triple_buffer_init((triple_buffer_object_t*)&test_object); }
-};
-
-TEST_F(TripleBufferedObject, writes_and_reads_object) {
- *triple_buffer_begin_write(&test_object) = 0x3456ABCC;
- triple_buffer_end_write(&test_object);
- EXPECT_EQ(*triple_buffer_read(&test_object), 0x3456ABCC);
-}
-
-TEST_F(TripleBufferedObject, does_not_read_empty) { EXPECT_EQ(triple_buffer_read(&test_object), nullptr); }
-
-TEST_F(TripleBufferedObject, writes_twice_and_reads_object) {
- *triple_buffer_begin_write(&test_object) = 0x3456ABCC;
- triple_buffer_end_write(&test_object);
- *triple_buffer_begin_write(&test_object) = 0x44778899;
- triple_buffer_end_write(&test_object);
- EXPECT_EQ(*triple_buffer_read(&test_object), 0x44778899);
-}
-
-TEST_F(TripleBufferedObject, performs_another_write_in_the_middle_of_read) {
- *triple_buffer_begin_write(&test_object) = 1;
- triple_buffer_end_write(&test_object);
- uint32_t* read = triple_buffer_read(&test_object);
- *triple_buffer_begin_write(&test_object) = 2;
- triple_buffer_end_write(&test_object);
- EXPECT_EQ(*read, 1);
- EXPECT_EQ(*triple_buffer_read(&test_object), 2);
- EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
-}
-
-TEST_F(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) {
- *triple_buffer_begin_write(&test_object) = 1;
- triple_buffer_end_write(&test_object);
- uint32_t* read = triple_buffer_read(&test_object);
- *triple_buffer_begin_write(&test_object) = 2;
- triple_buffer_end_write(&test_object);
- *triple_buffer_begin_write(&test_object) = 3;
- triple_buffer_end_write(&test_object);
- EXPECT_EQ(*read, 1);
- EXPECT_EQ(*triple_buffer_read(&test_object), 3);
- EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
-}
diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c
index fd676f0729..3ff87710e7 100644
--- a/quantum/split_common/transactions.c
+++ b/quantum/split_common/transactions.c
@@ -42,8 +42,8 @@
{ &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb }
#define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL)
-#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0)
-#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length)
+#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0)
+#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length)
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
// Forward-declare the RPC callback handlers
@@ -157,8 +157,8 @@ static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_ro
memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix));
}
-# define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix)
-# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix)
+# define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix)
+# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix)
# define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix),
#else // SPLIT_TRANSPORT_MIRROR
@@ -235,8 +235,8 @@ static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
}
}
-# define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer)
-# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer)
+# define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer)
+# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer)
# define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer),
#else // DISABLE_SYNC_TIMER
@@ -300,8 +300,8 @@ static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
set_split_host_keyboard_leds(split_shmem->led_state);
}
-# define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state)
-# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state)
+# define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state)
+# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state)
# define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state),
#else // SPLIT_LED_STATE_ENABLE
@@ -357,8 +357,8 @@ static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave
# endif
}
-# define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods)
-# define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods)
+# define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods)
+# define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods)
# define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods),
#else // SPLIT_MODS_ENABLE
@@ -382,8 +382,8 @@ static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t
static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { backlight_set(split_shmem->backlight_level); }
-# define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight)
-# define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight)
+# define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight)
+# define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight)
# define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level),
#else // BACKLIGHT_ENABLE
@@ -419,8 +419,8 @@ static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s
}
}
-# define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight)
-# define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight)
+# define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight)
+# define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight)
# define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync),
#else // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
@@ -449,8 +449,8 @@ static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state);
}
-# define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix)
-# define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix)
+# define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix)
+# define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix)
# define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync),
#else // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
@@ -479,8 +479,8 @@ static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state);
}
-# define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix)
-# define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix)
+# define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix)
+# define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix)
# define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync),
#else // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
@@ -504,8 +504,8 @@ static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave
static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); }
-# define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm)
-# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm)
+# define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm)
+# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm)
# define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm),
#else // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
@@ -535,8 +535,8 @@ static void oled_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave
}
}
-# define TRANSACTIONS_OLED_MASTER() TRANSACTION_HANDLER_MASTER(oled)
-# define TRANSACTIONS_OLED_SLAVE() TRANSACTION_HANDLER_SLAVE(oled)
+# define TRANSACTIONS_OLED_MASTER() TRANSACTION_HANDLER_MASTER(oled)
+# define TRANSACTIONS_OLED_SLAVE() TRANSACTION_HANDLER_SLAVE(oled)
# define TRANSACTIONS_OLED_REGISTRATIONS [PUT_OLED] = trans_initiator2target_initializer(current_oled_state),
#else // defined(OLED_ENABLE) && defined(SPLIT_OLED_ENABLE)
@@ -566,8 +566,8 @@ static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sla
}
}
-# define TRANSACTIONS_ST7565_MASTER() TRANSACTION_HANDLER_MASTER(st7565)
-# define TRANSACTIONS_ST7565_SLAVE() TRANSACTION_HANDLER_SLAVE(st7565)
+# define TRANSACTIONS_ST7565_MASTER() TRANSACTION_HANDLER_MASTER(st7565)
+# define TRANSACTIONS_ST7565_SLAVE() TRANSACTION_HANDLER_SLAVE(st7565)
# define TRANSACTIONS_ST7565_REGISTRATIONS [PUT_ST7565] = trans_initiator2target_initializer(current_st7565_state),
#else // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)
diff --git a/tmk_core/common/sync_timer.c b/quantum/sync_timer.c
index 68b92d8b43..de24b463b6 100644
--- a/tmk_core/common/sync_timer.c
+++ b/quantum/sync_timer.c
@@ -26,7 +26,7 @@ SOFTWARE.
#include "sync_timer.h"
#include "keyboard.h"
-#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER)
+#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
volatile int32_t sync_timer_ms;
void sync_timer_init(void) { sync_timer_ms = 0; }
diff --git a/tmk_core/common/sync_timer.h b/quantum/sync_timer.h
index 744e2b50d5..9ddef45bb2 100644
--- a/tmk_core/common/sync_timer.h
+++ b/quantum/sync_timer.h
@@ -32,7 +32,7 @@ SOFTWARE.
extern "C" {
#endif
-#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER)
+#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
void sync_timer_init(void);
void sync_timer_update(uint32_t time);
uint16_t sync_timer_read(void);
diff --git a/quantum/via.c b/quantum/via.c
index 1b2dbcf08d..7c8aa753e7 100644
--- a/quantum/via.c
+++ b/quantum/via.c
@@ -44,7 +44,7 @@
#include "raw_hid.h"
#include "dynamic_keymap.h"
-#include "tmk_core/common/eeprom.h"
+#include "eeprom.h"
#include "version.h" // for QMK_BUILDDATE used in EEPROM magic
#include "via_ensure_keycode.h"
diff --git a/quantum/via_ensure_keycode.h b/quantum/via_ensure_keycode.h
index a9c1b8ba5d..1aba0cdd2a 100644
--- a/quantum/via_ensure_keycode.h
+++ b/quantum/via_ensure_keycode.h
@@ -5,362 +5,338 @@
#ifndef VIA_HAS_BROKEN_KEYCODES
-_Static_assert(KC_NO == 0, "");
-_Static_assert(KC_TRNS == 1, "");
+// clang-format off
-_Static_assert(KC_A == 0x04, "");
-_Static_assert(KC_B == 0x05, "");
-_Static_assert(KC_C == 0x06, "");
-_Static_assert(KC_D == 0x07, "");
-_Static_assert(KC_E == 0x08, "");
-_Static_assert(KC_F == 0x09, "");
-_Static_assert(KC_G == 0x0A, "");
-_Static_assert(KC_H == 0x0B, "");
-_Static_assert(KC_I == 0x0C, "");
-_Static_assert(KC_J == 0x0D, "");
-_Static_assert(KC_K == 0x0E, "");
-_Static_assert(KC_L == 0x0F, "");
-_Static_assert(KC_M == 0x10, "");
-_Static_assert(KC_N == 0x11, "");
-_Static_assert(KC_O == 0x12, "");
-_Static_assert(KC_P == 0x13, "");
-_Static_assert(KC_Q == 0x14, "");
-_Static_assert(KC_R == 0x15, "");
-_Static_assert(KC_S == 0x16, "");
-_Static_assert(KC_T == 0x17, "");
-_Static_assert(KC_U == 0x18, "");
-_Static_assert(KC_V == 0x19, "");
-_Static_assert(KC_W == 0x1A, "");
-_Static_assert(KC_X == 0x1B, "");
-_Static_assert(KC_Y == 0x1C, "");
-_Static_assert(KC_Z == 0x1D, "");
-_Static_assert(KC_1 == 0x1E, "");
-_Static_assert(KC_2 == 0x1F, "");
-_Static_assert(KC_3 == 0x20, "");
-_Static_assert(KC_4 == 0x21, "");
-_Static_assert(KC_5 == 0x22, "");
-_Static_assert(KC_6 == 0x23, "");
-_Static_assert(KC_7 == 0x24, "");
-_Static_assert(KC_8 == 0x25, "");
-_Static_assert(KC_9 == 0x26, "");
-_Static_assert(KC_0 == 0x27, "");
-_Static_assert(KC_ENTER == 0x28, "");
-_Static_assert(KC_ESCAPE == 0x29, "");
-_Static_assert(KC_BSPACE == 0x2A, "");
-_Static_assert(KC_TAB == 0x2B, "");
-_Static_assert(KC_SPACE == 0x2C, "");
-_Static_assert(KC_MINUS == 0x2D, "");
-_Static_assert(KC_EQUAL == 0x2E, "");
-_Static_assert(KC_LBRACKET == 0x2F, "");
-_Static_assert(KC_RBRACKET == 0x30, "");
-_Static_assert(KC_BSLASH == 0x31, "");
-_Static_assert(KC_SCOLON == 0x33, "");
-_Static_assert(KC_QUOTE == 0x34, "");
-_Static_assert(KC_GRAVE == 0x35, "");
-_Static_assert(KC_COMMA == 0x36, "");
-_Static_assert(KC_DOT == 0x37, "");
-_Static_assert(KC_SLASH == 0x38, "");
-_Static_assert(KC_CAPSLOCK == 0x39, "");
-_Static_assert(KC_F1 == 0x3A, "");
-_Static_assert(KC_F2 == 0x3B, "");
-_Static_assert(KC_F3 == 0x3C, "");
-_Static_assert(KC_F4 == 0x3D, "");
-_Static_assert(KC_F5 == 0x3E, "");
-_Static_assert(KC_F6 == 0x3F, "");
-_Static_assert(KC_F7 == 0x40, "");
-_Static_assert(KC_F8 == 0x41, "");
-_Static_assert(KC_F9 == 0x42, "");
-_Static_assert(KC_F10 == 0x43, "");
-_Static_assert(KC_F11 == 0x44, "");
-_Static_assert(KC_F12 == 0x45, "");
-_Static_assert(KC_PSCREEN == 0x46, "");
-_Static_assert(KC_SCROLLLOCK == 0x47, "");
-_Static_assert(KC_PAUSE == 0x48, "");
-_Static_assert(KC_INSERT == 0x49, "");
-_Static_assert(KC_HOME == 0x4A, "");
-_Static_assert(KC_PGUP == 0x4B, "");
-_Static_assert(KC_DELETE == 0x4C, "");
-_Static_assert(KC_END == 0x4D, "");
-_Static_assert(KC_PGDOWN == 0x4E, "");
-_Static_assert(KC_RIGHT == 0x4F, "");
-_Static_assert(KC_LEFT == 0x50, "");
-_Static_assert(KC_DOWN == 0x51, "");
-_Static_assert(KC_UP == 0x52, "");
-_Static_assert(KC_NUMLOCK == 0x53, "");
-_Static_assert(KC_KP_SLASH == 0x54, "");
-_Static_assert(KC_KP_ASTERISK == 0x55, "");
-_Static_assert(KC_KP_MINUS == 0x56, "");
-_Static_assert(KC_KP_PLUS == 0x57, "");
-_Static_assert(KC_KP_ENTER == 0x58, "");
-_Static_assert(KC_KP_1 == 0x59, "");
-_Static_assert(KC_KP_2 == 0x5A, "");
-_Static_assert(KC_KP_3 == 0x5B, "");
-_Static_assert(KC_KP_4 == 0x5C, "");
-_Static_assert(KC_KP_5 == 0x5D, "");
-_Static_assert(KC_KP_6 == 0x5E, "");
-_Static_assert(KC_KP_7 == 0x5F, "");
-_Static_assert(KC_KP_8 == 0x60, "");
-_Static_assert(KC_KP_9 == 0x61, "");
-_Static_assert(KC_KP_0 == 0x62, "");
-_Static_assert(KC_KP_DOT == 0x63, "");
-_Static_assert(KC_APPLICATION == 0x65, "");
-_Static_assert(KC_KP_EQUAL == 0x67, "");
-_Static_assert(KC_KP_COMMA == 0x85, "");
-_Static_assert(KC_LCTRL == 0xE0, "");
-_Static_assert(KC_LSHIFT == 0xE1, "");
-_Static_assert(KC_LALT == 0xE2, "");
-_Static_assert(KC_LGUI == 0xE3, "");
-_Static_assert(KC_RCTRL == 0xE4, "");
-_Static_assert(KC_RSHIFT == 0xE5, "");
-_Static_assert(KC_RALT == 0xE6, "");
-_Static_assert(KC_RGUI == 0xE7, "");
+_Static_assert(KC_NO == 0x0000, "");
+_Static_assert(KC_TRANSPARENT == 0x0001, "");
-_Static_assert(KC_TILD == 0x235, "");
-_Static_assert(KC_EXLM == 0x21E, "");
-_Static_assert(KC_AT == 0x21F, "");
-_Static_assert(KC_HASH == 0x220, "");
-_Static_assert(KC_DLR == 0x221, "");
-_Static_assert(KC_PERC == 0x222, "");
-_Static_assert(KC_CIRC == 0x223, "");
-_Static_assert(KC_AMPR == 0x224, "");
-_Static_assert(KC_ASTR == 0x225, "");
-_Static_assert(KC_LPRN == 0x226, "");
-_Static_assert(KC_RPRN == 0x227, "");
-_Static_assert(KC_UNDS == 0x22D, "");
-_Static_assert(KC_PLUS == 0x22E, "");
-_Static_assert(KC_LCBR == 0x22F, "");
-_Static_assert(KC_RCBR == 0x230, "");
-_Static_assert(KC_LT == 0x236, "");
-_Static_assert(KC_GT == 0x237, "");
-_Static_assert(KC_COLN == 0x233, "");
-_Static_assert(KC_PIPE == 0x231, "");
-_Static_assert(KC_QUES == 0x238, "");
-_Static_assert(KC_DQUO == 0x234, "");
+_Static_assert(KC_A == 0x0004, "");
+_Static_assert(KC_B == 0x0005, "");
+_Static_assert(KC_C == 0x0006, "");
+_Static_assert(KC_D == 0x0007, "");
+_Static_assert(KC_E == 0x0008, "");
+_Static_assert(KC_F == 0x0009, "");
+_Static_assert(KC_G == 0x000A, "");
+_Static_assert(KC_H == 0x000B, "");
+_Static_assert(KC_I == 0x000C, "");
+_Static_assert(KC_J == 0x000D, "");
+_Static_assert(KC_K == 0x000E, "");
+_Static_assert(KC_L == 0x000F, "");
+_Static_assert(KC_M == 0x0010, "");
+_Static_assert(KC_N == 0x0011, "");
+_Static_assert(KC_O == 0x0012, "");
+_Static_assert(KC_P == 0x0013, "");
+_Static_assert(KC_Q == 0x0014, "");
+_Static_assert(KC_R == 0x0015, "");
+_Static_assert(KC_S == 0x0016, "");
+_Static_assert(KC_T == 0x0017, "");
+_Static_assert(KC_U == 0x0018, "");
+_Static_assert(KC_V == 0x0019, "");
+_Static_assert(KC_W == 0x001A, "");
+_Static_assert(KC_X == 0x001B, "");
+_Static_assert(KC_Y == 0x001C, "");
+_Static_assert(KC_Z == 0x001D, "");
+_Static_assert(KC_1 == 0x001E, "");
+_Static_assert(KC_2 == 0x001F, "");
+_Static_assert(KC_3 == 0x0020, "");
+_Static_assert(KC_4 == 0x0021, "");
+_Static_assert(KC_5 == 0x0022, "");
+_Static_assert(KC_6 == 0x0023, "");
+_Static_assert(KC_7 == 0x0024, "");
+_Static_assert(KC_8 == 0x0025, "");
+_Static_assert(KC_9 == 0x0026, "");
+_Static_assert(KC_0 == 0x0027, "");
+_Static_assert(KC_ENTER == 0x0028, "");
+_Static_assert(KC_ESCAPE == 0x0029, "");
+_Static_assert(KC_BACKSPACE == 0x002A, "");
+_Static_assert(KC_TAB == 0x002B, "");
+_Static_assert(KC_SPACE == 0x002C, "");
+_Static_assert(KC_MINUS == 0x002D, "");
+_Static_assert(KC_EQUAL == 0x002E, "");
+_Static_assert(KC_LEFT_BRACKET == 0x002F, "");
+_Static_assert(KC_RIGHT_BRACKET == 0x0030, "");
+_Static_assert(KC_BACKSLASH == 0x0031, "");
+_Static_assert(KC_NONUS_HASH == 0x0032, "");
+_Static_assert(KC_SEMICOLON == 0x0033, "");
+_Static_assert(KC_QUOTE == 0x0034, "");
+_Static_assert(KC_GRAVE == 0x0035, "");
+_Static_assert(KC_COMMA == 0x0036, "");
+_Static_assert(KC_DOT == 0x0037, "");
+_Static_assert(KC_SLASH == 0x0038, "");
+_Static_assert(KC_CAPS_LOCK == 0x0039, "");
+_Static_assert(KC_F1 == 0x003A, "");
+_Static_assert(KC_F2 == 0x003B, "");
+_Static_assert(KC_F3 == 0x003C, "");
+_Static_assert(KC_F4 == 0x003D, "");
+_Static_assert(KC_F5 == 0x003E, "");
+_Static_assert(KC_F6 == 0x003F, "");
+_Static_assert(KC_F7 == 0x0040, "");
+_Static_assert(KC_F8 == 0x0041, "");
+_Static_assert(KC_F9 == 0x0042, "");
+_Static_assert(KC_F10 == 0x0043, "");
+_Static_assert(KC_F11 == 0x0044, "");
+_Static_assert(KC_F12 == 0x0045, "");
+_Static_assert(KC_PRINT_SCREEN == 0x0046, "");
+_Static_assert(KC_SCROLL_LOCK == 0x0047, "");
+_Static_assert(KC_PAUSE == 0x0048, "");
+_Static_assert(KC_INSERT == 0x0049, "");
+_Static_assert(KC_HOME == 0x004A, "");
+_Static_assert(KC_PAGE_UP == 0x004B, "");
+_Static_assert(KC_DELETE == 0x004C, "");
+_Static_assert(KC_END == 0x004D, "");
+_Static_assert(KC_PAGE_DOWN == 0x004E, "");
+_Static_assert(KC_RIGHT == 0x004F, "");
+_Static_assert(KC_LEFT == 0x0050, "");
+_Static_assert(KC_DOWN == 0x0051, "");
+_Static_assert(KC_UP == 0x0052, "");
+_Static_assert(KC_NUM_LOCK == 0x0053, "");
+_Static_assert(KC_KP_SLASH == 0x0054, "");
+_Static_assert(KC_KP_ASTERISK == 0x0055, "");
+_Static_assert(KC_KP_MINUS == 0x0056, "");
+_Static_assert(KC_KP_PLUS == 0x0057, "");
+_Static_assert(KC_KP_ENTER == 0x0058, "");
+_Static_assert(KC_KP_1 == 0x0059, "");
+_Static_assert(KC_KP_2 == 0x005A, "");
+_Static_assert(KC_KP_3 == 0x005B, "");
+_Static_assert(KC_KP_4 == 0x005C, "");
+_Static_assert(KC_KP_5 == 0x005D, "");
+_Static_assert(KC_KP_6 == 0x005E, "");
+_Static_assert(KC_KP_7 == 0x005F, "");
+_Static_assert(KC_KP_8 == 0x0060, "");
+_Static_assert(KC_KP_9 == 0x0061, "");
+_Static_assert(KC_KP_0 == 0x0062, "");
+_Static_assert(KC_KP_DOT == 0x0063, "");
+_Static_assert(KC_NONUS_BACKSLASH == 0x0064, "");
+_Static_assert(KC_APPLICATION == 0x0065, "");
+_Static_assert(KC_KB_POWER == 0x0066, "");
+_Static_assert(KC_KP_EQUAL == 0x0067, "");
+_Static_assert(KC_F13 == 0x0068, "");
+_Static_assert(KC_F14 == 0x0069, "");
+_Static_assert(KC_F15 == 0x006A, "");
+_Static_assert(KC_F16 == 0x006B, "");
+_Static_assert(KC_F17 == 0x006C, "");
+_Static_assert(KC_F18 == 0x006D, "");
+_Static_assert(KC_F19 == 0x006E, "");
+_Static_assert(KC_F20 == 0x006F, "");
+_Static_assert(KC_F21 == 0x0070, "");
+_Static_assert(KC_F22 == 0x0071, "");
+_Static_assert(KC_F23 == 0x0072, "");
+_Static_assert(KC_F24 == 0x0073, "");
+_Static_assert(KC_EXECUTE == 0x0074, "");
+_Static_assert(KC_HELP == 0x0075, "");
+_Static_assert(KC_MENU == 0x0076, "");
+_Static_assert(KC_SELECT == 0x0077, "");
+_Static_assert(KC_STOP == 0x0078, "");
+_Static_assert(KC_AGAIN == 0x0079, "");
+_Static_assert(KC_UNDO == 0x007A, "");
+_Static_assert(KC_CUT == 0x007B, "");
+_Static_assert(KC_COPY == 0x007C, "");
+_Static_assert(KC_PASTE == 0x007D, "");
+_Static_assert(KC_FIND == 0x007E, "");
-_Static_assert(KC_NONUS_HASH == 0x32, "");
-_Static_assert(KC_NONUS_BSLASH == 0x64, "");
-_Static_assert(KC_RO == 0x87, "");
-_Static_assert(KC_KANA == 0x88, "");
-_Static_assert(KC_JYEN == 0x89, "");
-_Static_assert(KC_HENK == 0x8A, "");
-_Static_assert(KC_MHEN == 0x8B, "");
-_Static_assert(KC_LANG1 == 0x90, "");
-_Static_assert(KC_LANG2 == 0x91, "");
+_Static_assert(KC_LOCKING_CAPS_LOCK == 0x0082, "");
+_Static_assert(KC_LOCKING_NUM_LOCK == 0x0083, "");
+_Static_assert(KC_LOCKING_SCROLL_LOCK == 0x0084, "");
+_Static_assert(KC_KP_COMMA == 0x0085, "");
+_Static_assert(KC_KP_EQUAL_AS400 == 0x0086, "");
+_Static_assert(KC_INTERNATIONAL_1 == 0x0087, "");
+_Static_assert(KC_INTERNATIONAL_2 == 0x0088, "");
+_Static_assert(KC_INTERNATIONAL_3 == 0x0089, "");
+_Static_assert(KC_INTERNATIONAL_4 == 0x008A, "");
+_Static_assert(KC_INTERNATIONAL_5 == 0x008B, "");
+_Static_assert(KC_INTERNATIONAL_6 == 0x008C, "");
+_Static_assert(KC_INTERNATIONAL_7 == 0x008D, "");
+_Static_assert(KC_INTERNATIONAL_8 == 0x008E, "");
+_Static_assert(KC_INTERNATIONAL_9 == 0x008F, "");
+_Static_assert(KC_LANGUAGE_1 == 0x0090, "");
+_Static_assert(KC_LANGUAGE_2 == 0x0091, "");
+_Static_assert(KC_LANGUAGE_3 == 0x0092, "");
+_Static_assert(KC_LANGUAGE_4 == 0x0093, "");
+_Static_assert(KC_LANGUAGE_5 == 0x0094, "");
+_Static_assert(KC_LANGUAGE_6 == 0x0095, "");
+_Static_assert(KC_LANGUAGE_7 == 0x0096, "");
+_Static_assert(KC_LANGUAGE_8 == 0x0097, "");
+_Static_assert(KC_LANGUAGE_9 == 0x0098, "");
+_Static_assert(KC_ALTERNATE_ERASE == 0x0099, "");
+_Static_assert(KC_SYSTEM_REQUEST == 0x009A, "");
+_Static_assert(KC_CANCEL == 0x009B, "");
+_Static_assert(KC_CLEAR == 0x009C, "");
+_Static_assert(KC_PRIOR == 0x009D, "");
-_Static_assert(KC_GESC == 0x5C16, "");
-_Static_assert(KC_LSPO == 0x5CD7, "");
-_Static_assert(KC_RSPC == 0x5CD8, "");
-_Static_assert(KC_LCPO == 0x5CF3, "");
-_Static_assert(KC_RCPC == 0x5CF4, "");
-_Static_assert(KC_LAPO == 0x5CF5, "");
-_Static_assert(KC_RAPC == 0x5CF6, "");
-_Static_assert(KC_SFTENT == 0x5CD9, "");
+_Static_assert(KC_OUT == 0x00A0, "");
+_Static_assert(KC_OPER == 0x00A1, "");
+_Static_assert(KC_CLEAR_AGAIN == 0x00A2, "");
+_Static_assert(KC_CRSEL == 0x00A3, "");
+_Static_assert(KC_EXSEL == 0x00A4, "");
-_Static_assert(BL_TOGG == 23743, "");
-_Static_assert(BL_STEP == 23744, "");
-_Static_assert(BL_BRTG == 23745, "");
-_Static_assert(BL_ON == 23739, "");
-_Static_assert(BL_OFF == 23740, "");
-_Static_assert(BL_INC == 23742, "");
-_Static_assert(BL_DEC == 23741, "");
-_Static_assert(RGB_TOG == 23746, "");
-_Static_assert(RGB_MOD == 23747, "");
-_Static_assert(RGB_RMOD == 23748, "");
-_Static_assert(RGB_HUI == 23749, "");
-_Static_assert(RGB_HUD == 23750, "");
-_Static_assert(RGB_SAI == 23751, "");
-_Static_assert(RGB_SAD == 23752, "");
-_Static_assert(RGB_VAI == 23753, "");
-_Static_assert(RGB_VAD == 23754, "");
-_Static_assert(RGB_SPI == 23755, "");
-_Static_assert(RGB_SPD == 23756, "");
-_Static_assert(RGB_M_P == 23757, "");
-_Static_assert(RGB_M_B == 23758, "");
-_Static_assert(RGB_M_R == 23759, "");
-_Static_assert(RGB_M_SW == 23760, "");
-_Static_assert(RGB_M_SN == 23761, "");
-_Static_assert(RGB_M_K == 23762, "");
-_Static_assert(RGB_M_X == 23763, "");
-_Static_assert(RGB_M_G == 23764, "");
-_Static_assert(RGB_M_T == 23765, "");
+_Static_assert(KC_PWR == 0x00A5, "");
+_Static_assert(KC_SLEP == 0x00A6, "");
+_Static_assert(KC_WAKE == 0x00A7, "");
+_Static_assert(KC_MUTE == 0x00A8, "");
+_Static_assert(KC_VOLU == 0x00A9, "");
+_Static_assert(KC_VOLD == 0x00AA, "");
+_Static_assert(KC_MNXT == 0x00AB, "");
+_Static_assert(KC_MPRV == 0x00AC, "");
+_Static_assert(KC_MSTP == 0x00AD, "");
+_Static_assert(KC_MPLY == 0x00AE, "");
+_Static_assert(KC_MSEL == 0x00AF, "");
+_Static_assert(KC_EJCT == 0x00B0, "");
+_Static_assert(KC_MAIL == 0x00B1, "");
+_Static_assert(KC_CALC == 0x00B2, "");
+_Static_assert(KC_MYCM == 0x00B3, "");
+_Static_assert(KC_WSCH == 0x00B4, "");
+_Static_assert(KC_WHOM == 0x00B5, "");
+_Static_assert(KC_WBAK == 0x00B6, "");
+_Static_assert(KC_WFWD == 0x00B7, "");
+_Static_assert(KC_WSTP == 0x00B8, "");
+_Static_assert(KC_WREF == 0x00B9, "");
+_Static_assert(KC_WFAV == 0x00BA, "");
+_Static_assert(KC_MFFD == 0x00BB, "");
+_Static_assert(KC_MRWD == 0x00BC, "");
+_Static_assert(KC_BRIU == 0x00BD, "");
+_Static_assert(KC_BRID == 0x00BE, "");
-_Static_assert(KC_F13 == 104, "");
-_Static_assert(KC_F14 == 105, "");
-_Static_assert(KC_F15 == 106, "");
-_Static_assert(KC_F16 == 107, "");
-_Static_assert(KC_F17 == 108, "");
-_Static_assert(KC_F18 == 109, "");
-_Static_assert(KC_F19 == 110, "");
-_Static_assert(KC_F20 == 111, "");
-_Static_assert(KC_F21 == 112, "");
-_Static_assert(KC_F22 == 113, "");
-_Static_assert(KC_F23 == 114, "");
-_Static_assert(KC_F24 == 115, "");
-_Static_assert(KC_PWR == 165, "");
-_Static_assert(KC_SLEP == 166, "");
-_Static_assert(KC_WAKE == 167, "");
-_Static_assert(KC_EXEC == 116, "");
-_Static_assert(KC_HELP == 117, "");
-_Static_assert(KC_SLCT == 119, "");
-_Static_assert(KC_STOP == 120, "");
-_Static_assert(KC_AGIN == 121, "");
-_Static_assert(KC_UNDO == 122, "");
-_Static_assert(KC_CUT == 123, "");
-_Static_assert(KC_COPY == 124, "");
-_Static_assert(KC_PSTE == 125, "");
-_Static_assert(KC_FIND == 126, "");
-_Static_assert(KC_CALC == 178, "");
-_Static_assert(KC_MAIL == 177, "");
-_Static_assert(KC_MSEL == 175, "");
-_Static_assert(KC_MYCM == 179, "");
-_Static_assert(KC_WSCH == 180, "");
-_Static_assert(KC_WHOM == 181, "");
-_Static_assert(KC_WBAK == 182, "");
-_Static_assert(KC_WFWD == 183, "");
-_Static_assert(KC_WSTP == 184, "");
-_Static_assert(KC_WREF == 185, "");
-_Static_assert(KC_WFAV == 186, "");
-_Static_assert(KC_BRIU == 189, "");
-_Static_assert(KC_BRID == 190, "");
-_Static_assert(KC_MPRV == 172, "");
-_Static_assert(KC_MNXT == 171, "");
-_Static_assert(KC_MUTE == 168, "");
-_Static_assert(KC_VOLD == 170, "");
-_Static_assert(KC_VOLU == 169, "");
-_Static_assert(KC_MSTP == 173, "");
-_Static_assert(KC_MPLY == 174, "");
-_Static_assert(KC_MRWD == 188, "");
-_Static_assert(KC_MFFD == 187, "");
-_Static_assert(KC_EJCT == 176, "");
-_Static_assert(KC_MS_U == 240, "");
-_Static_assert(KC_MS_D == 241, "");
-_Static_assert(KC_MS_L == 242, "");
-_Static_assert(KC_MS_R == 243, "");
-_Static_assert(KC_BTN1 == 244, "");
-_Static_assert(KC_BTN2 == 245, "");
-_Static_assert(KC_BTN3 == 246, "");
-_Static_assert(KC_BTN4 == 247, "");
-_Static_assert(KC_BTN5 == 248, "");
-_Static_assert(KC_WH_U == 249, "");
-_Static_assert(KC_WH_D == 250, "");
-_Static_assert(KC_WH_L == 251, "");
-_Static_assert(KC_WH_R == 252, "");
-_Static_assert(KC_ACL0 == 253, "");
-_Static_assert(KC_ACL1 == 254, "");
-_Static_assert(KC_ACL2 == 255, "");
-_Static_assert(KC_LCAP == 130, "");
-_Static_assert(KC_LNUM == 131, "");
-_Static_assert(KC_LSCR == 132, "");
+_Static_assert(KC_LEFT_CTRL == 0x00E0, "");
+_Static_assert(KC_LEFT_SHIFT == 0x00E1, "");
+_Static_assert(KC_LEFT_ALT == 0x00E2, "");
+_Static_assert(KC_LEFT_GUI == 0x00E3, "");
+_Static_assert(KC_RIGHT_CTRL == 0x00E4, "");
+_Static_assert(KC_RIGHT_SHIFT == 0x00E5, "");
+_Static_assert(KC_RIGHT_ALT == 0x00E6, "");
+_Static_assert(KC_RIGHT_GUI == 0x00E7, "");
-_Static_assert(FN_MO13 == 0x5F10, "");
-_Static_assert(FN_MO23 == 0x5F11, "");
+_Static_assert(KC_MS_U == 0x00F0, "");
+_Static_assert(KC_MS_D == 0x00F1, "");
+_Static_assert(KC_MS_L == 0x00F2, "");
+_Static_assert(KC_MS_R == 0x00F3, "");
+_Static_assert(KC_BTN1 == 0x00F4, "");
+_Static_assert(KC_BTN2 == 0x00F5, "");
+_Static_assert(KC_BTN3 == 0x00F6, "");
+_Static_assert(KC_BTN4 == 0x00F7, "");
+_Static_assert(KC_BTN5 == 0x00F8, "");
+_Static_assert(KC_WH_U == 0x00F9, "");
+_Static_assert(KC_WH_D == 0x00FA, "");
+_Static_assert(KC_WH_L == 0x00FB, "");
+_Static_assert(KC_WH_R == 0x00FC, "");
+_Static_assert(KC_ACL0 == 0x00FD, "");
+_Static_assert(KC_ACL1 == 0x00FE, "");
+_Static_assert(KC_ACL2 == 0x00FF, "");
-_Static_assert(MACRO00 == 0x5F12, "");
-_Static_assert(MACRO01 == 0x5F13, "");
-_Static_assert(MACRO02 == 0x5F14, "");
-_Static_assert(MACRO03 == 0x5F15, "");
-_Static_assert(MACRO04 == 0x5F16, "");
-_Static_assert(MACRO05 == 0x5F17, "");
-_Static_assert(MACRO06 == 0x5F18, "");
-_Static_assert(MACRO07 == 0x5F19, "");
-_Static_assert(MACRO08 == 0x5F1A, "");
-_Static_assert(MACRO09 == 0x5F1B, "");
-_Static_assert(MACRO10 == 0x5F1C, "");
-_Static_assert(MACRO11 == 0x5F1D, "");
-_Static_assert(MACRO12 == 0x5F1E, "");
-_Static_assert(MACRO13 == 0x5F1F, "");
-_Static_assert(MACRO14 == 0x5F20, "");
-_Static_assert(MACRO15 == 0x5F21, "");
+_Static_assert(KC_EXLM == 0x021E, "");
+_Static_assert(KC_AT == 0x021F, "");
+_Static_assert(KC_HASH == 0x0220, "");
+_Static_assert(KC_DLR == 0x0221, "");
+_Static_assert(KC_PERC == 0x0222, "");
+_Static_assert(KC_CIRC == 0x0223, "");
+_Static_assert(KC_AMPR == 0x0224, "");
+_Static_assert(KC_ASTR == 0x0225, "");
+_Static_assert(KC_LPRN == 0x0226, "");
+_Static_assert(KC_RPRN == 0x0227, "");
+_Static_assert(KC_UNDS == 0x022D, "");
+_Static_assert(KC_PLUS == 0x022E, "");
+_Static_assert(KC_LCBR == 0x022F, "");
+_Static_assert(KC_RCBR == 0x0230, "");
+_Static_assert(KC_PIPE == 0x0231, "");
+_Static_assert(KC_COLN == 0x0233, "");
+_Static_assert(KC_DQUO == 0x0234, "");
+_Static_assert(KC_TILD == 0x0235, "");
+_Static_assert(KC_LT == 0x0236, "");
+_Static_assert(KC_GT == 0x0237, "");
+_Static_assert(KC_QUES == 0x0238, "");
-_Static_assert(USER00 == 0x5F80, "");
-_Static_assert(USER01 == 0x5F81, "");
-_Static_assert(USER02 == 0x5F82, "");
-_Static_assert(USER03 == 0x5F83, "");
-_Static_assert(USER04 == 0x5F84, "");
-_Static_assert(USER05 == 0x5F85, "");
-_Static_assert(USER06 == 0x5F86, "");
-_Static_assert(USER07 == 0x5F87, "");
-_Static_assert(USER08 == 0x5F88, "");
-_Static_assert(USER09 == 0x5F89, "");
-_Static_assert(USER10 == 0x5F8A, "");
-_Static_assert(USER11 == 0x5F8B, "");
-_Static_assert(USER12 == 0x5F8C, "");
-_Static_assert(USER13 == 0x5F8D, "");
-_Static_assert(USER14 == 0x5F8E, "");
-_Static_assert(USER15 == 0x5F8F, "");
+_Static_assert(RESET == 0x5C00, "");
+_Static_assert(DEBUG == 0x5C01, "");
-_Static_assert(KC_POWER == 102, "");
-_Static_assert(KC_MENU == 118, "");
-_Static_assert(KC_KP_EQUAL_AS400 == 134, "");
-_Static_assert(KC_INT6 == 140, "");
-_Static_assert(KC_INT7 == 141, "");
-_Static_assert(KC_INT8 == 142, "");
-_Static_assert(KC_INT9 == 143, "");
-_Static_assert(KC_LANG3 == 146, "");
-_Static_assert(KC_LANG4 == 147, "");
-_Static_assert(KC_LANG5 == 148, "");
-_Static_assert(KC_LANG6 == 149, "");
-_Static_assert(KC_LANG7 == 150, "");
-_Static_assert(KC_LANG8 == 151, "");
-_Static_assert(KC_LANG9 == 152, "");
-_Static_assert(KC_ERAS == 153, "");
-_Static_assert(KC_SYSREQ == 154, "");
-_Static_assert(KC_CANCEL == 155, "");
-_Static_assert(KC_CLEAR == 156, "");
-_Static_assert(KC_CLR == 156, "");
-_Static_assert(KC_PRIOR == 157, "");
-_Static_assert(KC_OUT == 160, "");
-_Static_assert(KC_OPER == 161, "");
-_Static_assert(KC_CLEAR_AGAIN == 162, "");
-_Static_assert(KC_CRSEL == 163, "");
-_Static_assert(KC_EXSEL == 164, "");
-_Static_assert(KC_FN0 == 192, "");
-_Static_assert(KC_FN1 == 193, "");
-_Static_assert(KC_FN2 == 194, "");
-_Static_assert(KC_FN3 == 195, "");
-_Static_assert(KC_FN4 == 196, "");
-_Static_assert(KC_FN5 == 197, "");
-_Static_assert(KC_FN6 == 198, "");
-_Static_assert(KC_FN7 == 199, "");
-_Static_assert(KC_FN8 == 200, "");
-_Static_assert(KC_FN9 == 201, "");
-_Static_assert(KC_FN10 == 202, "");
-_Static_assert(KC_FN11 == 203, "");
-_Static_assert(KC_FN12 == 204, "");
-_Static_assert(KC_FN13 == 205, "");
-_Static_assert(KC_FN14 == 206, "");
-_Static_assert(KC_FN15 == 207, "");
-_Static_assert(KC_FN16 == 208, "");
-_Static_assert(KC_FN17 == 209, "");
-_Static_assert(KC_FN18 == 210, "");
-_Static_assert(KC_FN19 == 211, "");
-_Static_assert(KC_FN20 == 212, "");
-_Static_assert(KC_FN21 == 213, "");
-_Static_assert(KC_FN22 == 214, "");
-_Static_assert(KC_FN23 == 215, "");
-_Static_assert(KC_FN24 == 216, "");
-_Static_assert(KC_FN25 == 217, "");
-_Static_assert(KC_FN26 == 218, "");
-_Static_assert(KC_FN27 == 219, "");
-_Static_assert(KC_FN28 == 220, "");
-_Static_assert(KC_FN29 == 221, "");
-_Static_assert(KC_FN30 == 222, "");
-_Static_assert(KC_FN31 == 223, "");
-_Static_assert(RESET == 23552, "");
-_Static_assert(DEBUG == 23553, "");
-_Static_assert(MAGIC_TOGGLE_NKRO == 23572, "");
-_Static_assert(AU_ON == 23581, "");
-_Static_assert(AU_OFF == 23582, "");
-_Static_assert(AU_TOG == 23583, "");
-_Static_assert(CLICKY_TOGGLE == 23584, "");
-_Static_assert(CLICKY_ENABLE == 23585, "");
-_Static_assert(CLICKY_DISABLE == 23586, "");
-_Static_assert(CLICKY_UP == 23587, "");
-_Static_assert(CLICKY_DOWN == 23588, "");
-_Static_assert(CLICKY_RESET == 23589, "");
-_Static_assert(MU_ON == 23590, "");
-_Static_assert(MU_OFF == 23591, "");
-_Static_assert(MU_TOG == 23592, "");
-_Static_assert(MU_MOD == 23593, "");
+_Static_assert(MAGIC_TOGGLE_NKRO == 0x5C14, "");
+
+_Static_assert(KC_GESC == 0x5C16, "");
+
+_Static_assert(AU_ON == 0x5C1D, "");
+_Static_assert(AU_OFF == 0x5C1E, "");
+_Static_assert(AU_TOG == 0x5C1F, "");
+
+_Static_assert(CLICKY_TOGGLE == 0x5C20, "");
+_Static_assert(CLICKY_ENABLE == 0x5C21, "");
+_Static_assert(CLICKY_DISABLE == 0x5C22, "");
+_Static_assert(CLICKY_UP == 0x5C23, "");
+_Static_assert(CLICKY_DOWN == 0x5C24, "");
+_Static_assert(CLICKY_RESET == 0x5C25, "");
+_Static_assert(MU_ON == 0x5C26, "");
+_Static_assert(MU_OFF == 0x5C27, "");
+_Static_assert(MU_TOG == 0x5C28, "");
+_Static_assert(MU_MOD == 0x5C29, "");
+
+_Static_assert(BL_ON == 0x5CBB, "");
+_Static_assert(BL_OFF == 0x5CBC, "");
+_Static_assert(BL_DEC == 0x5CBD, "");
+_Static_assert(BL_INC == 0x5CBE, "");
+_Static_assert(BL_TOGG == 0x5CBF, "");
+_Static_assert(BL_STEP == 0x5CC0, "");
+_Static_assert(BL_BRTG == 0x5CC1, "");
+_Static_assert(RGB_TOG == 0x5CC2, "");
+_Static_assert(RGB_MOD == 0x5CC3, "");
+_Static_assert(RGB_RMOD == 0x5CC4, "");
+_Static_assert(RGB_HUI == 0x5CC5, "");
+_Static_assert(RGB_HUD == 0x5CC6, "");
+_Static_assert(RGB_SAI == 0x5CC7, "");
+_Static_assert(RGB_SAD == 0x5CC8, "");
+_Static_assert(RGB_VAI == 0x5CC9, "");
+_Static_assert(RGB_VAD == 0x5CCA, "");
+_Static_assert(RGB_SPI == 0x5CCB, "");
+_Static_assert(RGB_SPD == 0x5CCC, "");
+_Static_assert(RGB_M_P == 0x5CCD, "");
+_Static_assert(RGB_M_B == 0x5CCE, "");
+_Static_assert(RGB_M_R == 0x5CCF, "");
+_Static_assert(RGB_M_SW == 0x5CD0, "");
+_Static_assert(RGB_M_SN == 0x5CD1, "");
+_Static_assert(RGB_M_K == 0x5CD2, "");
+_Static_assert(RGB_M_X == 0x5CD3, "");
+_Static_assert(RGB_M_G == 0x5CD4, "");
+_Static_assert(RGB_M_T == 0x5CD5, "");
+
+_Static_assert(KC_LSPO == 0x5CD7, "");
+_Static_assert(KC_RSPC == 0x5CD8, "");
+_Static_assert(KC_SFTENT == 0x5CD9, "");
+
+_Static_assert(KC_LCPO == 0x5CF3, "");
+_Static_assert(KC_RCPC == 0x5CF4, "");
+_Static_assert(KC_LAPO == 0x5CF5, "");
+_Static_assert(KC_RAPC == 0x5CF6, "");
+
+_Static_assert(FN_MO13 == 0x5F10, "");
+_Static_assert(FN_MO23 == 0x5F11, "");
+_Static_assert(MACRO00 == 0x5F12, "");
+_Static_assert(MACRO01 == 0x5F13, "");
+_Static_assert(MACRO02 == 0x5F14, "");
+_Static_assert(MACRO03 == 0x5F15, "");
+_Static_assert(MACRO04 == 0x5F16, "");
+_Static_assert(MACRO05 == 0x5F17, "");
+_Static_assert(MACRO06 == 0x5F18, "");
+_Static_assert(MACRO07 == 0x5F19, "");
+_Static_assert(MACRO08 == 0x5F1A, "");
+_Static_assert(MACRO09 == 0x5F1B, "");
+_Static_assert(MACRO10 == 0x5F1C, "");
+_Static_assert(MACRO11 == 0x5F1D, "");
+_Static_assert(MACRO12 == 0x5F1E, "");
+_Static_assert(MACRO13 == 0x5F1F, "");
+_Static_assert(MACRO14 == 0x5F20, "");
+_Static_assert(MACRO15 == 0x5F21, "");
+
+_Static_assert(USER00 == 0x5F80, "");
+_Static_assert(USER01 == 0x5F81, "");
+_Static_assert(USER02 == 0x5F82, "");
+_Static_assert(USER03 == 0x5F83, "");
+_Static_assert(USER04 == 0x5F84, "");
+_Static_assert(USER05 == 0x5F85, "");
+_Static_assert(USER06 == 0x5F86, "");
+_Static_assert(USER07 == 0x5F87, "");
+_Static_assert(USER08 == 0x5F88, "");
+_Static_assert(USER09 == 0x5F89, "");
+_Static_assert(USER10 == 0x5F8A, "");
+_Static_assert(USER11 == 0x5F8B, "");
+_Static_assert(USER12 == 0x5F8C, "");
+_Static_assert(USER13 == 0x5F8D, "");
+_Static_assert(USER14 == 0x5F8E, "");
+_Static_assert(USER15 == 0x5F8F, "");
#endif
diff --git a/tmk_core/common/virtser.h b/quantum/virtser.h
index a0645f9e03..df7e87984c 100644
--- a/tmk_core/common/virtser.h
+++ b/quantum/virtser.h
@@ -1,5 +1,7 @@
#pragma once
+void virtser_init(void);
+
/* Define this function in your code to process incoming bytes */
void virtser_recv(const uint8_t ch);
diff --git a/quantum/visualizer/LICENSE.md b/quantum/visualizer/LICENSE.md
deleted file mode 100644
index 22d4c3f08b..0000000000
--- a/quantum/visualizer/LICENSE.md
+++ /dev/null
@@ -1,29 +0,0 @@
-The files in this project are licensed under the MIT license
-It uses the following libraries
-uGFX - with it's own license, see the license.html file in the uGFX subfolder for more information
-tmk_core - is indirectly used and not included in the repository. It's licensed under the GPLv2 license
-Chibios - which is used by tmk_core is licensed under GPLv3.
-
-Therefore the effective license for any project using the library is GPLv3
-
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/quantum/visualizer/common_gfxconf.h b/quantum/visualizer/common_gfxconf.h
deleted file mode 100644
index e0735b37d0..0000000000
--- a/quantum/visualizer/common_gfxconf.h
+++ /dev/null
@@ -1,354 +0,0 @@
-/**
- * This file has a different license to the rest of the uGFX system.
- * You can copy, modify and distribute this file as you see fit.
- * You do not need to publish your source modifications to this file.
- * The only thing you are not permitted to do is to relicense it
- * under a different license.
- */
-
-/**
- * Copy this file into your project directory and rename it as gfxconf.h
- * Edit your copy to turn on the uGFX features you want to use.
- * The values below are the defaults.
- *
- * Only remove the comments from lines where you want to change the
- * default value. This allows definitions to be included from
- * driver makefiles when required and provides the best future
- * compatibility for your project.
- *
- * Please use spaces instead of tabs in this file.
- */
-
-#pragma once
-
-///////////////////////////////////////////////////////////////////////////
-// GFX - Compatibility options //
-///////////////////////////////////////////////////////////////////////////
-//#define GFX_COMPAT_V2 GFXON
-//#define GFX_COMPAT_OLDCOLORS GFXON
-
-///////////////////////////////////////////////////////////////////////////
-// GOS - One of these must be defined, preferably in your Makefile //
-///////////////////////////////////////////////////////////////////////////
-//#define GFX_USE_OS_CHIBIOS GFXOFF
-//#define GFX_USE_OS_FREERTOS GFXOFF
-// #define GFX_FREERTOS_USE_TRACE GFXOFF
-//#define GFX_USE_OS_WIN32 GFXOFF
-//#define GFX_USE_OS_LINUX GFXOFF
-//#define GFX_USE_OS_OSX GFXOFF
-//#define GFX_USE_OS_ECOS GFXOFF
-//#define GFX_USE_OS_RAWRTOS GFXOFF
-//#define GFX_USE_OS_ARDUINO GFXOFF
-//#define GFX_USE_OS_KEIL GFXOFF
-//#define GFX_USE_OS_RTX5 GFXOFF
-//#define GFX_USE_OS_CMSIS GFXOFF
-//#define GFX_USE_OS_CMSIS2 GFXOFF
-//#define GFX_USE_OS_RAW32 GFXOFF
-//#define GFX_USE_OS_ZEPHYR GFXOFF
-//#define GFX_USE_OS_NIOS GFXOFF
-//#define GFX_USE_OS_QT GFXOFF
-// #define INTERRUPTS_OFF() optional_code
-// #define INTERRUPTS_ON() optional_code
-
-// Options that (should where relevant) apply to all operating systems
-#define GFX_NO_INLINE GFXON
-// #define GFX_COMPILER GFX_COMPILER_UNKNOWN
-// #define GFX_SHOW_COMPILER GFXOFF
-// #define GFX_CPU GFX_CPU_UNKNOWN
-// #define GFX_CPU_NO_ALIGNMENT_FAULTS GFXOFF
-// #define GFX_CPU_ENDIAN GFX_CPU_ENDIAN_UNKNOWN
-// #define GFX_OS_HEAP_SIZE 0
-// #define GFX_OS_NO_INIT GFXOFF
-// #define GFX_OS_INIT_NO_WARNING GFXOFF
-// #define GFX_OS_PRE_INIT_FUNCTION myHardwareInitRoutine
-// #define GFX_OS_EXTRA_INIT_FUNCTION myOSInitRoutine
-// #define GFX_OS_EXTRA_DEINIT_FUNCTION myOSDeInitRoutine
-// #define GFX_OS_CALL_UGFXMAIN GFXOFF
-// #define GFX_OS_UGFXMAIN_STACKSIZE 0
-// #define GFX_EMULATE_MALLOC GFXOFF
-// #define GFX_MEM_LT64K GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GDISP //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GDISP GFXON
-
-//#define GDISP_NEED_AUTOFLUSH GFXOFF
-//#define GDISP_NEED_TIMERFLUSH GFXOFF
-//#define GDISP_NEED_VALIDATION GFXON
-//#define GDISP_NEED_CLIP GFXON
-#define GDISP_NEED_CIRCLE GFXON
-//#define GDISP_NEED_DUALCIRCLE GFXOFF
-#define GDISP_NEED_ELLIPSE GFXON
-#define GDISP_NEED_ARC GFXON
-#define GDISP_NEED_ARCSECTORS GFXON
-#define GDISP_NEED_CONVEX_POLYGON GFXON
-//#define GDISP_NEED_SCROLL GFXOFF
-#define GDISP_NEED_PIXELREAD GFXON
-#define GDISP_NEED_CONTROL GFXON
-//#define GDISP_NEED_QUERY GFXOFF
-//#define GDISP_NEED_MULTITHREAD GFXOFF
-//#define GDISP_NEED_STREAMING GFXOFF
-#define GDISP_NEED_TEXT GFXON
-// #define GDISP_NEED_TEXT_WORDWRAP GFXOFF
-// #define GDISP_NEED_TEXT_BOXPADLR 1
-// #define GDISP_NEED_TEXT_BOXPADTB 1
-// #define GDISP_NEED_ANTIALIAS GFXOFF
-// #define GDISP_NEED_UTF8 GFXOFF
-#define GDISP_NEED_TEXT_KERNING GFXON
-// #define GDISP_INCLUDE_FONT_UI1 GFXOFF
-// #define GDISP_INCLUDE_FONT_UI2 GFXOFF // The smallest preferred font.
-// #define GDISP_INCLUDE_FONT_LARGENUMBERS GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS10 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS12 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS16 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS20 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS24 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS32 GFXOFF
-#define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 GFXON
-// #define GDISP_INCLUDE_FONT_FIXED_10X20 GFXOFF
-// #define GDISP_INCLUDE_FONT_FIXED_7X14 GFXOFF
-#define GDISP_INCLUDE_FONT_FIXED_5X8 GFXON
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS20_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA GFXOFF
-// #define GDISP_INCLUDE_USER_FONTS GFXOFF
-
-//#define GDISP_NEED_IMAGE GFXOFF
-// #define GDISP_NEED_IMAGE_NATIVE GFXOFF
-// #define GDISP_NEED_IMAGE_GIF GFXOFF
-// #define GDISP_IMAGE_GIF_BLIT_BUFFER_SIZE 32
-// #define GDISP_NEED_IMAGE_BMP GFXOFF
-// #define GDISP_NEED_IMAGE_BMP_1 GFXON
-// #define GDISP_NEED_IMAGE_BMP_4 GFXON
-// #define GDISP_NEED_IMAGE_BMP_4_RLE GFXON
-// #define GDISP_NEED_IMAGE_BMP_8 GFXON
-// #define GDISP_NEED_IMAGE_BMP_8_RLE GFXON
-// #define GDISP_NEED_IMAGE_BMP_16 GFXON
-// #define GDISP_NEED_IMAGE_BMP_24 GFXON
-// #define GDISP_NEED_IMAGE_BMP_32 GFXON
-// #define GDISP_IMAGE_BMP_BLIT_BUFFER_SIZE 32
-// #define GDISP_NEED_IMAGE_JPG GFXOFF
-// #define GDISP_NEED_IMAGE_PNG GFXOFF
-// #define GDISP_NEED_IMAGE_PNG_INTERLACED GFXOFF
-// #define GDISP_NEED_IMAGE_PNG_TRANSPARENCY GFXON
-// #define GDISP_NEED_IMAGE_PNG_BACKGROUND GFXON
-// #define GDISP_NEED_IMAGE_PNG_ALPHACLIFF 32
-// #define GDISP_NEED_IMAGE_PNG_PALETTE_124 GFXON
-// #define GDISP_NEED_IMAGE_PNG_PALETTE_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 GFXON
-// #define GDISP_NEED_IMAGE_PNG_RGB_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_RGB_16 GFXON
-// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_16 GFXON
-// #define GDISP_IMAGE_PNG_BLIT_BUFFER_SIZE 32
-// #define GDISP_IMAGE_PNG_FILE_BUFFER_SIZE 8
-// #define GDISP_IMAGE_PNG_Z_BUFFER_SIZE 32768
-// #define GDISP_NEED_IMAGE_ACCOUNTING GFXOFF
-
-//#define GDISP_NEED_PIXMAP GFXOFF
-// #define GDISP_NEED_PIXMAP_IMAGE GFXOFF
-
-//#define GDISP_DEFAULT_ORIENTATION gOrientationLandscape // If not defined the native hardware orientation is used.
-//#define GDISP_LINEBUF_SIZE 128
-//#define GDISP_STARTUP_COLOR GFX_BLACK
-#define GDISP_NEED_STARTUP_LOGO GFXOFF
-
-//#define GDISP_TOTAL_DISPLAYS 1
-
-//#define GDISP_DRIVER_LIST GDISPVMT_Win32, GDISPVMT_Win32
-#ifdef GDISP_DRIVER_LIST
-// // For code and speed optimization define as GFXON or GFXOFF if all controllers have the same capability
-# define GDISP_HARDWARE_STREAM_WRITE GFXOFF
-# define GDISP_HARDWARE_STREAM_READ GFXOFF
-# define GDISP_HARDWARE_STREAM_POS GFXOFF
-# define GDISP_HARDWARE_DRAWPIXEL GFXON
-# define GDISP_HARDWARE_CLEARS GFXOFF
-# define GDISP_HARDWARE_FILLS GFXOFF
-//#define GDISP_HARDWARE_BITFILLS GFXOFF
-# define GDISP_HARDWARE_SCROLL GFXOFF
-# define GDISP_HARDWARE_PIXELREAD GFXON
-# define GDISP_HARDWARE_CONTROL GFXON
-# define GDISP_HARDWARE_QUERY GFXOFF
-# define GDISP_HARDWARE_CLIP GFXOFF
-
-# define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
-#endif
-
-#define GDISP_USE_GFXNET GFXOFF
-// #define GDISP_GFXNET_PORT 13001
-// #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP GFXOFF
-// #define GDISP_DONT_WAIT_FOR_NET_DISPLAY GFXOFF
-// #define GDISP_GFXNET_UNSAFE_SOCKETS GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GWIN //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GWIN GFXOFF
-
-//#define GWIN_NEED_WINDOWMANAGER GFXOFF
-// #define GWIN_REDRAW_IMMEDIATE GFXOFF
-// #define GWIN_REDRAW_SINGLEOP GFXOFF
-// #define GWIN_NEED_FLASHING GFXOFF
-// #define GWIN_FLASHING_PERIOD 250
-
-//#define GWIN_NEED_CONSOLE GFXOFF
-// #define GWIN_CONSOLE_USE_HISTORY GFXOFF
-// #define GWIN_CONSOLE_HISTORY_AVERAGING GFXOFF
-// #define GWIN_CONSOLE_HISTORY_ATCREATE GFXOFF
-// #define GWIN_CONSOLE_ESCSEQ GFXOFF
-// #define GWIN_CONSOLE_USE_BASESTREAM GFXOFF
-// #define GWIN_CONSOLE_USE_FLOAT GFXOFF
-//#define GWIN_NEED_GRAPH GFXOFF
-//#define GWIN_NEED_GL3D GFXOFF
-
-//#define GWIN_NEED_WIDGET GFXOFF
-//#define GWIN_FOCUS_HIGHLIGHT_WIDTH 1
-// #define GWIN_NEED_LABEL GFXOFF
-// #define GWIN_LABEL_ATTRIBUTE GFXOFF
-// #define GWIN_NEED_BUTTON GFXOFF
-// #define GWIN_BUTTON_LAZY_RELEASE GFXOFF
-// #define GWIN_NEED_SLIDER GFXOFF
-// #define GWIN_SLIDER_NOSNAP GFXOFF
-// #define GWIN_SLIDER_DEAD_BAND 5
-// #define GWIN_SLIDER_TOGGLE_INC 20
-// #define GWIN_NEED_CHECKBOX GFXOFF
-// #define GWIN_NEED_IMAGE GFXOFF
-// #define GWIN_NEED_IMAGE_ANIMATION GFXOFF
-// #define GWIN_NEED_RADIO GFXOFF
-// #define GWIN_NEED_LIST GFXOFF
-// #define GWIN_NEED_LIST_IMAGES GFXOFF
-// #define GWIN_NEED_PROGRESSBAR GFXOFF
-// #define GWIN_PROGRESSBAR_AUTO GFXOFF
-// #define GWIN_NEED_KEYBOARD GFXOFF
-// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1
-// #define GWIN_NEED_KEYBOARD_ENGLISH1 GFXON
-// #define GWIN_NEED_TEXTEDIT GFXOFF
-// #define GWIN_FLAT_STYLING GFXOFF
-// #define GWIN_WIDGET_TAGS GFXOFF
-
-//#define GWIN_NEED_CONTAINERS GFXOFF
-// #define GWIN_NEED_CONTAINER GFXOFF
-// #define GWIN_NEED_FRAME GFXOFF
-// #define GWIN_NEED_TABSET GFXOFF
-// #define GWIN_TABSET_TABHEIGHT 18
-
-///////////////////////////////////////////////////////////////////////////
-// GTRANS //
-///////////////////////////////////////////////////////////////////////////
-//#define GFX_USE_GTRANS GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GEVENT //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GEVENT GFXON
-
-//#define GEVENT_ASSERT_NO_RESOURCE GFXOFF
-//#define GEVENT_MAXIMUM_SIZE 32
-//#define GEVENT_MAX_SOURCE_LISTENERS 32
-
-///////////////////////////////////////////////////////////////////////////
-// GTIMER //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GTIMER GFXOFF
-
-//#define GTIMER_THREAD_PRIORITY gThreadpriorityHigh
-//#define GTIMER_THREAD_WORKAREA_SIZE 2048
-
-///////////////////////////////////////////////////////////////////////////
-// GQUEUE //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GQUEUE GFXOFF
-
-//#define GQUEUE_NEED_ASYNC GFXOFF
-//#define GQUEUE_NEED_GSYNC GFXOFF
-//#define GQUEUE_NEED_FSYNC GFXOFF
-//#define GQUEUE_NEED_BUFFERS GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GINPUT //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GINPUT GFXOFF
-
-//#define GINPUT_NEED_MOUSE GFXOFF
-// #define GINPUT_TOUCH_STARTRAW GFXOFF
-// #define GINPUT_TOUCH_NOTOUCH GFXOFF
-// #define GINPUT_TOUCH_NOCALIBRATE GFXOFF
-// #define GINPUT_TOUCH_NOCALIBRATE_GUI GFXOFF
-// #define GINPUT_MOUSE_POLL_PERIOD 25
-// #define GINPUT_MOUSE_CLICK_TIME 300
-// #define GINPUT_TOUCH_CXTCLICK_TIME 700
-// #define GINPUT_TOUCH_USER_CALIBRATION_LOAD GFXOFF
-// #define GINPUT_TOUCH_USER_CALIBRATION_SAVE GFXOFF
-// #define GMOUSE_DRIVER_LIST GMOUSEVMT_Win32, GMOUSEVMT_Win32
-// #define GINPUT_TOUCH_CALIBRATION_FONT1 "* Double"
-// #define GINPUT_TOUCH_CALIBRATION_FONT2 "* Narrow"
-// #define GINPUT_TOUCH_CALIBRATION_TITLE "Calibration"
-// #define GINPUT_TOUCH_CALIBRATION_ERROR "Calibration Failed!"
-//#define GINPUT_NEED_KEYBOARD GFXOFF
-// #define GINPUT_KEYBOARD_POLL_PERIOD 200
-// #define GKEYBOARD_DRIVER_LIST GKEYBOARDVMT_Win32, GKEYBOARDVMT_Win32
-// #define GKEYBOARD_LAYOUT_OFF GFXOFF
-// #define GKEYBOARD_LAYOUT_SCANCODE2_US GFXOFF
-//#define GINPUT_NEED_TOGGLE GFXOFF
-//#define GINPUT_NEED_DIAL GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GFILE //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GFILE GFXOFF
-
-//#define GFILE_NEED_PRINTG GFXOFF
-//#define GFILE_NEED_SCANG GFXOFF
-//#define GFILE_NEED_STRINGS GFXOFF
-//#define GFILE_NEED_FILELISTS GFXOFF
-//#define GFILE_NEED_STDIO GFXOFF
-//#define GFILE_NEED_NOAUTOMOUNT GFXOFF
-//#define GFILE_NEED_NOAUTOSYNC GFXOFF
-
-//#define GFILE_NEED_MEMFS GFXOFF
-//#define GFILE_NEED_ROMFS GFXOFF
-//#define GFILE_NEED_RAMFS GFXOFF
-//#define GFILE_NEED_FATFS GFXOFF
-//#define GFILE_NEED_NATIVEFS GFXOFF
-//#define GFILE_NEED_CHBIOSFS GFXOFF
-//#define GFILE_NEED_USERFS GFXOFF
-
-//#define GFILE_ALLOW_FLOATS GFXOFF
-//#define GFILE_ALLOW_DEVICESPECIFIC GFXOFF
-//#define GFILE_MAX_GFILES 3
-
-///////////////////////////////////////////////////////////////////////////
-// GADC //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GADC GFXOFF
-// #define GADC_MAX_LOWSPEED_DEVICES 4
-
-///////////////////////////////////////////////////////////////////////////
-// GAUDIO //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GAUDIO GFXOFF
-// #define GAUDIO_NEED_PLAY GFXOFF
-// #define GAUDIO_NEED_RECORD GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GMISC //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GMISC GFXON
-
-//#define GMISC_NEED_ARRAYOPS GFXOFF
-//#define GMISC_NEED_FASTTRIG GFXOFF
-//#define GMISC_NEED_FIXEDTRIG GFXOFF
-//#define GMISC_NEED_INVSQRT GFXOFF
-// #define GMISC_INVSQRT_MIXED_ENDIAN GFXOFF
-// #define GMISC_INVSQRT_REAL_SLOW GFXOFF
-#define GMISC_NEED_MATRIXFLOAT2D GFXON
-#define GMISC_NEED_MATRIXFIXED2D GFXOFF
-//#define GMISC_NEED_HITTEST_POLY GFXOFF
diff --git a/quantum/visualizer/default_animations.c b/quantum/visualizer/default_animations.c
deleted file mode 100644
index 2f43c67cc8..0000000000
--- a/quantum/visualizer/default_animations.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#if defined(VISUALIZER_ENABLE)
-
-# include "default_animations.h"
-# include "visualizer.h"
-# ifdef LCD_ENABLE
-# include "lcd_keyframes.h"
-# endif
-# ifdef LCD_BACKLIGHT_ENABLE
-# include "lcd_backlight_keyframes.h"
-# endif
-
-# ifdef BACKLIGHT_ENABLE
-# include "led_backlight_keyframes.h"
-# endif
-
-# include "visualizer_keyframes.h"
-
-# if defined(LCD_ENABLE) || defined(LCD_BACKLIGHT_ENABLE) || defined(BACKLIGHT_ENABLE)
-
-static bool keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) {
-# ifdef LCD_ENABLE
- lcd_keyframe_enable(animation, state);
-# endif
-# ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_keyframe_enable(animation, state);
-# endif
-# ifdef BACKLIGHT_ENABLE
- led_backlight_keyframe_enable(animation, state);
-# endif
- return false;
-}
-
-static bool keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) {
-# ifdef LCD_ENABLE
- lcd_keyframe_disable(animation, state);
-# endif
-# ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_keyframe_disable(animation, state);
-# endif
-# ifdef BACKLIGHT_ENABLE
- led_backlight_keyframe_disable(animation, state);
-# endif
- return false;
-}
-
-static bool keyframe_fade_in(keyframe_animation_t* animation, visualizer_state_t* state) {
- bool ret = false;
-# ifdef LCD_BACKLIGHT_ENABLE
- ret |= lcd_backlight_keyframe_animate_color(animation, state);
-# endif
-# ifdef BACKLIGHT_ENABLE
- ret |= led_backlight_keyframe_fade_in_all(animation, state);
-# endif
- return ret;
-}
-
-static bool keyframe_fade_out(keyframe_animation_t* animation, visualizer_state_t* state) {
- bool ret = false;
-# ifdef LCD_BACKLIGHT_ENABLE
- ret |= lcd_backlight_keyframe_animate_color(animation, state);
-# endif
-# ifdef BACKLIGHT_ENABLE
- ret |= led_backlight_keyframe_fade_out_all(animation, state);
-# endif
- return ret;
-}
-
-// Don't worry, if the startup animation is long, you can use the keyboard like normal
-// during that time
-keyframe_animation_t default_startup_animation = {
-# if LCD_ENABLE
- .num_frames = 3,
-# else
- .num_frames = 2,
-# endif
- .loop = false,
- .frame_lengths = {0,
-# if LCD_ENABLE
- 0,
-# endif
- gfxMillisecondsToTicks(5000)},
- .frame_functions =
- {
- keyframe_enable,
-# if LCD_ENABLE
- lcd_keyframe_draw_logo,
-# endif
- keyframe_fade_in,
- },
-};
-
-keyframe_animation_t default_suspend_animation = {
-# if LCD_ENABLE
- .num_frames = 3,
-# else
- .num_frames = 2,
-# endif
- .loop = false,
- .frame_lengths =
- {
-# if LCD_ENABLE
- 0,
-# endif
- gfxMillisecondsToTicks(1000), 0},
- .frame_functions =
- {
-# if LCD_ENABLE
- lcd_keyframe_display_layer_text,
-# endif
- keyframe_fade_out,
- keyframe_disable,
- },
-};
-# endif
-
-# if defined(BACKLIGHT_ENABLE)
-# define CROSSFADE_TIME 1000
-# define GRADIENT_TIME 3000
-
-keyframe_animation_t led_test_animation = {
- .num_frames = 14,
- .loop = true,
- .frame_lengths =
- {
- gfxMillisecondsToTicks(1000), // fade in
- gfxMillisecondsToTicks(1000), // no op (leds on)
- gfxMillisecondsToTicks(1000), // fade out
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
- gfxMillisecondsToTicks(GRADIENT_TIME), // left to rigt (outside in)
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
- gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom
- 0, // mirror leds
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
- gfxMillisecondsToTicks(GRADIENT_TIME), // left_to_right (mirrored, so inside out)
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
- gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom
- 0, // normal leds
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
-
- },
- .frame_functions =
- {
- led_backlight_keyframe_fade_in_all,
- keyframe_no_operation,
- led_backlight_keyframe_fade_out_all,
- led_backlight_keyframe_crossfade,
- led_backlight_keyframe_left_to_right_gradient,
- led_backlight_keyframe_crossfade,
- led_backlight_keyframe_top_to_bottom_gradient,
- led_backlight_keyframe_mirror_orientation,
- led_backlight_keyframe_crossfade,
- led_backlight_keyframe_left_to_right_gradient,
- led_backlight_keyframe_crossfade,
- led_backlight_keyframe_top_to_bottom_gradient,
- led_backlight_keyframe_normal_orientation,
- led_backlight_keyframe_crossfade,
- },
-};
-# endif
-
-#endif
diff --git a/quantum/visualizer/lcd_backlight.c b/quantum/visualizer/lcd_backlight.c
deleted file mode 100644
index 23978974e3..0000000000
--- a/quantum/visualizer/lcd_backlight.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "lcd_backlight.h"
-#include <math.h>
-
-static uint8_t current_hue = 0;
-static uint8_t current_saturation = 0;
-static uint8_t current_intensity = 0;
-static uint8_t current_brightness = 0;
-
-void lcd_backlight_init(void) {
- lcd_backlight_hal_init();
- lcd_backlight_color(current_hue, current_saturation, current_intensity);
-}
-
-// This code is based on Brian Neltner's blogpost and example code
-// "Why every LED light should be using HSI colorspace".
-// http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi
-static void hsi_to_rgb(float h, float s, float i, uint16_t* r_out, uint16_t* g_out, uint16_t* b_out) {
- unsigned int r, g, b;
- h = fmodf(h, 360.0f); // cycle h around to 0-360 degrees
- h = 3.14159f * h / 180.0f; // Convert to radians.
- s = s > 0.0f ? (s < 1.0f ? s : 1.0f) : 0.0f; // clamp s and i to interval [0,1]
- i = i > 0.0f ? (i < 1.0f ? i : 1.0f) : 0.0f;
-
- // Math! Thanks in part to Kyle Miller.
- if (h < 2.09439f) {
- r = 65535.0f * i / 3.0f * (1.0f + s * cos(h) / cosf(1.047196667f - h));
- g = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cos(1.047196667f - h)));
- b = 65535.0f * i / 3.0f * (1.0f - s);
- } else if (h < 4.188787) {
- h = h - 2.09439;
- g = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h));
- b = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h)));
- r = 65535.0f * i / 3.0f * (1.0f - s);
- } else {
- h = h - 4.188787;
- b = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h));
- r = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h)));
- g = 65535.0f * i / 3.0f * (1.0f - s);
- }
- *r_out = r > 65535 ? 65535 : r;
- *g_out = g > 65535 ? 65535 : g;
- *b_out = b > 65535 ? 65535 : b;
-}
-
-void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity) {
- uint16_t r, g, b;
- float hue_f = 360.0f * (float)hue / 255.0f;
- float saturation_f = (float)saturation / 255.0f;
- float intensity_f = (float)intensity / 255.0f;
- intensity_f *= (float)current_brightness / 255.0f;
- hsi_to_rgb(hue_f, saturation_f, intensity_f, &r, &g, &b);
- current_hue = hue;
- current_saturation = saturation;
- current_intensity = intensity;
- lcd_backlight_hal_color(r, g, b);
-}
-
-void lcd_backlight_brightness(uint8_t b) {
- current_brightness = b;
- lcd_backlight_color(current_hue, current_saturation, current_intensity);
-}
-
-uint8_t lcd_get_backlight_brightness(void) { return current_brightness; }
diff --git a/quantum/visualizer/lcd_backlight.h b/quantum/visualizer/lcd_backlight.h
deleted file mode 100644
index 4ea5b14639..0000000000
--- a/quantum/visualizer/lcd_backlight.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-
-// Helper macros for storing hue, staturation and intensity as unsigned integers
-#define LCD_COLOR(hue, saturation, intensity) (hue << 16 | saturation << 8 | intensity)
-#define LCD_HUE(color) ((color >> 16) & 0xFF)
-#define LCD_SAT(color) ((color >> 8) & 0xFF)
-#define LCD_INT(color) (color & 0xFF)
-
-static inline uint32_t change_lcd_color_intensity(uint32_t color, uint8_t new_intensity) { return (color & 0xFFFFFF00) | new_intensity; }
-
-void lcd_backlight_init(void);
-void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity);
-void lcd_backlight_brightness(uint8_t b);
-uint8_t lcd_get_backlight_brightness(void);
-
-void lcd_backlight_hal_init(void);
-void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b);
diff --git a/quantum/visualizer/lcd_backlight_keyframes.c b/quantum/visualizer/lcd_backlight_keyframes.c
deleted file mode 100644
index c13cce311d..0000000000
--- a/quantum/visualizer/lcd_backlight_keyframes.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "lcd_backlight_keyframes.h"
-
-bool lcd_backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state) {
- int frame_length = animation->frame_lengths[animation->current_frame];
- int current_pos = frame_length - animation->time_left_in_frame;
- uint8_t t_h = LCD_HUE(state->target_lcd_color);
- uint8_t t_s = LCD_SAT(state->target_lcd_color);
- uint8_t t_i = LCD_INT(state->target_lcd_color);
- uint8_t p_h = LCD_HUE(state->prev_lcd_color);
- uint8_t p_s = LCD_SAT(state->prev_lcd_color);
- uint8_t p_i = LCD_INT(state->prev_lcd_color);
-
- uint8_t d_h1 = t_h - p_h; // Modulo arithmetic since we want to wrap around
- int d_h2 = t_h - p_h;
- // Chose the shortest way around
- int d_h = abs(d_h2) < d_h1 ? d_h2 : d_h1;
- int d_s = t_s - p_s;
- int d_i = t_i - p_i;
-
- int hue = (d_h * current_pos) / frame_length;
- int sat = (d_s * current_pos) / frame_length;
- int intensity = (d_i * current_pos) / frame_length;
- // dprintf("%X -> %X = %X\n", p_h, t_h, hue);
- hue += p_h;
- sat += p_s;
- intensity += p_i;
- state->current_lcd_color = LCD_COLOR(hue, sat, intensity);
- lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color));
-
- return true;
-}
-
-bool lcd_backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- state->prev_lcd_color = state->target_lcd_color;
- state->current_lcd_color = state->target_lcd_color;
- lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color));
- return false;
-}
-
-bool lcd_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- lcd_backlight_hal_color(0, 0, 0);
- return false;
-}
-
-bool lcd_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color));
- return false;
-}
diff --git a/quantum/visualizer/lcd_backlight_keyframes.h b/quantum/visualizer/lcd_backlight_keyframes.h
deleted file mode 100644
index 88768dd4a5..0000000000
--- a/quantum/visualizer/lcd_backlight_keyframes.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "visualizer.h"
-
-// Animates the LCD backlight color between the current color and the target color (of the state)
-bool lcd_backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state);
-// Sets the backlight color to the target color
-bool lcd_backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state);
-
-bool lcd_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state);
-bool lcd_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state);
diff --git a/quantum/visualizer/lcd_keyframes.c b/quantum/visualizer/lcd_keyframes.c
deleted file mode 100644
index 1d6f3dca18..0000000000
--- a/quantum/visualizer/lcd_keyframes.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "lcd_keyframes.h"
-#include <string.h>
-#include "action_util.h"
-#include "led.h"
-#include "resources/resources.h"
-
-bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- gdispClear(White);
- gdispDrawString(0, 10, state->layer_text, state->font_dejavusansbold12, Black);
- return false;
-}
-
-static void format_layer_bitmap_string(uint16_t default_layer, uint16_t layer, char* buffer) {
- for (int i = 0; i < 16; i++) {
- uint32_t mask = (1u << i);
- if (default_layer & mask) {
- if (layer & mask) {
- *buffer = 'B';
- } else {
- *buffer = 'D';
- }
- } else if (layer & mask) {
- *buffer = '1';
- } else {
- *buffer = '0';
- }
- ++buffer;
-
- if (i == 3 || i == 7 || i == 11) {
- *buffer = ' ';
- ++buffer;
- }
- }
- *buffer = 0;
-}
-
-bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- const char* layer_help = "1=On D=Default B=Both";
- char layer_buffer[16 + 4]; // 3 spaces and one null terminator
- gdispClear(White);
- gdispDrawString(0, 0, layer_help, state->font_fixed5x8, Black);
- format_layer_bitmap_string(state->status.default_layer, state->status.layer, layer_buffer);
- gdispDrawString(0, 10, layer_buffer, state->font_fixed5x8, Black);
- format_layer_bitmap_string(state->status.default_layer >> 16, state->status.layer >> 16, layer_buffer);
- gdispDrawString(0, 20, layer_buffer, state->font_fixed5x8, Black);
- return false;
-}
-
-static void format_mods_bitmap_string(uint8_t mods, char* buffer) {
- *buffer = ' ';
- ++buffer;
-
- for (int i = 0; i < 8; i++) {
- uint32_t mask = (1u << i);
- if (mods & mask) {
- *buffer = '1';
- } else {
- *buffer = '0';
- }
- ++buffer;
-
- if (i == 3) {
- *buffer = ' ';
- ++buffer;
- }
- }
- *buffer = 0;
-}
-
-bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
-
- const char* title = "Modifier states";
- const char* mods_header = " CSAG CSAG ";
- char status_buffer[12];
-
- gdispClear(White);
- gdispDrawString(0, 0, title, state->font_fixed5x8, Black);
- gdispDrawString(0, 10, mods_header, state->font_fixed5x8, Black);
- format_mods_bitmap_string(state->status.mods, status_buffer);
- gdispDrawString(0, 20, status_buffer, state->font_fixed5x8, Black);
-
- return false;
-}
-
-#define LED_STATE_STRING_SIZE sizeof("NUM CAPS SCRL COMP KANA")
-
-static void get_led_state_string(char* output, visualizer_state_t* state) {
- uint8_t pos = 0;
-
- if (state->status.leds & (1u << USB_LED_NUM_LOCK)) {
- memcpy(output + pos, "NUM ", 4);
- pos += 4;
- }
- if (state->status.leds & (1u << USB_LED_CAPS_LOCK)) {
- memcpy(output + pos, "CAPS ", 5);
- pos += 5;
- }
- if (state->status.leds & (1u << USB_LED_SCROLL_LOCK)) {
- memcpy(output + pos, "SCRL ", 5);
- pos += 5;
- }
- if (state->status.leds & (1u << USB_LED_COMPOSE)) {
- memcpy(output + pos, "COMP ", 5);
- pos += 5;
- }
- if (state->status.leds & (1u << USB_LED_KANA)) {
- memcpy(output + pos, "KANA", 4);
- pos += 4;
- }
- output[pos] = 0;
-}
-
-bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- char output[LED_STATE_STRING_SIZE];
- get_led_state_string(output, state);
- gdispClear(White);
- gdispDrawString(0, 10, output, state->font_dejavusansbold12, Black);
- return false;
-}
-
-bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- gdispClear(White);
- uint8_t y = 10;
- if (state->status.leds) {
- char output[LED_STATE_STRING_SIZE];
- get_led_state_string(output, state);
- gdispDrawString(0, 1, output, state->font_dejavusansbold12, Black);
- y = 17;
- }
- gdispDrawString(0, y, state->layer_text, state->font_dejavusansbold12, Black);
- return false;
-}
-
-bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- // Read the uGFX documentation for information how to use the displays
- // http://wiki.ugfx.org/index.php/Main_Page
- gdispClear(Black);
-
- // You can use static variables for things that can't be found in the animation
- // or state structs, here we use the image
-
- // gdispGBlitArea is a tricky function to use since it supports blitting part of the image
- // if you have full screen image, then just use LCD_WIDTH and LCD_HEIGHT for both source and target dimensions
- gdispGBlitArea(GDISP, 0, 0, 128, 32, 0, 0, LCD_WIDTH, (pixel_t*)resource_lcd_logo);
-
- return false;
-}
-
-bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- gdispSetPowerMode(powerOff);
- return false;
-}
-
-bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- gdispSetPowerMode(powerOn);
- return false;
-}
diff --git a/quantum/visualizer/lcd_keyframes.h b/quantum/visualizer/lcd_keyframes.h
deleted file mode 100644
index b7125e8323..0000000000
--- a/quantum/visualizer/lcd_keyframes.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "visualizer.h"
-
-// Displays the layer text centered vertically on the screen
-bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays a bitmap (0/1) of all the currently active layers
-bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays a bitmap (0/1) of all the currently active mods
-bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays the keyboard led states (CAPS (Caps lock), NUM (Num lock), SCRL (Scroll lock), COMP (Compose), KANA)
-bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays both the layer text and the led states
-bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays the QMK logo on the LCD screen
-bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state);
-
-bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state);
-bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state);
diff --git a/quantum/visualizer/led_backlight_keyframes.c b/quantum/visualizer/led_backlight_keyframes.c
deleted file mode 100644
index 338ada5227..0000000000
--- a/quantum/visualizer/led_backlight_keyframes.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-#include "gfx.h"
-#include <math.h>
-#include "led_backlight_keyframes.h"
-
-static uint8_t fade_led_color(keyframe_animation_t* animation, int from, int to) {
- int frame_length = animation->frame_lengths[animation->current_frame];
- int current_pos = frame_length - animation->time_left_in_frame;
- int delta = to - from;
- int luma = (delta * current_pos) / frame_length;
- luma += from;
- return luma;
-}
-
-static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint8_t from, uint8_t to) {
- uint8_t luma = fade_led_color(animation, from, to);
- color_t color = LUMA2COLOR(luma);
- gdispGClear(LED_DISPLAY, color);
-}
-
-// TODO: Should be customizable per keyboard
-#define NUM_ROWS LED_HEIGHT
-#define NUM_COLS LED_WIDTH
-
-static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS];
-static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS];
-
-static uint8_t compute_gradient_color(float t, float index, float num) {
- const float two_pi = M_PI * 2.0f;
- float normalized_index = (1.0f - index / (num - 1.0f)) * two_pi;
- float x = t * two_pi + normalized_index;
- float v = 0.5 * (cosf(x) + 1.0f);
- return (uint8_t)(255.0f * v);
-}
-
-bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- keyframe_fade_all_leds_from_to(animation, 0, 255);
- return true;
-}
-
-bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- keyframe_fade_all_leds_from_to(animation, 255, 0);
- return true;
-}
-
-bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- float frame_length = animation->frame_lengths[animation->current_frame];
- float current_pos = frame_length - animation->time_left_in_frame;
- float t = current_pos / frame_length;
- for (int i = 0; i < NUM_COLS; i++) {
- uint8_t color = compute_gradient_color(t, i, NUM_COLS);
- gdispGDrawLine(LED_DISPLAY, i, 0, i, NUM_ROWS - 1, LUMA2COLOR(color));
- }
- return true;
-}
-
-bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- float frame_length = animation->frame_lengths[animation->current_frame];
- float current_pos = frame_length - animation->time_left_in_frame;
- float t = current_pos / frame_length;
- for (int i = 0; i < NUM_ROWS; i++) {
- uint8_t color = compute_gradient_color(t, i, NUM_ROWS);
- gdispGDrawLine(LED_DISPLAY, 0, i, NUM_COLS - 1, i, LUMA2COLOR(color));
- }
- return true;
-}
-
-static void copy_current_led_state(uint8_t* dest) {
- for (int i = 0; i < NUM_ROWS; i++) {
- for (int j = 0; j < NUM_COLS; j++) {
- dest[i * NUM_COLS + j] = gdispGGetPixelColor(LED_DISPLAY, j, i);
- }
- }
-}
-bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- if (animation->first_update_of_frame) {
- copy_current_led_state(&crossfade_start_frame[0][0]);
- run_next_keyframe(animation, state);
- copy_current_led_state(&crossfade_end_frame[0][0]);
- }
- for (int i = 0; i < NUM_ROWS; i++) {
- for (int j = 0; j < NUM_COLS; j++) {
- color_t color = LUMA2COLOR(fade_led_color(animation, crossfade_start_frame[i][j], crossfade_end_frame[i][j]));
- gdispGDrawPixel(LED_DISPLAY, j, i, color);
- }
- }
- return true;
-}
-
-bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_180);
- return false;
-}
-
-bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0);
- return false;
-}
-
-bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- gdispGSetPowerMode(LED_DISPLAY, powerOff);
- return false;
-}
-
-bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- gdispGSetPowerMode(LED_DISPLAY, powerOn);
- return false;
-}
diff --git a/quantum/visualizer/led_backlight_keyframes.h b/quantum/visualizer/led_backlight_keyframes.h
deleted file mode 100644
index 90153be5eb..0000000000
--- a/quantum/visualizer/led_backlight_keyframes.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include "visualizer.h"
-
-bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state);
-
-bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state);
-
-extern keyframe_animation_t led_test_animation;
diff --git a/quantum/visualizer/readme.md b/quantum/visualizer/readme.md
deleted file mode 100644
index 298efb742f..0000000000
--- a/quantum/visualizer/readme.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# A visualization library for the TMK keyboard firmware
-
-This library is designed to work together with the [TMK keyboard firmware](https://github.com/tmk/tmk_keyboard). Currently it only works for [Chibios](http://www.chibios.org/)
- flavors, but it would be possible to add support for other configurations as well. The LCD display functionality is provided by the [uGFX library](https://ugfx.io/).
-
-## To use this library as a user
-You can and should modify the visualizer\_user.c file. Check the comments in the file for more information.
-
-## To add this library to custom keyboard projects
-
-1. Add tmk_visualizer as a submodule to your project
-1. Set VISUALIZER_DIR in the main keyboard project makefile to point to the submodule
-1. Define LCD\_ENABLE and/or LCD\_BACKLIGHT\_ENABLE, to enable support
-1. Include the visualizer.mk make file
-1. Copy the files in the example\_integration folder to your keyboard project
-1. All other files than the callback.c file are included automatically, so you will need to add callback.c to your makefile manually. If you already have a similar file in your project, you can just copy the functions instead of the whole file.
-1. Edit the files to match your hardware. You might might want to read the Chibios and UGfx documentation, for more information.
-1. If you enable LCD support you might also have to write a custom uGFX display driver, check the uGFX documentation for that. You probably also want to enable SPI support in your Chibios configuration.
diff --git a/quantum/visualizer/resources/lcd_logo.c b/quantum/visualizer/resources/lcd_logo.c
deleted file mode 100644
index 13bf734cb3..0000000000
--- a/quantum/visualizer/resources/lcd_logo.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "resources.h"
-
-// clang-format off
-
-// To generate an image array like this
-// Ensure the image is 128 x 32 or smaller
-// Convert the bitmap to a C array using a program like http://www.riuson.com/lcd-image-converter/
-// Ensure the the conversion process produces a monochrome format array - 1 bit/pixel, left to right, top to bottom
-// Update array in the source code with the C array produced by the conversion program
-
-// The image below is generated from lcd_logo.png
-__attribute__((weak)) const uint8_t resource_lcd_logo[512] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xFE, 0xEE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xEE, 0xF0, 0x01, 0xC6, 0x0D, 0x8C, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xFE, 0xEE, 0xFE, 0x03, 0xE7, 0x1D, 0x9C, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x37, 0x1D, 0xB8, 0x18, 0x0B, 0x59, 0xC8, 0x09, 0xE5, 0x9E, 0x00,
- 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x37, 0xBD, 0xF0, 0x18, 0x6F, 0x7F, 0xEC, 0x9B, 0x37, 0xB3, 0x00, 0x00, 0xFE, 0xEE, 0xFE, 0x06, 0x37, 0xBD, 0xE0, 0x1F, 0x6C, 0x66, 0x6D, 0xD8, 0x36, 0x33, 0x00,
- 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x36, 0xED, 0xF0, 0x1F, 0x6C, 0x66, 0x6D, 0x59, 0xF6, 0x3E, 0x00, 0x00, 0x1F, 0x6D, 0xF0, 0x06, 0x36, 0xED, 0xB8, 0x18, 0x6C, 0x66, 0x67, 0x73, 0x36, 0x30, 0x00,
- 0x00, 0xFF, 0x83, 0xFE, 0x03, 0xE6, 0x4D, 0x9C, 0x18, 0x6C, 0x66, 0x67, 0x73, 0x36, 0x1F, 0x00, 0x00, 0x1F, 0xEF, 0xF0, 0x01, 0xC6, 0x0D, 0x8C, 0x18, 0x6C, 0x66, 0x62, 0x21, 0xD6, 0x0E, 0x00,
- 0x00, 0xFF, 0xEF, 0xFE, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
diff --git a/quantum/visualizer/resources/lcd_logo.png b/quantum/visualizer/resources/lcd_logo.png
deleted file mode 100644
index 178ef65f15..0000000000
--- a/quantum/visualizer/resources/lcd_logo.png
+++ /dev/null
Binary files differ
diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c
deleted file mode 100644
index 709affbb77..0000000000
--- a/quantum/visualizer/visualizer.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "config.h"
-#include "visualizer.h"
-#include <string.h>
-#ifdef PROTOCOL_CHIBIOS
-# include <ch.h>
-#endif
-
-#include "gfx.h"
-
-#ifdef LCD_BACKLIGHT_ENABLE
-# include "lcd_backlight.h"
-#endif
-
-//#define DEBUG_VISUALIZER
-
-#ifdef DEBUG_VISUALIZER
-# include "debug.h"
-#else
-# include "nodebug.h"
-#endif
-
-#ifdef SERIAL_LINK_ENABLE
-# include "serial_link/protocol/transport.h"
-# include "serial_link/system/serial_link.h"
-#endif
-
-#include "action_util.h"
-
-// Define this in config.h
-#ifndef VISUALIZER_THREAD_PRIORITY
-// The visualizer needs gfx thread priorities
-# define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2)
-#endif
-
-static visualizer_keyboard_status_t current_status = {.layer = 0xFFFFFFFF,
- .default_layer = 0xFFFFFFFF,
- .leds = 0xFFFFFFFF,
-#ifdef BACKLIGHT_ENABLE
- .backlight_level = 0,
-#endif
- .mods = 0xFF,
- .suspended = false,
-#ifdef VISUALIZER_USER_DATA_SIZE
- .user_data = {0}
-#endif
-};
-
-static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) {
- return status1->layer == status2->layer && status1->default_layer == status2->default_layer && status1->mods == status2->mods && status1->leds == status2->leds && status1->suspended == status2->suspended
-#ifdef BACKLIGHT_ENABLE
- && status1->backlight_level == status2->backlight_level
-#endif
-#ifdef VISUALIZER_USER_DATA_SIZE
- && memcmp(status1->user_data, status2->user_data, VISUALIZER_USER_DATA_SIZE) == 0
-#endif
- ;
-}
-
-static bool visualizer_enabled = false;
-
-#ifdef VISUALIZER_USER_DATA_SIZE
-static uint8_t user_data[VISUALIZER_USER_DATA_SIZE];
-#endif
-
-#define MAX_SIMULTANEOUS_ANIMATIONS 4
-static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {};
-
-#ifdef SERIAL_LINK_ENABLE
-MASTER_TO_ALL_SLAVES_OBJECT(current_status, visualizer_keyboard_status_t);
-
-static remote_object_t* remote_objects[] = {
- REMOTE_OBJECT(current_status),
-};
-
-#endif
-
-GDisplay* LCD_DISPLAY = 0;
-GDisplay* LED_DISPLAY = 0;
-
-#ifdef LCD_DISPLAY_NUMBER
-__attribute__((weak)) GDisplay* get_lcd_display(void) { return gdispGetDisplay(LCD_DISPLAY_NUMBER); }
-#endif
-
-#ifdef LED_DISPLAY_NUMBER
-__attribute__((weak)) GDisplay* get_led_display(void) { return gdispGetDisplay(LED_DISPLAY_NUMBER); }
-#endif
-
-void start_keyframe_animation(keyframe_animation_t* animation) {
- animation->current_frame = -1;
- animation->time_left_in_frame = 0;
- animation->need_update = true;
- int free_index = -1;
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- if (animations[i] == animation) {
- return;
- }
- if (free_index == -1 && animations[i] == NULL) {
- free_index = i;
- }
- }
- if (free_index != -1) {
- animations[free_index] = animation;
- }
-}
-
-void stop_keyframe_animation(keyframe_animation_t* animation) {
- animation->current_frame = animation->num_frames;
- animation->time_left_in_frame = 0;
- animation->need_update = true;
- animation->first_update_of_frame = false;
- animation->last_update_of_frame = false;
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- if (animations[i] == animation) {
- animations[i] = NULL;
- return;
- }
- }
-}
-
-void stop_all_keyframe_animations(void) {
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- if (animations[i]) {
- animations[i]->current_frame = animations[i]->num_frames;
- animations[i]->time_left_in_frame = 0;
- animations[i]->need_update = true;
- animations[i]->first_update_of_frame = false;
- animations[i]->last_update_of_frame = false;
- animations[i] = NULL;
- }
- }
-}
-
-static uint8_t get_num_running_animations(void) {
- uint8_t count = 0;
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- count += animations[i] ? 1 : 0;
- }
- return count;
-}
-
-static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systemticks_t delta, systemticks_t* sleep_time) {
- // TODO: Clean up this messy code
- dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, animation->time_left_in_frame, delta);
- if (animation->current_frame == animation->num_frames) {
- animation->need_update = false;
- return false;
- }
- if (animation->current_frame == -1) {
- animation->current_frame = 0;
- animation->time_left_in_frame = animation->frame_lengths[0];
- animation->need_update = true;
- animation->first_update_of_frame = true;
- } else {
- animation->time_left_in_frame -= delta;
- while (animation->time_left_in_frame <= 0) {
- int left = animation->time_left_in_frame;
- if (animation->need_update) {
- animation->time_left_in_frame = 0;
- animation->last_update_of_frame = true;
- (*animation->frame_functions[animation->current_frame])(animation, state);
- animation->last_update_of_frame = false;
- }
- animation->current_frame++;
- animation->need_update = true;
- animation->first_update_of_frame = true;
- if (animation->current_frame == animation->num_frames) {
- if (animation->loop) {
- animation->current_frame = 0;
- } else {
- stop_keyframe_animation(animation);
- return false;
- }
- }
- delta = -left;
- animation->time_left_in_frame = animation->frame_lengths[animation->current_frame];
- animation->time_left_in_frame -= delta;
- }
- }
- if (animation->need_update) {
- animation->need_update = (*animation->frame_functions[animation->current_frame])(animation, state);
- animation->first_update_of_frame = false;
- }
-
- systemticks_t wanted_sleep = animation->need_update ? gfxMillisecondsToTicks(10) : (unsigned)animation->time_left_in_frame;
- if (wanted_sleep < *sleep_time) {
- *sleep_time = wanted_sleep;
- }
-
- return true;
-}
-
-void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state) {
- int next_frame = animation->current_frame + 1;
- if (next_frame == animation->num_frames) {
- next_frame = 0;
- }
- keyframe_animation_t temp_animation = *animation;
- temp_animation.current_frame = next_frame;
- temp_animation.time_left_in_frame = animation->frame_lengths[next_frame];
- temp_animation.first_update_of_frame = true;
- temp_animation.last_update_of_frame = false;
- temp_animation.need_update = false;
- visualizer_state_t temp_state = *state;
- (*temp_animation.frame_functions[next_frame])(&temp_animation, &temp_state);
-}
-
-// TODO: Optimize the stack size, this is probably way too big
-static DECLARE_THREAD_STACK(visualizerThreadStack, 1024);
-static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
- (void)arg;
-
- GListener event_listener;
- geventListenerInit(&event_listener);
- geventAttachSource(&event_listener, (GSourceHandle)&current_status, 0);
-
- visualizer_keyboard_status_t initial_status = {
- .default_layer = 0xFFFFFFFF,
- .layer = 0xFFFFFFFF,
- .mods = 0xFF,
- .leds = 0xFFFFFFFF,
- .suspended = false,
-#ifdef BACKLIGHT_ENABLE
- .backlight_level = 0,
-#endif
-#ifdef VISUALIZER_USER_DATA_SIZE
- .user_data = {0},
-#endif
- };
-
- visualizer_state_t state = {.status = initial_status,
- .current_lcd_color = 0,
-#ifdef LCD_ENABLE
- .font_fixed5x8 = gdispOpenFont("fixed_5x8"),
- .font_dejavusansbold12 = gdispOpenFont("DejaVuSansBold12")
-#endif
- };
- initialize_user_visualizer(&state);
- state.prev_lcd_color = state.current_lcd_color;
-
-#ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_color(LCD_HUE(state.current_lcd_color), LCD_SAT(state.current_lcd_color), LCD_INT(state.current_lcd_color));
-#endif
-
- systemticks_t sleep_time = TIME_INFINITE;
- systemticks_t current_time = gfxSystemTicks();
- bool force_update = true;
-
- while (true) {
- systemticks_t new_time = gfxSystemTicks();
- systemticks_t delta = new_time - current_time;
- current_time = new_time;
- bool enabled = visualizer_enabled;
- if (force_update || !same_status(&state.status, &current_status)) {
- force_update = false;
-#if BACKLIGHT_ENABLE
- if (current_status.backlight_level != state.status.backlight_level) {
- if (current_status.backlight_level != 0) {
- gdispGSetPowerMode(LED_DISPLAY, powerOn);
- uint16_t percent = (uint16_t)current_status.backlight_level * 100 / BACKLIGHT_LEVELS;
- gdispGSetBacklight(LED_DISPLAY, percent);
- } else {
- gdispGSetPowerMode(LED_DISPLAY, powerOff);
- }
- state.status.backlight_level = current_status.backlight_level;
- }
-#endif
- if (visualizer_enabled) {
- if (current_status.suspended) {
- stop_all_keyframe_animations();
- visualizer_enabled = false;
- state.status = current_status;
- user_visualizer_suspend(&state);
- } else {
- visualizer_keyboard_status_t prev_status = state.status;
- state.status = current_status;
- update_user_visualizer_state(&state, &prev_status);
- }
- state.prev_lcd_color = state.current_lcd_color;
- }
- }
- if (!enabled && state.status.suspended && current_status.suspended == false) {
- // Setting the status to the initial status will force an update
- // when the visualizer is enabled again
- state.status = initial_status;
- state.status.suspended = false;
- stop_all_keyframe_animations();
- user_visualizer_resume(&state);
- state.prev_lcd_color = state.current_lcd_color;
- }
- sleep_time = TIME_INFINITE;
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- if (animations[i]) {
- update_keyframe_animation(animations[i], &state, delta, &sleep_time);
- }
- }
-#ifdef BACKLIGHT_ENABLE
- gdispGFlush(LED_DISPLAY);
-#endif
-
-#ifdef LCD_ENABLE
- gdispGFlush(LCD_DISPLAY);
-#endif
-
-#ifdef EMULATOR
- draw_emulator();
-#endif
- // Enable the visualizer when the startup or the suspend animation has finished
- if (!visualizer_enabled && state.status.suspended == false && get_num_running_animations() == 0) {
- visualizer_enabled = true;
- force_update = true;
- sleep_time = 0;
- }
-
- systemticks_t after_update = gfxSystemTicks();
- unsigned update_delta = after_update - current_time;
- if (sleep_time != TIME_INFINITE) {
- if (sleep_time > update_delta) {
- sleep_time -= update_delta;
- } else {
- sleep_time = 0;
- }
- }
- dprintf("Update took %d, last delta %d, sleep_time %d\n", update_delta, delta, sleep_time);
-#ifdef PROTOCOL_CHIBIOS
- // The gEventWait function really takes milliseconds, even if the documentation says ticks.
- // Unfortunately there's no generic ugfx conversion from system time to milliseconds,
- // so let's do it in a platform dependent way.
-
- // On windows the system ticks is the same as milliseconds anyway
- if (sleep_time != TIME_INFINITE) {
- sleep_time = TIME_I2MS(sleep_time);
- }
-#endif
- geventEventWait(&event_listener, sleep_time);
- }
-#ifdef LCD_ENABLE
- gdispCloseFont(state.font_fixed5x8);
- gdispCloseFont(state.font_dejavusansbold12);
-#endif
-
- return 0;
-}
-
-void visualizer_init(void) {
- gfxInit();
-
-#ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_init();
-#endif
-
-#ifdef SERIAL_LINK_ENABLE
- add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*));
-#endif
-
-#ifdef LCD_ENABLE
- LCD_DISPLAY = get_lcd_display();
-#endif
-
-#ifdef BACKLIGHT_ENABLE
- LED_DISPLAY = get_led_display();
-#endif
-
- // We are using a low priority thread, the idea is to have it run only
- // when the main thread is sleeping during the matrix scanning
- gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack), VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL);
-}
-
-void update_status(bool changed) {
- if (changed) {
- GSourceListener* listener = geventGetSourceListener((GSourceHandle)&current_status, NULL);
- if (listener) {
- geventSendEvent(listener);
- }
- }
-#ifdef SERIAL_LINK_ENABLE
- static systime_t last_update = 0;
- systime_t current_update = chVTGetSystemTimeX();
- systime_t delta = current_update - last_update;
- if (changed || delta > TIME_MS2I(10)) {
- last_update = current_update;
- visualizer_keyboard_status_t* r = begin_write_current_status();
- *r = current_status;
- end_write_current_status();
- }
-#endif
-}
-
-uint8_t visualizer_get_mods() {
- uint8_t mods = get_mods();
-
-#ifndef NO_ACTION_ONESHOT
- if (!has_oneshot_mods_timed_out()) {
- mods |= get_oneshot_mods();
- }
-#endif
- return mods;
-}
-
-#ifdef VISUALIZER_USER_DATA_SIZE
-void visualizer_set_user_data(void* u) { memcpy(user_data, u, VISUALIZER_USER_DATA_SIZE); }
-#endif
-
-void visualizer_update(layer_state_t default_state, layer_state_t state, uint8_t mods, uint32_t leds) {
- // Note that there's a small race condition here, the thread could read
- // a state where one of these are set but not the other. But this should
- // not really matter as it will be fixed during the next loop step.
- // Alternatively a mutex could be used instead of the volatile variables
-
- bool changed = false;
-#ifdef SERIAL_LINK_ENABLE
- if (is_serial_link_connected()) {
- visualizer_keyboard_status_t* new_status = read_current_status();
- if (new_status) {
- if (!same_status(&current_status, new_status)) {
- changed = true;
- current_status = *new_status;
- }
- }
- } else {
-#else
- {
-#endif
- visualizer_keyboard_status_t new_status = {
- .layer = state,
- .default_layer = default_state,
- .mods = mods,
- .leds = leds,
-#ifdef BACKLIGHT_ENABLE
- .backlight_level = current_status.backlight_level,
-#endif
- .suspended = current_status.suspended,
- };
-#ifdef VISUALIZER_USER_DATA_SIZE
- memcpy(new_status.user_data, user_data, VISUALIZER_USER_DATA_SIZE);
-#endif
- if (!same_status(&current_status, &new_status)) {
- changed = true;
- current_status = new_status;
- }
- }
- update_status(changed);
-}
-
-void visualizer_suspend(void) {
- current_status.suspended = true;
- update_status(true);
-}
-
-void visualizer_resume(void) {
- current_status.suspended = false;
- update_status(true);
-}
-
-#ifdef BACKLIGHT_ENABLE
-void backlight_set(uint8_t level) {
- current_status.backlight_level = level;
- update_status(true);
-}
-#endif
diff --git a/quantum/visualizer/visualizer.h b/quantum/visualizer/visualizer.h
deleted file mode 100644
index 627c80a305..0000000000
--- a/quantum/visualizer/visualizer.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#include "config.h"
-#include "gfx.h"
-#include "action_layer.h"
-
-#ifdef LCD_BACKLIGHT_ENABLE
-# include "lcd_backlight.h"
-#endif
-
-#ifdef BACKLIGHT_ENABLE
-# include "backlight.h"
-#endif
-
-// use this function to merge both real_mods and oneshot_mods in a uint16_t
-uint8_t visualizer_get_mods(void);
-
-// This need to be called once at the start
-void visualizer_init(void);
-// This should be called at every matrix scan
-void visualizer_update(layer_state_t default_state, layer_state_t state, uint8_t mods, uint32_t leds);
-
-// This should be called when the keyboard goes to suspend state
-void visualizer_suspend(void);
-// This should be called when the keyboard wakes up from suspend state
-void visualizer_resume(void);
-
-// These functions are week, so they can be overridden by the keyboard
-// if needed
-GDisplay* get_lcd_display(void);
-GDisplay* get_led_display(void);
-
-// For emulator builds, this function need to be implemented
-#ifdef EMULATOR
-void draw_emulator(void);
-#endif
-
-// If you need support for more than 16 keyframes per animation, you can change this
-#define MAX_VISUALIZER_KEY_FRAMES 16
-
-struct keyframe_animation_t;
-
-typedef struct {
- layer_state_t layer;
- layer_state_t default_layer;
- uint32_t leds; // See led.h for available statuses
- uint8_t mods;
- bool suspended;
-#ifdef BACKLIGHT_ENABLE
- uint8_t backlight_level;
-#endif
-#ifdef VISUALIZER_USER_DATA_SIZE
- uint8_t user_data[VISUALIZER_USER_DATA_SIZE];
-#endif
-} visualizer_keyboard_status_t;
-
-// The state struct is used by the various keyframe functions
-// It's also used for setting the LCD color and layer text
-// from the user customized code
-typedef struct visualizer_state_t {
- // The user code should primarily be modifying these
- uint32_t target_lcd_color;
- const char* layer_text;
-
- // The user visualizer(and animation functions) can read these
- visualizer_keyboard_status_t status;
-
- // These are used by the animation functions
- uint32_t current_lcd_color;
- uint32_t prev_lcd_color;
-#ifdef LCD_ENABLE
- gFont font_fixed5x8;
- gFont font_dejavusansbold12;
-#endif
-} visualizer_state_t;
-
-// Any custom keyframe function should have this signature
-// return true to get continuous updates, otherwise you will only get one
-// update per frame
-typedef bool (*frame_func)(struct keyframe_animation_t*, visualizer_state_t*);
-
-// Represents a keyframe animation, so fields are internal to the system
-// while others are meant to be initialized by the user code
-typedef struct keyframe_animation_t {
- // These should be initialized
- int num_frames;
- bool loop;
- int frame_lengths[MAX_VISUALIZER_KEY_FRAMES];
- frame_func frame_functions[MAX_VISUALIZER_KEY_FRAMES];
-
- // Used internally by the system, and can also be read by
- // keyframe update functions
- int current_frame;
- int time_left_in_frame;
- bool first_update_of_frame;
- bool last_update_of_frame;
- bool need_update;
-
-} keyframe_animation_t;
-
-extern GDisplay* LCD_DISPLAY;
-extern GDisplay* LED_DISPLAY;
-
-void start_keyframe_animation(keyframe_animation_t* animation);
-void stop_keyframe_animation(keyframe_animation_t* animation);
-// This runs the next keyframe, but does not update the animation state
-// Useful for crossfades for example
-void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state);
-
-// The master can set userdata which will be transferred to the slave
-#ifdef VISUALIZER_USER_DATA_SIZE
-void visualizer_set_user_data(void* user_data);
-#endif
-
-// These functions have to be implemented by the user
-// Called regularly each time the state has changed (but not every scan loop)
-void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status);
-// Called when the computer goes to suspend, will also stop calling update_user_visualizer_state
-void user_visualizer_suspend(visualizer_state_t* state);
-// You have to start at least one animation as a response to the following two functions
-// When the animation has finished the visualizer will resume normal operation and start calling the
-// update_user_visualizer_state again
-// Called when the keyboard boots up
-void initialize_user_visualizer(visualizer_state_t* state);
-// Called when the computer resumes from a suspend
-void user_visualizer_resume(visualizer_state_t* state);
diff --git a/quantum/visualizer/visualizer.mk b/quantum/visualizer/visualizer.mk
deleted file mode 100644
index 4c961ac59d..0000000000
--- a/quantum/visualizer/visualizer.mk
+++ /dev/null
@@ -1,123 +0,0 @@
-# The MIT License (MIT)
-#
-# Copyright (c) 2016 Fred Sundvik
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-define ADD_DRIVER
- $(1)_DRIVER:=$(strip $($(1)_DRIVER))
- $(1)_WIDTH:=$(strip $($(1)_WIDTH))
- $(1)_HEIGHT:=$(strip $($(1)_HEIGHT))
- ifeq ($($(1)_DRIVER),)
- $$(error $(1)_DRIVER is not defined)
- endif
- ifeq ($($(1)_WIDTH),)
- $$(error $(1)_WIDTH is not defined)
- endif
- ifeq ($($(1)_HEIGHT),)
- $$(error $(1)_HEIGHT is not defined)
- endif
- OPT_DEFS+=-D$(1)_WIDTH=$($(1)_WIDTH)
- OPT_DEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT)
- GFXDEFS+=-D$(1)_WIDTH=$($(1)_WIDTH)
- GFXDEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT)
- $(1)_DISPLAY_NUMBER:=$$(words $$(GDISP_DRIVER_LIST))
- OPT_DEFS+=-D$(1)_DISPLAY_NUMBER=$$($(1)_DISPLAY_NUMBER)
- include $(TOP_DIR)/drivers/ugfx/gdisp/$($(1)_DRIVER)/driver.mk
-endef
-
-GDISP_DRIVER_LIST:=
-
-SRC += $(VISUALIZER_DIR)/visualizer.c \
- $(VISUALIZER_DIR)/visualizer_keyframes.c
-EXTRAINCDIRS += $(GFXINC) $(VISUALIZER_DIR)
-GFXLIB = $(LIB_PATH)/ugfx
-VPATH += $(VISUALIZER_PATH)
-
-OPT_DEFS += -DVISUALIZER_ENABLE
-
-ifdef LCD_ENABLE
-OPT_DEFS += -DLCD_ENABLE
-ULIBS += -lm
-endif
-
-ifeq ($(strip $(LCD_ENABLE)), yes)
- SRC += $(VISUALIZER_DIR)/lcd_keyframes.c
- ifeq ($(strip $(LCD_BACKLIGHT_ENABLE)), yes)
- OPT_DEFS += -DLCD_BACKLIGHT_ENABLE
- SRC += $(VISUALIZER_DIR)/lcd_backlight.c
- SRC += $(VISUALIZER_DIR)/lcd_backlight_keyframes.c
- endif
-# Note, that the linker will strip out any resources that are not actually in use
-SRC += $(VISUALIZER_DIR)/resources/lcd_logo.c
-$(eval $(call ADD_DRIVER,LCD))
-endif
-
-ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
-SRC += $(VISUALIZER_DIR)/led_backlight_keyframes.c
-$(eval $(call ADD_DRIVER,LED))
-endif
-
-SRC += $(VISUALIZER_DIR)/default_animations.c
-
-include $(GFXLIB)/gfx.mk
-# For the common_gfxconf.h
-GFXINC += quantum/visualizer
-
-GFXSRC := $(patsubst $(TOP_DIR)/%,%,$(GFXSRC))
-GFXDEFS := $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS)))
-
-GDISP_LIST_COMMA=,
-GDISP_LIST_EMPTY=
-GDISP_LIST_SPACE=$(GDISP_LIST_EMPTY) $(GDISP_LIST_EMPTY)
-
-GDISP_DRIVER_LIST := $(strip $(GDISP_DRIVER_LIST))
-GDISP_DRIVER_LIST := $(subst $(GDISP_LIST_SPACE),$(GDISP_LIST_COMMA),$(GDISP_DRIVER_LIST))
-
-GFXDEFS +=-DGDISP_DRIVER_LIST="$(GDISP_DRIVER_LIST)"
-
-ifneq ("$(wildcard $(KEYMAP_PATH)/visualizer.c)","")
- SRC += $(KEYMAP_PATH)/visualizer.c
-else
- VISUALIZER_1 := $(KEYBOARD_PATH_1)/visualizer.c
- VISUALIZER_2 := $(KEYBOARD_PATH_2)/visualizer.c
- VISUALIZER_3 := $(KEYBOARD_PATH_3)/visualizer.c
- VISUALIZER_4 := $(KEYBOARD_PATH_4)/visualizer.c
- VISUALIZER_5 := $(KEYBOARD_PATH_5)/visualizer.c
-
- ifneq ("$(wildcard $(VISUALIZER_5))","")
- SRC += $(VISUALIZER_5)
- endif
- ifneq ("$(wildcard $(VISUALIZER_4))","")
- SRC += $(VISUALIZER_4)
- endif
- ifneq ("$(wildcard $(VISUALIZER_3))","")
- SRC += $(VISUALIZER_3)
- endif
- ifneq ("$(wildcard $(VISUALIZER_2))","")
- SRC += $(VISUALIZER_2)
- endif
- ifneq ("$(wildcard $(VISUALIZER_1))","")
- SRC += $(VISUALIZER_1)
- endif
-endif
-
-ifdef EMULATOR
-UINCDIR += $(TMK_DIR)/common
-endif
diff --git a/quantum/wpm.c b/quantum/wpm.c
index e711e9fe73..925e2c416e 100644
--- a/quantum/wpm.c
+++ b/quantum/wpm.c
@@ -21,13 +21,37 @@
// WPM Stuff
static uint8_t current_wpm = 0;
-static uint16_t wpm_timer = 0;
+static uint32_t wpm_timer = 0;
+#ifndef WPM_UNFILTERED
+static uint32_t smoothing_timer = 0;
+#endif
-// This smoothing is 40 keystrokes
-static const float wpm_smoothing = WPM_SMOOTHING;
+/* The WPM calculation works by specifying a certain number of 'periods' inside
+ * a ring buffer, and we count the number of keypresses which occur in each of
+ * those periods. Then to calculate WPM, we add up all of the keypresses in
+ * the whole ring buffer, divide by the number of keypresses in a 'word', and
+ * then adjust for how much time is captured by our ring buffer. Right now
+ * the ring buffer is hardcoded below to be six half-second periods, accounting
+ * for a total WPM sampling period of up to three seconds of typing.
+ *
+ * Whenever our WPM drops to absolute zero due to no typing occurring within
+ * any contiguous three seconds, we reset and start measuring fresh,
+ * which lets our WPM immediately reach the correct value even before a full
+ * three second sampling buffer has been filled.
+ */
+#define MAX_PERIODS (WPM_SAMPLE_PERIODS)
+#define PERIOD_DURATION (1000 * WPM_SAMPLE_SECONDS / MAX_PERIODS)
+#define LATENCY (100)
+static int8_t period_presses[MAX_PERIODS] = {0};
+static uint8_t current_period = 0;
+static uint8_t periods = 1;
-void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; }
+#if !defined(WPM_UNFILTERED)
+static uint8_t prev_wpm = 0;
+static uint8_t next_wpm = 0;
+#endif
+void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; }
uint8_t get_current_wpm(void) { return current_wpm; }
bool wpm_keycode(uint16_t keycode) { return wpm_keycode_kb(keycode); }
@@ -56,7 +80,7 @@ __attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) {
} else if (keycode > 0xFF) {
keycode = 0;
}
- if (keycode == KC_DEL || keycode == KC_BSPC) {
+ if (keycode == KC_DELETE || keycode == KC_BACKSPACE) {
if (((get_mods() | get_oneshot_mods()) & MOD_MASK_CTRL) || weak_modded) {
return WPM_ESTIMATED_WORD_SIZE;
} else {
@@ -68,33 +92,65 @@ __attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) {
}
#endif
+// Outside 'raw' mode we smooth results over time.
+
void update_wpm(uint16_t keycode) {
if (wpm_keycode(keycode)) {
- if (wpm_timer > 0) {
- uint16_t latest_wpm = 60000 / timer_elapsed(wpm_timer) / WPM_ESTIMATED_WORD_SIZE;
- if (latest_wpm > UINT8_MAX) {
- latest_wpm = UINT8_MAX;
- }
- current_wpm += ceilf((latest_wpm - current_wpm) * wpm_smoothing);
- }
- wpm_timer = timer_read();
+ period_presses[current_period]++;
}
#ifdef WPM_ALLOW_COUNT_REGRESSION
uint8_t regress = wpm_regress_count(keycode);
if (regress) {
- if (current_wpm < regress) {
- current_wpm = 0;
- } else {
- current_wpm -= regress;
- }
- wpm_timer = timer_read();
+ period_presses[current_period]--;
}
#endif
}
void decay_wpm(void) {
- if (timer_elapsed(wpm_timer) > 1000) {
- current_wpm += (-current_wpm) * wpm_smoothing;
- wpm_timer = timer_read();
+ int32_t presses = period_presses[0];
+ for (int i = 1; i <= periods; i++) {
+ presses += period_presses[i];
+ }
+ if (presses < 0) {
+ presses = 0;
}
+ int32_t elapsed = timer_elapsed32(wpm_timer);
+ uint32_t duration = (((periods)*PERIOD_DURATION) + elapsed);
+ uint32_t wpm_now = (60000 * presses) / (duration * WPM_ESTIMATED_WORD_SIZE);
+ wpm_now = (wpm_now > 240) ? 240 : wpm_now;
+
+ if (elapsed > PERIOD_DURATION) {
+ current_period = (current_period + 1) % MAX_PERIODS;
+ period_presses[current_period] = 0;
+ periods = (periods < MAX_PERIODS - 1) ? periods + 1 : MAX_PERIODS - 1;
+ elapsed = 0;
+ /* if (wpm_timer == 0) { */
+ wpm_timer = timer_read32();
+ /* } else { */
+ /* wpm_timer += PERIOD_DURATION; */
+ /* } */
+ }
+ if (presses < 2) // don't guess high WPM based on a single keypress.
+ wpm_now = 0;
+
+#if defined WPM_LAUNCH_CONTROL
+ if (presses == 0) {
+ current_period = 0;
+ periods = 0;
+ wpm_now = 0;
+ }
+#endif // WPM_LAUNCH_CONTROL
+
+#ifndef WPM_UNFILTERED
+ int32_t latency = timer_elapsed32(smoothing_timer);
+ if (latency > LATENCY) {
+ smoothing_timer = timer_read32();
+ prev_wpm = current_wpm;
+ next_wpm = wpm_now;
+ }
+
+ current_wpm = prev_wpm + (latency * ((int)next_wpm - (int)prev_wpm) / LATENCY);
+#else
+ current_wpm = wpm_now;
+#endif
}
diff --git a/quantum/wpm.h b/quantum/wpm.h
index 4af52d2b98..c8e7d26684 100644
--- a/quantum/wpm.h
+++ b/quantum/wpm.h
@@ -22,8 +22,11 @@
#ifndef WPM_ESTIMATED_WORD_SIZE
# define WPM_ESTIMATED_WORD_SIZE 5
#endif
-#ifndef WPM_SMOOTHING
-# define WPM_SMOOTHING 0.0487
+#ifndef WPM_SAMPLE_SECONDS
+# define WPM_SAMPLE_SECONDS 5
+#endif
+#ifndef WPM_SAMPLE_PERIODS
+# define WPM_SAMPLE_PERIODS 50
#endif
bool wpm_keycode(uint16_t keycode);
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 1db3b6d733..7213707338 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -5,4 +5,5 @@
nose2
flake8
pep8-naming
+pyflakes
yapf
diff --git a/shell.nix b/shell.nix
index c36df032de..5023a3b0f7 100644
--- a/shell.nix
+++ b/shell.nix
@@ -14,7 +14,7 @@ let
projectDir = ./util/nix;
overrides = poetry2nix.overrides.withDefaults (self: super: {
qmk = super.qmk.overridePythonAttrs(old: {
- # Allow QMK CLI to run "bin/qmk" as a subprocess (the wrapper changes
+ # Allow QMK CLI to run "qmk" as a subprocess (the wrapper changes
# $PATH and breaks these invocations).
dontWrapPythonPrograms = true;
});
diff --git a/testlist.mk b/testlist.mk
index b66b93d295..904485c15c 100644
--- a/testlist.mk
+++ b/testlist.mk
@@ -1,10 +1,9 @@
-TEST_LIST = $(notdir $(patsubst %/rules.mk,%,$(wildcard $(ROOT_DIR)/tests/*/rules.mk)))
-FULL_TESTS := $(TEST_LIST)
+TEST_LIST = $(sort $(patsubst %/test.mk,%, $(shell find $(ROOT_DIR)tests -type f -name test.mk)))
+FULL_TESTS := $(notdir $(TEST_LIST))
-include $(ROOT_DIR)/quantum/debounce/tests/testlist.mk
-include $(ROOT_DIR)/quantum/sequencer/tests/testlist.mk
-include $(ROOT_DIR)/quantum/serial_link/tests/testlist.mk
-include $(ROOT_DIR)/tmk_core/common/test/testlist.mk
+include $(QUANTUM_PATH)/debounce/tests/testlist.mk
+include $(QUANTUM_PATH)/sequencer/tests/testlist.mk
+include $(PLATFORM_PATH)/test/testlist.mk
define VALIDATE_TEST_LIST
ifneq ($1,)
diff --git a/data/templates/base/keyboard.c b/tests/auto_shift/config.h
index f69ae16ede..4f343b4529 100644
--- a/data/templates/base/keyboard.c
+++ b/tests/auto_shift/config.h
@@ -1,4 +1,4 @@
-/* Copyright %YEAR% %YOUR_NAME%
+/* Copyright 2021 Stefan Kerkmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,4 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "%KEYBOARD%.h"
+#pragma once
+
+#include "test_common.h" \ No newline at end of file
diff --git a/tests/auto_shift/test.mk b/tests/auto_shift/test.mk
new file mode 100644
index 0000000000..4259c606e4
--- /dev/null
+++ b/tests/auto_shift/test.mk
@@ -0,0 +1,20 @@
+# Copyright 2021 Stefan Kerkmann
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+AUTO_SHIFT_ENABLE = yes \ No newline at end of file
diff --git a/tests/auto_shift/test_auto_shift.cpp b/tests/auto_shift/test_auto_shift.cpp
new file mode 100644
index 0000000000..9c5ed9a832
--- /dev/null
+++ b/tests/auto_shift/test_auto_shift.cpp
@@ -0,0 +1,73 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_fixture.hpp"
+#include "test_keymap_key.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class AutoShift : public TestFixture {};
+
+TEST_F(AutoShift, key_release_before_timeout) {
+ TestDriver driver;
+ InSequence s;
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({regular_key});
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(AutoShift, key_release_after_timeout) {
+ TestDriver driver;
+ InSequence s;
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({regular_key});
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ idle_for(AUTO_SHIFT_TIMEOUT);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+} \ No newline at end of file
diff --git a/tests/basic/config.h b/tests/basic/config.h
index 99bd62d991..85fa9d691d 100644
--- a/tests/basic/config.h
+++ b/tests/basic/config.h
@@ -16,5 +16,4 @@
#pragma once
-#define MATRIX_ROWS 4
-#define MATRIX_COLS 10
+#include "test_common.h" \ No newline at end of file
diff --git a/tests/basic/keymap.c b/tests/basic/keymap.c
deleted file mode 100644
index 2b5747abb7..0000000000
--- a/tests/basic/keymap.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "quantum.h"
-
-// Don't rearrange keys as existing tests might rely on the order
-// Col2, Row 0 has to be KC_NO, because tests rely on it
-
-#define COMBO1 RSFT(LCTL(KC_O))
-
-const uint16_t PROGMEM
- keymaps[][MATRIX_ROWS][MATRIX_COLS] =
- {
- [0] =
- {
- // 0 1 2 3 4 5 6 7 8 9
- {KC_A, KC_B, KC_NO, KC_LSFT, KC_RSFT, KC_LCTL, COMBO1, SFT_T(KC_P), M(0), KC_NO},
- {KC_EQL, KC_PLUS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
- {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
- {KC_C, KC_D, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
- },
-};
-
-const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
- if (record->event.pressed) {
- switch (id) {
- case 0:
- return MACRO(D(LSFT), T(H), U(LSFT), T(E), T(L), T(L), T(O), T(SPACE), W(100), D(LSFT), T(W), U(LSFT), I(10), T(O), T(R), T(L), T(D), D(LSFT), T(1), U(LSFT), END);
- }
- }
- return MACRO_NONE;
-};
diff --git a/tests/basic/test.mk b/tests/basic/test.mk
new file mode 100644
index 0000000000..29690d1adf
--- /dev/null
+++ b/tests/basic/test.mk
@@ -0,0 +1,18 @@
+# Copyright 2017 Fred Sundvik
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# -------------------------------------------------------------------------------- \ No newline at end of file
diff --git a/tests/basic/test_action_layer.cpp b/tests/basic/test_action_layer.cpp
index d00a0859b9..1b12d13642 100644
--- a/tests/basic/test_action_layer.cpp
+++ b/tests/basic/test_action_layer.cpp
@@ -14,39 +14,54 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "gtest/gtest.h"
+#include "keyboard_report_util.hpp"
#include "test_common.hpp"
using testing::_;
-using testing::Return;
+using testing::InSequence;
class ActionLayer : public TestFixture {};
-// TEST_F(ActionLayer, LayerStateDBG) {
-// layer_state_set(0);
-// }
-
-// TEST_F(ActionLayer, LayerStateSet) {
-// layer_state_set(0);
-// EXPECT_EQ(layer_state, 0);
-// layer_state_set(0b001100);
-// EXPECT_EQ(layer_state, 0b001100);
-// }
-
-// TEST_F(ActionLayer, LayerStateIs) {
-// layer_state_set(0);
-// EXPECT_EQ(layer_state_is(0), true);
-// EXPECT_EQ(layer_state_is(1), true);
-// layer_state_set(1);
-// EXPECT_EQ(layer_state_is(0), true);
-// EXPECT_EQ(layer_state_is(1), true);
-// layer_state_set(2);
-// EXPECT_EQ(layer_state_is(0), false);
-// EXPECT_EQ(layer_state_is(1), false);
-// EXPECT_EQ(layer_state_is(2), true);
-// }
+TEST_F(ActionLayer, LayerStateDBG) {
+ TestDriver driver;
+
+ layer_state_set(0);
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, LayerStateSet) {
+ TestDriver driver;
+
+ layer_state_set(0);
+ EXPECT_EQ(layer_state, 0);
+ layer_state_set(0b001100);
+ EXPECT_EQ(layer_state, 0b001100);
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, LayerStateIs) {
+ TestDriver driver;
+
+ layer_state_set(0);
+ EXPECT_EQ(layer_state_is(0), true);
+ EXPECT_EQ(layer_state_is(1), false);
+ layer_state_set(1);
+ EXPECT_EQ(layer_state_is(0), true);
+ EXPECT_EQ(layer_state_is(1), false);
+ layer_state_set(2);
+ EXPECT_EQ(layer_state_is(0), false);
+ EXPECT_EQ(layer_state_is(1), true);
+ EXPECT_EQ(layer_state_is(2), false);
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
TEST_F(ActionLayer, LayerStateCmp) {
- uint32_t prev_layer;
+ TestDriver driver;
+ uint32_t prev_layer;
prev_layer = 0;
EXPECT_EQ(layer_state_cmp(prev_layer, 0), true);
@@ -60,33 +75,339 @@ TEST_F(ActionLayer, LayerStateCmp) {
EXPECT_EQ(layer_state_cmp(prev_layer, 0), false);
EXPECT_EQ(layer_state_cmp(prev_layer, 1), true);
EXPECT_EQ(layer_state_cmp(prev_layer, 2), false);
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, LayerClear) {
+ TestDriver driver;
+
+ layer_clear();
+ EXPECT_EQ(layer_state, 0);
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, LayerMove) {
+ TestDriver driver;
+
+ layer_move(0);
+ EXPECT_EQ(layer_state, 1);
+ layer_move(3);
+ EXPECT_EQ(layer_state, 0b1000);
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, LayerOn) {
+ TestDriver driver;
+
+ layer_clear();
+ layer_on(1);
+ layer_on(3);
+ layer_on(3);
+ EXPECT_EQ(layer_state, 0b1010);
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, LayerOff) {
+ TestDriver driver;
+
+ layer_clear();
+ layer_on(1);
+ layer_on(3);
+ layer_off(3);
+ layer_off(2);
+ EXPECT_EQ(layer_state, 0b0010);
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, MomentaryLayerDoesNothing) {
+ TestDriver driver;
+ KeymapKey layer_key = KeymapKey{0, 0, 0, MO(1)};
+
+ set_keymap({layer_key});
+
+ /* Press and release MO, nothing should happen. */
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ layer_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ layer_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, MomentaryLayerWithKeypress) {
+ TestDriver driver;
+ KeymapKey layer_key = KeymapKey{0, 0, 0, MO(1)};
+
+ /* These keys must have the same position in the matrix, only the layer is different. */
+ KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A};
+ set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}});
+
+ /* Press MO. */
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ layer_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press key on layer 1 */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release key on layer 1 */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ regular_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release MO */
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ layer_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, ToggleLayerDoesNothing) {
+ GTEST_SKIP() << "TODO: Toggle layer does not activate the expected layer on key press but on release.";
+
+ TestDriver driver;
+ KeymapKey layer_key = KeymapKey{0, 0, 0, TG(1)};
+
+ set_keymap({layer_key});
+
+ /* Press TG. Layer state should not change as it's applied on release. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ layer_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release TG. */
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ layer_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, ToggleLayerUpAndDown) {
+ GTEST_SKIP() << "TODO: Toggle layer does not activate the expected layer on key press but on release.";
+
+ TestDriver driver;
+ KeymapKey toggle_layer_1_on_layer_0 = KeymapKey{0, 0, 0, TG(1)};
+ KeymapKey toggle_layer_0_on_layer_1 = KeymapKey{1, 1, 0, TG(0)};
+
+ set_keymap({toggle_layer_1_on_layer_0, toggle_layer_0_on_layer_1});
+
+ /* Toggle Layer 1. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ toggle_layer_1_on_layer_0.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ toggle_layer_1_on_layer_0.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Toggle Layer 0. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ toggle_layer_0_on_layer_1.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ toggle_layer_0_on_layer_1.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, LayerTapToggleDoesNothing) {
+ GTEST_SKIP() << "TODO: Tap toggle layer does not activate the expected layer on key press.";
+
+ TestDriver driver;
+ KeymapKey layer_key = KeymapKey{0, 0, 0, TT(1)};
+
+ set_keymap({layer_key});
+
+ /* Press and release TT. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0);
+ layer_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(2);
+ layer_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, LayerTapToggleWithKeypress) {
+ GTEST_SKIP() << "TODO: Tap toggle layer does not activate the expected layer on key press.";
+
+ TestDriver driver;
+ KeymapKey layer_key = KeymapKey{0, 0, 0, TT(1)};
+
+ /* These keys must have the same position in the matrix, only the layer is different. */
+ KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A};
+ set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}});
+
+ /* Press TT. */
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0);
+ layer_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ regular_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ layer_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) {
+ GTEST_SKIP() << "TODO: Tap toggle layer does not activate the expected layer on key press.";
+
+ TestDriver driver;
+ KeymapKey layer_key = KeymapKey{0, 0, 0, TT(1)};
+
+ /* These keys must have the same position in the matrix, only the layer is different. */
+ KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A};
+ set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}});
+
+ /* Tap TT five times . */
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(9);
+
+ layer_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ layer_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+
+ layer_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ layer_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+
+ layer_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ layer_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+
+ layer_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ layer_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+
+ layer_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ layer_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ regular_key.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
}
-// TEST_F(ActionLayer, LayerClear) {
-// layer_clear();
-// EXPECT_EQ(layer_state, 0);
-// }
-
-// TEST_F(ActionLayer, LayerMove) {
-// layer_move(0);
-// EXPECT_EQ(layer_state, 1);
-// layer_move(3);
-// EXPECT_EQ(layer_state, 0b1000);
-// }
-
-// TEST_F(ActionLayer, LayerOn) {
-// layer_clear();
-// layer_on(1);
-// layer_on(3);
-// layer_on(3);
-// EXPECT_EQ(layer_state, 0b1010);
-// }
-
-// TEST_F(ActionLayer, LayerOff) {
-// layer_clear();
-// layer_on(1);
-// layer_on(3);
-// layer_off(3);
-// layer_off(2);
-// EXPECT_EQ(layer_state, 0b1000);
-// }
+TEST_F(ActionLayer, LayerTapReleasedBeforeKeypressReleaseWithModifiers) {
+ GTEST_SKIP() << "TODO: Modifiers are erroneously discarded on layer changes, although a key that introduced the modifier is still held.";
+ TestDriver driver;
+ InSequence s;
+
+ KeymapKey layer_0_key_0 = KeymapKey{0, 0, 0, LT(1, KC_T)};
+ KeymapKey layer_1_key_1 = KeymapKey{1, 1, 0, RALT(KC_9)};
+
+ set_keymap({layer_0_key_0, layer_1_key_1});
+
+ /* Press layer tap and wait for tapping term to switch to layer 1 */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0);
+ layer_0_key_0.press();
+ idle_for(TAPPING_TERM);
+ EXPECT_TRUE(layer_state_is(0));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press key with layer 1 mapping, result basically expected
+ * altough more reports are send then necessary. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RALT))).Times(1);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RALT, KC_9))).Times(1);
+ layer_1_key_1.press();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(1));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release layer tap key, no report is send because key is still held. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ layer_0_key_0.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Unregister keycode and modifier. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RALT))).Times(1);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ layer_1_key_1.release();
+ run_one_scan_loop();
+ EXPECT_TRUE(layer_state_is(0));
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
diff --git a/tests/basic/test_keypress.cpp b/tests/basic/test_keypress.cpp
index ecd6e98e44..1c175c9d56 100644
--- a/tests/basic/test_keypress.cpp
+++ b/tests/basic/test_keypress.cpp
@@ -14,11 +14,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "keycode.h"
#include "test_common.hpp"
using testing::_;
using testing::InSequence;
-using testing::Return;
class KeyPress : public TestFixture {};
@@ -30,95 +30,156 @@ TEST_F(KeyPress, SendKeyboardIsNotCalledWhenNoKeyIsPressed) {
TEST_F(KeyPress, CorrectKeyIsReportedWhenPressed) {
TestDriver driver;
- press_key(0, 0);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A)));
+ auto key = KeymapKey(0, 0, 0, KC_A);
+
+ set_keymap({key});
+
+ key.press();
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key.report_code)));
keyboard_task();
- release_key(0, 0);
+
+ key.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
keyboard_task();
}
+TEST_F(KeyPress, ANonMappedKeyDoesNothing) {
+ TestDriver driver;
+ auto key = KeymapKey(0, 0, 0, KC_NO);
+
+ set_keymap({key});
+
+ key.press();
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ keyboard_task();
+ keyboard_task();
+}
+
TEST_F(KeyPress, CorrectKeysAreReportedWhenTwoKeysArePressed) {
TestDriver driver;
- press_key(1, 0);
- press_key(0, 3);
+ auto key_b = KeymapKey(0, 0, 0, KC_B);
+ auto key_c = KeymapKey(0, 1, 1, KC_C);
+
+ set_keymap({key_b, key_c});
+
+ key_b.press();
+ key_c.press();
// Note that QMK only processes one key at a time
// See issue #1476 for more information
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_b.report_code)));
keyboard_task();
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B, KC_C)));
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_b.report_code, key_c.report_code)));
keyboard_task();
- release_key(1, 0);
- release_key(0, 3);
+
+ key_b.release();
+ key_c.release();
// Note that the first key released is the first one in the matrix order
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_C)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_c.report_code)));
keyboard_task();
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
- keyboard_task();
-}
-TEST_F(KeyPress, ANonMappedKeyDoesNothing) {
- TestDriver driver;
- press_key(2, 0);
- EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
- keyboard_task();
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
keyboard_task();
}
TEST_F(KeyPress, LeftShiftIsReportedCorrectly) {
TestDriver driver;
- press_key(3, 0);
- press_key(0, 0);
+ auto key_a = KeymapKey(0, 0, 0, KC_A);
+ auto key_lsft = KeymapKey(0, 3, 0, KC_LSFT);
+
+ set_keymap({key_a, key_lsft});
+
+ key_lsft.press();
+ key_a.press();
+
// Unfortunately modifiers are also processed in the wrong order
// See issue #1476 for more information
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_a.report_code)));
keyboard_task();
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_a.report_code, key_lsft.report_code)));
keyboard_task();
- release_key(0, 0);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+
+ key_a.release();
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code)));
keyboard_task();
- release_key(3, 0);
+
+ key_lsft.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
keyboard_task();
}
TEST_F(KeyPress, PressLeftShiftAndControl) {
TestDriver driver;
- press_key(3, 0);
- press_key(5, 0);
+ auto key_lsft = KeymapKey(0, 3, 0, KC_LSFT);
+ auto key_lctrl = KeymapKey(0, 5, 0, KC_LCTRL);
+
+ set_keymap({key_lctrl, key_lsft});
+
+ key_lsft.press();
+ key_lctrl.press();
+
// Unfortunately modifiers are also processed in the wrong order
// See issue #1476 for more information
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code)));
+ keyboard_task();
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code, key_lctrl.report_code)));
keyboard_task();
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_LCTRL)));
+
+ key_lsft.release();
+ key_lctrl.release();
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lctrl.report_code)));
+ keyboard_task();
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
keyboard_task();
}
TEST_F(KeyPress, LeftAndRightShiftCanBePressedAtTheSameTime) {
TestDriver driver;
- press_key(3, 0);
- press_key(4, 0);
+ auto key_lsft = KeymapKey(0, 3, 0, KC_LSFT);
+ auto key_rsft = KeymapKey(0, 4, 0, KC_RSFT);
+
+ set_keymap({key_rsft, key_lsft});
+
+ key_lsft.press();
+ key_rsft.press();
// Unfortunately modifiers are also processed in the wrong order
// See issue #1476 for more information
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code)));
+ keyboard_task();
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code, key_rsft.report_code)));
keyboard_task();
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_RSFT)));
+
+ key_lsft.release();
+ key_rsft.release();
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_rsft.report_code)));
+ keyboard_task();
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
keyboard_task();
}
TEST_F(KeyPress, RightShiftLeftControlAndCharWithTheSameKey) {
TestDriver driver;
- press_key(6, 0);
+ auto combo_key = KeymapKey(0, 0, 0, RSFT(LCTL(KC_O)));
+
+ set_keymap({combo_key});
+
// BUG: The press is split into two reports
// BUG: It reports RSFT instead of LSFT
// See issue #524 for more information
// The underlying cause is that we use only one bit to represent the right hand
// modifiers.
+ combo_key.press();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RSFT, KC_RCTRL)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RSFT, KC_RCTRL, KC_O)));
keyboard_task();
- release_key(6, 0);
+
+ combo_key.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RSFT, KC_RCTRL)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
keyboard_task();
@@ -127,25 +188,29 @@ TEST_F(KeyPress, RightShiftLeftControlAndCharWithTheSameKey) {
TEST_F(KeyPress, PressPlusEqualReleaseBeforePress) {
TestDriver driver;
InSequence s;
+ auto key_plus = KeymapKey(0, 1, 1, KC_PLUS);
+ auto key_eql = KeymapKey(0, 0, 1, KC_EQL);
- press_key(1, 1); // KC_PLUS
+ set_keymap({key_plus, key_eql});
+
+ key_plus.press();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_EQL)));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- release_key(1, 1); // KC_PLUS
+ key_plus.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- press_key(0, 1); // KC_EQL
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_EQL)));
+ key_eql.press();
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_eql.report_code)));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- release_key(0, 1); // KC_EQL
+ key_eql.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
@@ -154,27 +219,31 @@ TEST_F(KeyPress, PressPlusEqualReleaseBeforePress) {
TEST_F(KeyPress, PressPlusEqualDontReleaseBeforePress) {
TestDriver driver;
InSequence s;
+ auto key_plus = KeymapKey(0, 1, 1, KC_PLUS);
+ auto key_eql = KeymapKey(0, 0, 1, KC_EQL);
- press_key(1, 1); // KC_PLUS
+ set_keymap({key_plus, key_eql});
+
+ key_plus.press();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_EQL)));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- press_key(0, 1); // KC_EQL
+ key_eql.press();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_EQL)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_EQUAL)));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- release_key(1, 1); // KC_PLS
+ key_plus.release();
// BUG: Should really still return KC_EQL, but this is fine too
// It's also called twice for some reason
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(2);
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- release_key(0, 1); // KC_EQL
+ key_eql.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
@@ -183,24 +252,28 @@ TEST_F(KeyPress, PressPlusEqualDontReleaseBeforePress) {
TEST_F(KeyPress, PressEqualPlusReleaseBeforePress) {
TestDriver driver;
InSequence s;
+ auto key_plus = KeymapKey(0, 1, 1, KC_PLUS);
+ auto key_eql = KeymapKey(0, 0, 1, KC_EQL);
- press_key(0, 1); // KC_EQL
+ set_keymap({key_plus, key_eql});
+
+ key_eql.press();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_EQL)));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- release_key(0, 1); // KQ_EQL
+ key_eql.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- press_key(1, 1); // KC_PLUS
+ key_plus.press();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_EQL)));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- release_key(1, 1); // KC_PLUS
+ key_plus.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
run_one_scan_loop();
@@ -210,31 +283,35 @@ TEST_F(KeyPress, PressEqualPlusReleaseBeforePress) {
TEST_F(KeyPress, PressEqualPlusDontReleaseBeforePress) {
TestDriver driver;
InSequence s;
+ auto key_plus = KeymapKey(0, 1, 1, KC_PLUS);
+ auto key_eql = KeymapKey(0, 0, 1, KC_EQL);
+
+ set_keymap({key_plus, key_eql});
- press_key(0, 1); // KC_EQL
+ key_eql.press();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_EQL)));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- press_key(1, 1); // KC_PLUS
+ key_plus.press();
// BUG: The sequence is a bit strange, but it works, the end result is that
// KC_PLUS is sent
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_EQL)));
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_EQL)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_EQUAL)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_EQUAL)));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- release_key(0, 1); // KC_EQL
+ key_eql.release();
// I guess it's fine to still report shift here
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT)));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
- release_key(1, 1); // KC_PLUS
+ key_plus.release();
// This report is not needed
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
-}
+} \ No newline at end of file
diff --git a/tests/basic/test_macro.cpp b/tests/basic/test_macro.cpp
index dc4a77796a..ae2f3b32e3 100644
--- a/tests/basic/test_macro.cpp
+++ b/tests/basic/test_macro.cpp
@@ -24,14 +24,29 @@ class Macro : public TestFixture {};
#define AT_TIME(t) WillOnce(InvokeWithoutArgs([current_time]() { EXPECT_EQ(timer_elapsed32(current_time), t); }))
+extern "C" const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ if (record->event.pressed) {
+ switch (id) {
+ case 0:
+ return MACRO(D(LSFT), T(H), U(LSFT), T(E), T(L), T(L), T(O), T(SPACE), W(100), D(LSFT), T(W), U(LSFT), I(10), T(O), T(R), T(L), T(D), D(LSFT), T(1), U(LSFT), END);
+ }
+ }
+ return MACRO_NONE;
+};
+
TEST_F(Macro, PlayASimpleMacro) {
TestDriver driver;
InSequence s;
- press_key(8, 0);
+ auto key_macro = KeymapKey(0, 8, 0, M(0));
+
+ set_keymap({key_macro});
+
+ key_macro.press();
+
uint32_t current_time = timer_read32();
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).AT_TIME(0);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_H))).AT_TIME(0);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).AT_TIME(0);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).AT_TIME(0);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_H))).AT_TIME(0);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).AT_TIME(0);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).AT_TIME(0);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_E))).AT_TIME(0);
// The macro system could actually skip these empty keyboard reports
@@ -45,9 +60,9 @@ TEST_F(Macro, PlayASimpleMacro) {
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).AT_TIME(0);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_SPACE))).AT_TIME(0);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).AT_TIME(0);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).AT_TIME(100);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_W))).AT_TIME(100);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).AT_TIME(100);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).AT_TIME(100);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_W))).AT_TIME(100);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).AT_TIME(100);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).AT_TIME(100);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_O)))
// BUG: The timer should not really have advanced 10 ms here
@@ -63,9 +78,11 @@ TEST_F(Macro, PlayASimpleMacro) {
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).AT_TIME(160);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_D))).AT_TIME(170);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).AT_TIME(180);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).AT_TIME(190);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_1))).AT_TIME(200);
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).AT_TIME(210);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).AT_TIME(190);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_1))).AT_TIME(200);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).AT_TIME(210);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).AT_TIME(220);
run_one_scan_loop();
+
+ key_macro.release();
}
diff --git a/tests/basic/test_one_shot_keys.cpp b/tests/basic/test_one_shot_keys.cpp
new file mode 100644
index 0000000000..98178912e4
--- /dev/null
+++ b/tests/basic/test_one_shot_keys.cpp
@@ -0,0 +1,197 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "action_util.h"
+#include "keyboard_report_util.hpp"
+#include "test_common.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class OneShot : public TestFixture {};
+class OneShotParametrizedTestFixture : public ::testing::WithParamInterface<std::pair<KeymapKey, KeymapKey>>, public OneShot {};
+
+TEST_F(OneShot, OSMWithoutAdditionalKeypressDoesNothing) {
+ TestDriver driver;
+ auto osm_key = KeymapKey(0, 0, 0, OSM(MOD_LSFT), KC_LSFT);
+
+ set_keymap({osm_key});
+
+ /* Press and release OSM key*/
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ osm_key.press();
+ run_one_scan_loop();
+ osm_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* OSM are added when an actual report is send */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code)));
+ send_keyboard_report();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Make unit-test pass */
+ clear_oneshot_mods();
+}
+
+#if defined(ONESHOT_TIMEOUT)
+
+TEST_P(OneShotParametrizedTestFixture, OSMExpiredDoesNothing) {
+ TestDriver driver;
+ KeymapKey osm_key = GetParam().first;
+ KeymapKey regular_key = GetParam().second;
+
+ set_keymap({osm_key, regular_key});
+
+ /* Press and release OSM */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ osm_key.press();
+ run_one_scan_loop();
+ osm_key.release();
+ idle_for(ONESHOT_TIMEOUT);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code))).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+#endif
+
+TEST_P(OneShotParametrizedTestFixture, OSMWithAdditionalKeypress) {
+ TestDriver driver;
+ KeymapKey osm_key = GetParam().first;
+ KeymapKey regular_key = GetParam().second;
+
+ set_keymap({osm_key, regular_key});
+
+ /* Press and release OSM */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ osm_key.press();
+ run_one_scan_loop();
+ osm_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code, regular_key.report_code))).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_P(OneShotParametrizedTestFixture, OSMAsRegularModifierWithAdditionalKeypress) {
+ TestDriver driver;
+ testing::InSequence s;
+
+ KeymapKey osm_key = GetParam().first;
+ KeymapKey regular_key = GetParam().second;
+
+ set_keymap({osm_key, regular_key});
+
+ /* Press OSM */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ osm_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release OSM */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code, osm_key.report_code))).Times(1);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ osm_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+// clang-format off
+
+INSTANTIATE_TEST_CASE_P(
+ OneShotModifierTests,
+ OneShotParametrizedTestFixture,
+ ::testing::Values(
+ /* first is osm key, second is regular key. */
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LCTL), KC_LCTL}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LALT), KC_LALT}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LGUI), KC_LGUI}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RCTL), KC_RCTL}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RSFT), KC_RSFT}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RALT), KC_RALT}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RGUI), KC_RGUI}, KeymapKey{0, 1, 1, KC_A})
+ ));
+// clang-format on
+
+TEST_F(OneShot, OSLWithAdditionalKeypress) {
+ TestDriver driver;
+ InSequence s;
+ KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
+ KeymapKey regular_key = KeymapKey{1, 1, 0, KC_A};
+
+ set_keymap({osl_key, regular_key});
+
+ /* Press OSL key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ osl_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release OSL key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(2);
+ osl_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code))).Times(2);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
diff --git a/tests/basic/test_tapping.cpp b/tests/basic/test_tapping.cpp
index 30d032e9fd..e4a7e4a9f3 100644
--- a/tests/basic/test_tapping.cpp
+++ b/tests/basic/test_tapping.cpp
@@ -14,8 +14,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
#include "test_common.hpp"
#include "action_tapping.h"
+#include "test_keymap_key.hpp"
using testing::_;
using testing::InSequence;
@@ -25,14 +28,19 @@ class Tapping : public TestFixture {};
TEST_F(Tapping, TapA_SHFT_T_KeyReportsKey) {
TestDriver driver;
InSequence s;
+ auto key_shift_hold_p_tap = KeymapKey(0, 7, 0, SFT_T(KC_P));
+
+ set_keymap({key_shift_hold_p_tap});
- press_key(7, 0);
// Tapping keys does nothing on press
+ key_shift_hold_p_tap.press();
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
run_one_scan_loop();
- release_key(7, 0);
+
// First we get the key press
+ key_shift_hold_p_tap.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+
// Then the release
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
run_one_scan_loop();
@@ -41,25 +49,38 @@ TEST_F(Tapping, TapA_SHFT_T_KeyReportsKey) {
TEST_F(Tapping, HoldA_SHFT_T_KeyReportsShift) {
TestDriver driver;
InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 7, 0, SFT_T(KC_P));
+
+ set_keymap({mod_tap_hold_key});
+
+ mod_tap_hold_key.press();
- press_key(7, 0);
// Tapping keys does nothing on press
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
idle_for(TAPPING_TERM);
+
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
run_one_scan_loop();
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
}
TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) {
// See issue #1478 for more information
TestDriver driver;
InSequence s;
+ auto key_shift_hold_p_tap = KeymapKey(0, 7, 0, SFT_T(KC_P));
+
+ set_keymap({key_shift_hold_p_tap});
- press_key(7, 0);
// Tapping keys does nothing on press
+ key_shift_hold_p_tap.press();
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
run_one_scan_loop();
- release_key(7, 0);
+ key_shift_hold_p_tap.release();
+
// First we get the key press
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
// Then the release
@@ -67,19 +88,20 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) {
run_one_scan_loop();
// This sends KC_P, even if it should do nothing
- press_key(7, 0);
+ key_shift_hold_p_tap.press();
// This test should not succed if everything works correctly
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
run_one_scan_loop();
- release_key(7, 0);
+
+ key_shift_hold_p_tap.release();
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
idle_for(TAPPING_TERM + 1);
// On the other hand, nothing is sent if we are outside the tapping term
- press_key(7, 0);
+ key_shift_hold_p_tap.press();
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
run_one_scan_loop();
- release_key(7, 0);
+ key_shift_hold_p_tap.release();
// First we get the key press
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
@@ -90,8 +112,12 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) {
// Now we are geting into strange territory, as the hold registers too early here
// But the stranges part is:
// If TAPPING_TERM + 1 above is changed to TAPPING_TERM or TAPPING_TERM + 2 it doesn't
- press_key(7, 0);
+ key_shift_hold_p_tap.press();
// Shouldn't be called here really
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(1);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).Times(1);
idle_for(TAPPING_TERM);
-}
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ key_shift_hold_p_tap.release();
+ run_one_scan_loop();
+} \ No newline at end of file
diff --git a/tests/tap_hold_configurations/default_mod_tap/config.h b/tests/tap_hold_configurations/default_mod_tap/config.h
new file mode 100644
index 0000000000..5955b8600a
--- /dev/null
+++ b/tests/tap_hold_configurations/default_mod_tap/config.h
@@ -0,0 +1,21 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "test_common.h"
+
+#define IGNORE_MOD_TAP_INTERRUPT \ No newline at end of file
diff --git a/tests/tap_hold_configurations/default_mod_tap/test.mk b/tests/tap_hold_configurations/default_mod_tap/test.mk
new file mode 100644
index 0000000000..cfab996e0e
--- /dev/null
+++ b/tests/tap_hold_configurations/default_mod_tap/test.mk
@@ -0,0 +1,18 @@
+# Copyright 2021 Stefan Kerkmann
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# -------------------------------------------------------------------------------- \ No newline at end of file
diff --git a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp
new file mode 100644
index 0000000000..90befcdffd
--- /dev/null
+++ b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp
@@ -0,0 +1,230 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_fixture.hpp"
+#include "test_keymap_key.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class DefaultTapHold : public TestFixture {};
+
+TEST_F(DefaultTapHold, tap_regular_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ /* Press mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P, KC_A)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Idle for tapping term of mod tap hold key. */
+ idle_for(TAPPING_TERM - 3);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(DefaultTapHold, tap_mod_tap_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
+
+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
+
+ /* Press first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ first_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press second tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ second_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release second tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ second_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P, KC_A)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ first_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(DefaultTapHold, tap_regular_key_while_layer_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto layer_tap_hold_key = KeymapKey(0, 1, 0, LT(1, KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+ auto layer_key = KeymapKey(1, 2, 0, KC_B);
+
+ set_keymap({layer_tap_hold_key, regular_key, layer_key});
+
+ /* Press layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ layer_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(_));
+ layer_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(DefaultTapHold, tap_mod_tap_hold_key_two_times) {
+ GTEST_SKIP() << "TODO:Holding a modtap key results in out of bounds access to the keymap, this is a bug in QMK.";
+
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+
+ set_keymap({mod_tap_hold_key});
+
+ /* Press mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press mod-tap-hold key again. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ mod_tap_hold_key.press();
+ idle_for(TAPPING_TERM);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(DefaultTapHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) {
+ GTEST_SKIP() << "TODO:Holding a modtap key results in out of bounds access to the keymap, this is a bug in QMK.";
+
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+
+ set_keymap({mod_tap_hold_key});
+
+ /* Press mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press mod-tap-hold key again. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ mod_tap_hold_key.press();
+ idle_for(TAPPING_TERM);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(DefaultTapHold, tap_and_hold_mod_tap_hold_key) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+
+ set_keymap({mod_tap_hold_key});
+
+ /* Press mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
+ mod_tap_hold_key.press();
+ idle_for(TAPPING_TERM + 1);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+} \ No newline at end of file
diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h
new file mode 100644
index 0000000000..5955b8600a
--- /dev/null
+++ b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h
@@ -0,0 +1,21 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "test_common.h"
+
+#define IGNORE_MOD_TAP_INTERRUPT \ No newline at end of file
diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk
new file mode 100644
index 0000000000..efecca2c22
--- /dev/null
+++ b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk
@@ -0,0 +1,18 @@
+# Copyright 2021 Stefan Kerkmann
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp
new file mode 100644
index 0000000000..1702d604d3
--- /dev/null
+++ b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp
@@ -0,0 +1,136 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_fixture.hpp"
+#include "test_keymap_key.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class IgnoreModTapInterrupt : public TestFixture {};
+
+TEST_F(IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ /* Press mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
+
+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
+
+ /* Press first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ first_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press second tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ second_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release second tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ second_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ first_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(IgnoreModTapInterrupt, tap_regular_key_while_layer_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto layer_tap_hold_key = KeymapKey(0, 1, 0, LT(1, KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+ auto layer_key = KeymapKey(1, 2, 0, KC_B);
+
+ set_keymap({layer_tap_hold_key, regular_key, layer_key});
+
+ /* Press layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ layer_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P, regular_key.report_code)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ layer_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
diff --git a/tests/tap_hold_configurations/permissive_hold/config.h b/tests/tap_hold_configurations/permissive_hold/config.h
new file mode 100644
index 0000000000..2d5a9849e7
--- /dev/null
+++ b/tests/tap_hold_configurations/permissive_hold/config.h
@@ -0,0 +1,21 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "test_common.h"
+
+#define PERMISSIVE_HOLD \ No newline at end of file
diff --git a/tests/tap_hold_configurations/permissive_hold/test.mk b/tests/tap_hold_configurations/permissive_hold/test.mk
new file mode 100644
index 0000000000..efecca2c22
--- /dev/null
+++ b/tests/tap_hold_configurations/permissive_hold/test.mk
@@ -0,0 +1,18 @@
+# Copyright 2021 Stefan Kerkmann
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
diff --git a/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp b/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp
new file mode 100644
index 0000000000..aa71ec397f
--- /dev/null
+++ b/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp
@@ -0,0 +1,76 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "action_util.h"
+#include "keyboard_report_util.hpp"
+#include "test_common.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class OneShot : public TestFixture {};
+class OneShotParametrizedTestFixture : public ::testing::WithParamInterface<std::pair<KeymapKey, KeymapKey>>, public OneShot {};
+
+TEST_P(OneShotParametrizedTestFixture, OSMAsRegularModifierWithAdditionalKeypress) {
+ TestDriver driver;
+ KeymapKey osm_key = GetParam().first;
+ KeymapKey regular_key = GetParam().second;
+
+ set_keymap({osm_key, regular_key});
+
+ /* Press OSM */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ osm_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code))).Times(2);
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code, osm_key.report_code))).Times(1);
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release OSM */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ osm_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+// clang-format off
+
+INSTANTIATE_TEST_CASE_P(
+ OneShotModifierTests,
+ OneShotParametrizedTestFixture,
+ ::testing::Values(
+ /* first is osm key, second is regular key. */
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LCTL), KC_LCTL}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LALT), KC_LALT}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LGUI), KC_LGUI}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RCTL), KC_RCTL}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RSFT), KC_RSFT}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RALT), KC_RALT}, KeymapKey{0, 1, 1, KC_A}),
+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RGUI), KC_RGUI}, KeymapKey{0, 1, 1, KC_A})
+ ));
+// clang-format on \ No newline at end of file
diff --git a/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp
new file mode 100644
index 0000000000..ab9dd1518b
--- /dev/null
+++ b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp
@@ -0,0 +1,132 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_fixture.hpp"
+#include "test_keymap_key.hpp"
+
+using testing::_;
+using testing::InSequence;
+class PermissiveHold : public TestFixture {};
+
+TEST_F(PermissiveHold, tap_regular_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ /* Press mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT, regular_key.report_code)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(PermissiveHold, tap_mod_tap_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
+
+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
+
+ /* Press first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ first_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press second mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ second_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release second mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT, second_mod_tap_hold_key.report_code)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
+ second_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ first_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(PermissiveHold, tap_regular_key_while_layer_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto layer_tap_hold_key = KeymapKey(0, 1, 0, LT(1, KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+ auto layer_key = KeymapKey(1, 2, 0, KC_B);
+
+ set_keymap({layer_tap_hold_key, regular_key, layer_key});
+
+ /* Press layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ layer_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(layer_key.report_code)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ layer_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+} \ No newline at end of file
diff --git a/quantum/visualizer/resources/resources.h b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h
index 5178fbe55a..a6abd50bbe 100644
--- a/quantum/visualizer/resources/resources.h
+++ b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h
@@ -1,4 +1,4 @@
-/* Copyright 2017 Fred Sundvik
+/* Copyright 2021 Stefan Kerkmann
*
* 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
@@ -16,8 +16,7 @@
#pragma once
-#include <stdint.h>
+#include "test_common.h"
-#ifdef LCD_ENABLE
-extern const uint8_t resource_lcd_logo[];
-#endif
+#define IGNORE_MOD_TAP_INTERRUPT
+#define PERMISSIVE_HOLD \ No newline at end of file
diff --git a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk
new file mode 100644
index 0000000000..efecca2c22
--- /dev/null
+++ b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk
@@ -0,0 +1,18 @@
+# Copyright 2021 Stefan Kerkmann
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
diff --git a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp
new file mode 100644
index 0000000000..67f394653f
--- /dev/null
+++ b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp
@@ -0,0 +1,134 @@
+
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_fixture.hpp"
+#include "test_keymap_key.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class PermissiveHold_IgnoreModTapInterrupt : public TestFixture {};
+
+TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ /* Press mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
+
+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
+
+ /* Press first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ first_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press second tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ second_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release second tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ second_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ first_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_layer_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto layer_tap_hold_key = KeymapKey(0, 1, 0, LT(1, KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+ auto layer_key = KeymapKey(1, 2, 0, KC_B);
+
+ set_keymap({layer_tap_hold_key, regular_key, layer_key});
+
+ /* Press layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ layer_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ layer_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+} \ No newline at end of file
diff --git a/tests/tap_hold_configurations/retro_tapping/config.h b/tests/tap_hold_configurations/retro_tapping/config.h
new file mode 100644
index 0000000000..4b38f2644b
--- /dev/null
+++ b/tests/tap_hold_configurations/retro_tapping/config.h
@@ -0,0 +1,21 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "test_common.h"
+
+#define RETRO_TAPPING \ No newline at end of file
diff --git a/tests/tap_hold_configurations/retro_tapping/test.mk b/tests/tap_hold_configurations/retro_tapping/test.mk
new file mode 100644
index 0000000000..efecca2c22
--- /dev/null
+++ b/tests/tap_hold_configurations/retro_tapping/test.mk
@@ -0,0 +1,18 @@
+# Copyright 2021 Stefan Kerkmann
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
diff --git a/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp
new file mode 100644
index 0000000000..59ae77f781
--- /dev/null
+++ b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp
@@ -0,0 +1,52 @@
+
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_fixture.hpp"
+#include "test_keymap_key.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class RetroTapping : public TestFixture {};
+
+TEST_F(RetroTapping, tap_and_hold_mod_tap_hold_key) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+
+ set_keymap({mod_tap_hold_key});
+
+ /* Press mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ idle_for(TAPPING_TERM);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ /* TODO: Why is LSHIFT send at all? */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+} \ No newline at end of file
diff --git a/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp b/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp
new file mode 100644
index 0000000000..cf23df8317
--- /dev/null
+++ b/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp
@@ -0,0 +1,112 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_keymap_key.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class Tapping : public TestFixture {};
+
+TEST_F(Tapping, HoldA_SHFT_T_KeyReportsShift) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 7, 0, SFT_T(KC_P));
+
+ set_keymap({mod_tap_hold_key});
+
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ idle_for(TAPPING_TERM);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) {
+ TestDriver driver;
+ InSequence s;
+ auto key_shift_hold_p_tap = KeymapKey(0, 7, 0, SFT_T(KC_P));
+
+ set_keymap({key_shift_hold_p_tap});
+
+ /* Press mod_tap_hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ key_shift_hold_p_tap.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod_tap_hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ key_shift_hold_p_tap.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press mod_tap_hold key again */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ key_shift_hold_p_tap.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod_tap_hold key again */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ key_shift_hold_p_tap.release();
+ idle_for(TAPPING_TERM + 1);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press mod_tap_hold key again */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ key_shift_hold_p_tap.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod_tap_hold key again */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ key_shift_hold_p_tap.release();
+ idle_for(TAPPING_TERM + 1);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press mod_tap_hold key again */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ key_shift_hold_p_tap.press();
+ idle_for(TAPPING_TERM);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod_tap_hold key again */
+ /* TODO: Why is KC_LSFT send? */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ key_shift_hold_p_tap.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+} \ No newline at end of file
diff --git a/tests/tap_hold_configurations/tapping_force_hold/config.h b/tests/tap_hold_configurations/tapping_force_hold/config.h
new file mode 100644
index 0000000000..3b4646338a
--- /dev/null
+++ b/tests/tap_hold_configurations/tapping_force_hold/config.h
@@ -0,0 +1,21 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "test_common.h"
+
+#define TAPPING_FORCE_HOLD \ No newline at end of file
diff --git a/tests/tap_hold_configurations/tapping_force_hold/test.mk b/tests/tap_hold_configurations/tapping_force_hold/test.mk
new file mode 100644
index 0000000000..efecca2c22
--- /dev/null
+++ b/tests/tap_hold_configurations/tapping_force_hold/test.mk
@@ -0,0 +1,18 @@
+# Copyright 2021 Stefan Kerkmann
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
diff --git a/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp b/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp
new file mode 100644
index 0000000000..02416eed73
--- /dev/null
+++ b/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp
@@ -0,0 +1,81 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "test_common.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class ActionLayer : public TestFixture {};
+
+TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) {
+ TestDriver driver;
+ KeymapKey layer_key = KeymapKey{0, 0, 0, TT(1)};
+
+ /* These keys must have the same position in the matrix, only the layer is different. */
+ KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A};
+ set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}});
+
+ /* Tap TT five times . */
+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
+ /* TODO: Tapping Force Hold breaks TT */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(10);
+
+ layer_key.press();
+ run_one_scan_loop();
+ layer_key.release();
+ run_one_scan_loop();
+ expect_layer_state(0);
+
+ layer_key.press();
+ run_one_scan_loop();
+ layer_key.release();
+ run_one_scan_loop();
+ expect_layer_state(0);
+
+ layer_key.press();
+ run_one_scan_loop();
+ layer_key.release();
+ run_one_scan_loop();
+ expect_layer_state(0);
+
+ layer_key.press();
+ run_one_scan_loop();
+ layer_key.release();
+ run_one_scan_loop();
+ expect_layer_state(0);
+
+ layer_key.press();
+ run_one_scan_loop();
+ layer_key.release();
+ run_one_scan_loop();
+ expect_layer_state(0);
+
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A))).Times(1);
+ regular_key.press();
+ run_one_scan_loop();
+ expect_layer_state(0);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
+ regular_key.release();
+ run_one_scan_loop();
+ expect_layer_state(0);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+} \ No newline at end of file
diff --git a/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp
new file mode 100644
index 0000000000..cb68429617
--- /dev/null
+++ b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp
@@ -0,0 +1,215 @@
+
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_fixture.hpp"
+#include "test_keymap_key.hpp"
+
+using testing::_;
+using testing::InSequence;
+
+class TappingForceHold : public TestFixture {};
+
+TEST_F(TappingForceHold, tap_regular_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({mod_tap_hold_key, regular_key});
+
+ /* Press mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Idle for tapping term of mod tap hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ idle_for(TAPPING_TERM - 3);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(TappingForceHold, tap_mod_tap_key_while_mod_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
+
+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
+
+ /* Press first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ first_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press second tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ second_mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release second tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ second_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release first mod-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ first_mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Idle for tapping term of first mod tap hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ idle_for(TAPPING_TERM - 3);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(TappingForceHold, tap_regular_key_while_layer_tap_key_is_held) {
+ TestDriver driver;
+ InSequence s;
+ auto layer_tap_hold_key = KeymapKey(0, 1, 0, LT(1, KC_P));
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+ auto layer_key = KeymapKey(1, 2, 0, KC_B);
+
+ set_keymap({layer_tap_hold_key, regular_key, layer_key});
+
+ /* Press layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ layer_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release regular key */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ regular_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release layer-tap-hold key */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(_));
+ layer_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(TappingForceHold, tap_mod_tap_hold_key_two_times) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+
+ set_keymap({mod_tap_hold_key});
+
+ /* Press mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press mod-tap-hold key again. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
+
+TEST_F(TappingForceHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) {
+ TestDriver driver;
+ InSequence s;
+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
+
+ set_keymap({mod_tap_hold_key});
+
+ /* Press mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Press mod-tap-hold key again. */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ mod_tap_hold_key.press();
+ idle_for(TAPPING_TERM);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Release mod-tap-hold key. */
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
+ mod_tap_hold_key.release();
+ run_one_scan_loop();
+ testing::Mock::VerifyAndClearExpectations(&driver);
+}
diff --git a/tests/basic/rules.mk b/tests/test_common/build.mk
index 9fb5d43610..aeb3057854 100644
--- a/tests/basic/rules.mk
+++ b/tests/test_common/build.mk
@@ -1,4 +1,4 @@
-# Copyright 2017 Fred Sundvik
+# Copyright 2021 Stefan Kerkmann
#
# 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
@@ -13,4 +13,4 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-CUSTOM_MATRIX=yes
+CUSTOM_MATRIX=yes \ No newline at end of file
diff --git a/tests/test_common/keyboard_report_util.cpp b/tests/test_common/keyboard_report_util.cpp
index f73cf239e0..e148c76beb 100644
--- a/tests/test_common/keyboard_report_util.cpp
+++ b/tests/test_common/keyboard_report_util.cpp
@@ -44,16 +44,21 @@ bool operator==(const report_keyboard_t& lhs, const report_keyboard_t& rhs) {
return lhs.mods == rhs.mods && lhskeys == rhskeys;
}
-std::ostream& operator<<(std::ostream& stream, const report_keyboard_t& value) {
- stream << "Keyboard report:" << std::endl;
- stream << "Mods: " << (uint32_t)value.mods << std::endl;
- stream << "Keys: ";
+std::ostream& operator<<(std::ostream& stream, const report_keyboard_t& report) {
+ auto keys = get_keys(report);
+
// TODO: This should probably print friendly names for the keys
- for (uint32_t k : get_keys(value)) {
- stream << k << " ";
+ stream << "Keyboard Report: Mods (" << (uint32_t)report.mods << ") Keys (";
+
+ for (auto key = keys.cbegin(); key != keys.cend();) {
+ stream << +(*key);
+ key++;
+ if (key != keys.cend()) {
+ stream << ",";
+ }
}
- stream << std::endl;
- return stream;
+
+ return stream << ")" << std::endl;
}
KeyboardReportMatcher::KeyboardReportMatcher(const std::vector<uint8_t>& keys) {
diff --git a/tests/test_common/keymap.c b/tests/test_common/keymap.c
new file mode 100644
index 0000000000..fc3a56a007
--- /dev/null
+++ b/tests/test_common/keymap.c
@@ -0,0 +1,33 @@
+/* Copyright 2017 Fred Sundvik
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "quantum.h"
+
+// clang-format off
+
+const uint16_t PROGMEM
+ keymaps[][MATRIX_ROWS][MATRIX_COLS] =
+ {
+ [0] =
+ {
+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
+ },
+};
+
+// clang-format on
diff --git a/tests/test_common/test_common.h b/tests/test_common/test_common.h
new file mode 100644
index 0000000000..19ffcddcea
--- /dev/null
+++ b/tests/test_common/test_common.h
@@ -0,0 +1,4 @@
+#pragma once
+
+#define MATRIX_ROWS 4
+#define MATRIX_COLS 10 \ No newline at end of file
diff --git a/tests/test_common/test_driver.cpp b/tests/test_common/test_driver.cpp
index 84e249d838..2fa2b6a2e7 100644
--- a/tests/test_common/test_driver.cpp
+++ b/tests/test_common/test_driver.cpp
@@ -27,7 +27,10 @@ TestDriver::~TestDriver() { m_this = nullptr; }
uint8_t TestDriver::keyboard_leds(void) { return m_this->m_leds; }
-void TestDriver::send_keyboard(report_keyboard_t* report) { m_this->send_keyboard_mock(*report); }
+void TestDriver::send_keyboard(report_keyboard_t* report) {
+ test_logger.trace() << *report;
+ m_this->send_keyboard_mock(*report);
+}
void TestDriver::send_mouse(report_mouse_t* report) { m_this->send_mouse_mock(*report); }
diff --git a/tests/test_common/test_driver.hpp b/tests/test_common/test_driver.hpp
index f86308df95..f9197b3634 100644
--- a/tests/test_common/test_driver.hpp
+++ b/tests/test_common/test_driver.hpp
@@ -20,25 +20,26 @@
#include <stdint.h>
#include "host.h"
#include "keyboard_report_util.hpp"
-
+#include "test_logger.hpp"
class TestDriver {
-public:
+ public:
TestDriver();
~TestDriver();
void set_leds(uint8_t leds) { m_leds = leds; }
- MOCK_METHOD1(send_keyboard_mock, void (report_keyboard_t&));
- MOCK_METHOD1(send_mouse_mock, void (report_mouse_t&));
- MOCK_METHOD1(send_system_mock, void (uint16_t));
- MOCK_METHOD1(send_consumer_mock, void (uint16_t));
-private:
- static uint8_t keyboard_leds(void);
- static void send_keyboard(report_keyboard_t *report);
- static void send_mouse(report_mouse_t* report);
- static void send_system(uint16_t data);
- static void send_consumer(uint16_t data);
- host_driver_t m_driver;
- uint8_t m_leds = 0;
+ MOCK_METHOD1(send_keyboard_mock, void(report_keyboard_t&));
+ MOCK_METHOD1(send_mouse_mock, void(report_mouse_t&));
+ MOCK_METHOD1(send_system_mock, void(uint16_t));
+ MOCK_METHOD1(send_consumer_mock, void(uint16_t));
+
+ private:
+ static uint8_t keyboard_leds(void);
+ static void send_keyboard(report_keyboard_t* report);
+ static void send_mouse(report_mouse_t* report);
+ static void send_system(uint16_t data);
+ static void send_consumer(uint16_t data);
+ host_driver_t m_driver;
+ uint8_t m_leds = 0;
static TestDriver* m_this;
};
diff --git a/tests/test_common/test_fixture.cpp b/tests/test_common/test_fixture.cpp
index e041df7128..0601b17191 100644
--- a/tests/test_common/test_fixture.cpp
+++ b/tests/test_common/test_fixture.cpp
@@ -1,26 +1,48 @@
#include "test_fixture.hpp"
+#include <algorithm>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include "gmock/gmock-cardinalities.h"
#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
#include "test_driver.hpp"
+#include "test_logger.hpp"
#include "test_matrix.h"
-#include "keyboard.h"
-#include "action.h"
-#include "action_tapping.h"
+#include "test_keymap_key.hpp"
extern "C" {
+#include "action.h"
+#include "action_tapping.h"
+#include "action_util.h"
+#include "action_layer.h"
#include "debug.h"
#include "eeconfig.h"
-#include "action_layer.h"
+#include "keyboard.h"
+#include "keymap.h"
void set_time(uint32_t t);
void advance_time(uint32_t ms);
}
using testing::_;
-using testing::AnyNumber;
-using testing::Between;
-using testing::Return;
+
+/* This is used for dynamic dispatching keymap_key_to_keycode calls to the current active test_fixture. */
+TestFixture* TestFixture::m_this = nullptr;
+
+/* Override weak QMK function to allow the usage of isolated per-test keymaps in unit-tests.
+ * The actual call is dynamicaly dispatched to the current active test fixture, which in turn has it's own keymap. */
+extern "C" uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t position) {
+ uint16_t keycode;
+ TestFixture::m_this->get_keycode(layer, position, &keycode);
+ return keycode;
+}
void TestFixture::SetUpTestCase() {
+ test_logger.info() << "TestFixture setup-up start." << std::endl;
+
// The following is enough to bootstrap the values set in main
eeconfig_init_quantum();
eeconfig_update_debug(debug_config.raw);
@@ -28,23 +50,99 @@ void TestFixture::SetUpTestCase() {
TestDriver driver;
EXPECT_CALL(driver, send_keyboard_mock(_));
keyboard_init();
+
+ test_logger.info() << "TestFixture setup-up end." << std::endl;
}
void TestFixture::TearDownTestCase() {}
-TestFixture::TestFixture() {}
+TestFixture::TestFixture() { m_this = this; }
TestFixture::~TestFixture() {
+ test_logger.info() << "TestFixture clean-up start." << std::endl;
TestDriver driver;
- // Run for a while to make sure all keys are completely released
- EXPECT_CALL(driver, send_keyboard_mock(_)).Times(AnyNumber());
- layer_clear();
+
+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(2);
+
+ /* Reset keyboard state. */
clear_all_keys();
- idle_for(TAPPING_TERM + 10);
+
+ clear_keyboard();
+
+ clear_oneshot_mods();
+ clear_oneshot_locked_mods();
+ reset_oneshot_layer();
+
+ layer_clear();
+
+#if defined(SWAP_HANDS_ENABLE)
+ clear_oneshot_swaphands();
+#endif
+
+ idle_for(TAPPING_TERM * 10);
+ testing::Mock::VerifyAndClearExpectations(&driver);
+
+ /* Verify that the matrix really is cleared */
+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
+ idle_for(TAPPING_TERM * 10);
testing::Mock::VerifyAndClearExpectations(&driver);
- // Verify that the matrix really is cleared
- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0);
- idle_for(TAPPING_TERM + 10);
+
+ m_this = nullptr;
+
+ test_logger.info() << "TestFixture clean-up end." << std::endl;
+
+ print_test_log();
+}
+
+void TestFixture::add_key(KeymapKey key) {
+ if (this->find_key(key.layer, key.position)) {
+ FAIL() << "Key is already mapped for layer " << +key.layer << " and (column,row) (" << +key.position.col << "," << +key.position.row << ")";
+ }
+
+ this->keymap.push_back(key);
+}
+
+void TestFixture::set_keymap(std::initializer_list<KeymapKey> keys) {
+ this->keymap.clear();
+ for (auto& key : keys) {
+ add_key(key);
+ }
+}
+
+const KeymapKey* TestFixture::find_key(layer_t layer, keypos_t position) const {
+ auto keymap_key_predicate = [&](KeymapKey candidate) { return candidate.layer == layer && candidate.position.col == position.col && candidate.position.row == position.row; };
+
+ auto result = std::find_if(this->keymap.begin(), this->keymap.end(), keymap_key_predicate);
+
+ if (result != std::end(this->keymap)) {
+ return &(*result);
+ }
+ return nullptr;
+}
+
+void TestFixture::get_keycode(const layer_t layer, const keypos_t position, uint16_t* result) const {
+ bool key_is_out_of_bounds = position.col >= MATRIX_COLS && position.row >= MATRIX_ROWS;
+
+ if (key_is_out_of_bounds) {
+ /* See if this is done in hardware as well, because this is 100% out of bounds reads on all QMK keebs out there. */
+ auto msg = [&]() {
+ std::stringstream msg;
+ msg << "Keycode for position (" << +position.col << "," << +position.row << ") requested! This is out of bounds." << std::endl;
+ return msg.str();
+ }();
+
+ *result = KC_NO;
+ test_logger.error() << msg;
+ EXPECT_FALSE(key_is_out_of_bounds) << msg;
+ return;
+ }
+
+ if (auto key = this->find_key(layer, position)) {
+ *result = key->code;
+ return;
+ }
+
+ FAIL() << "No key is mapped for layer " << +layer << " and (column,row) " << +position.col << "," << +position.row << ")";
}
void TestFixture::run_one_scan_loop() {
@@ -57,3 +155,17 @@ void TestFixture::idle_for(unsigned time) {
run_one_scan_loop();
}
}
+
+void TestFixture::print_test_log() const {
+ const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info();
+ if (HasFailure()) {
+ std::cerr << test_info->test_case_name() << "." << test_info->name() << " failed!" << std::endl;
+ test_logger.print_log();
+ }
+ test_logger.reset();
+}
+
+void TestFixture::expect_layer_state(layer_t layer_state) const {
+ test_logger.trace() << "Layer state: (" << +layer_state << ") Highest layer bit: (" << +get_highest_layer(layer_state) << ")" << std::endl;
+ EXPECT_TRUE(layer_state_is(layer_state));
+}
diff --git a/tests/test_common/test_fixture.hpp b/tests/test_common/test_fixture.hpp
index 340503665b..73b5d8d3e8 100644
--- a/tests/test_common/test_fixture.hpp
+++ b/tests/test_common/test_fixture.hpp
@@ -16,15 +16,34 @@
#pragma once
+#include <cstdint>
+#include <unordered_map>
+#include <optional>
#include "gtest/gtest.h"
+#include "keyboard.h"
+#include "test_keymap_key.hpp"
class TestFixture : public testing::Test {
-public:
+ public:
+ static TestFixture* m_this;
+
TestFixture();
~TestFixture();
static void SetUpTestCase();
static void TearDownTestCase();
+ void set_keymap(std::initializer_list<KeymapKey> keycodes);
+ void add_key(const KeymapKey key);
+
+ const KeymapKey* find_key(const layer_t layer_t, const keypos_t position) const;
+ void get_keycode(const layer_t layer, const keypos_t position, uint16_t* result) const;
+
void run_one_scan_loop();
void idle_for(unsigned ms);
+
+ void expect_layer_state(layer_t layer) const;
+
+ protected:
+ void print_test_log() const;
+ std::vector<KeymapKey> keymap;
};
diff --git a/data/templates/base/keyboard.h b/tests/test_common/test_keymap_key.cpp
index bd2e88d12b..878ae097bf 100644
--- a/data/templates/base/keyboard.h
+++ b/tests/test_common/test_keymap_key.cpp
@@ -1,4 +1,4 @@
-/* Copyright %YEAR% %YOUR_NAME%
+/* Copyright 2021 Stefan Kerkmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,22 +14,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#pragma once
+#include "test_keymap_key.hpp"
+#include "test_logger.hpp"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest.h"
-#include "quantum.h"
-
-/* This is a shortcut to help you visually see your layout.
- *
- * The first section contains all of the arguments representing the physical
- * layout of the board and position of the keys.
- *
- * The second converts the arguments into a two-dimensional array which
- * represents the switch matrix.
- */
-#define LAYOUT( \
- k00, k01, k02, \
- k10, k12 \
-) { \
- { k00, k01, k02 }, \
- { k10, KC_NO, k12 } \
+void KeymapKey::press() {
+ test_logger.trace() << "Key pressed: (" << +this->position.col << "," << +this->position.row << ")" << std::endl;
+ press_key(this->position.col, this->position.row);
}
+
+void KeymapKey::release() {
+ test_logger.trace() << "Key released: (" << +this->position.col << "," << +this->position.row << ")" << std::endl;
+ release_key(this->position.col, this->position.row);
+} \ No newline at end of file
diff --git a/tests/test_common/test_keymap_key.hpp b/tests/test_common/test_keymap_key.hpp
new file mode 100644
index 0000000000..7861cb4a32
--- /dev/null
+++ b/tests/test_common/test_keymap_key.hpp
@@ -0,0 +1,46 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+extern "C" {
+#include "keyboard.h"
+#include "test_matrix.h"
+}
+
+#include <cassert>
+
+typedef uint8_t layer_t;
+
+struct KeymapKey {
+ KeymapKey(layer_t layer, uint8_t col, uint8_t row, uint16_t keycode) : layer(layer), position({.col = col, .row = row}), code(keycode), report_code(keycode) { validate(); }
+ KeymapKey(layer_t layer, uint8_t col, uint8_t row, uint16_t keycode, uint16_t report_code) : layer(layer), position({.col = col, .row = row}), code(keycode), report_code(report_code) { validate(); }
+
+ void press();
+ void release();
+
+ const layer_t layer;
+ const keypos_t position;
+ const uint16_t code;
+ /* Sometimes the keycode does not match the code that is send in the usb report, so we provide it here. */
+ const uint16_t report_code;
+
+ private:
+ void validate() {
+ assert(position.col <= MATRIX_COLS);
+ assert(position.row <= MATRIX_ROWS);
+ }
+}; \ No newline at end of file
diff --git a/tests/test_common/test_logger.cpp b/tests/test_common/test_logger.cpp
new file mode 100644
index 0000000000..959fdde5ec
--- /dev/null
+++ b/tests/test_common/test_logger.cpp
@@ -0,0 +1,39 @@
+/* Copyright 2021 Stefan Kerkmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <iostream>
+#include "test_logger.hpp"
+
+TestLogger test_logger;
+
+TestLogger& TestLogger::info() {
+ *this << "[ INFO ] ";
+ return *this;
+}
+
+TestLogger& TestLogger::trace() {
+ *this << "[ TRACE ] ";
+ return *this;
+}
+
+TestLogger& TestLogger::error() {
+ *this << "[ ERROR ] ";
+ return *this;
+}
+
+void TestLogger::reset() { this->m_log.str(""); };
+
+void TestLogger::print_log() { std::cerr << this->m_log.str(); }
diff --git a/quantum/visualizer/visualizer_keyframes.h b/tests/test_common/test_logger.hpp
index c92ff16113..348af7fab8 100644
--- a/quantum/visualizer/visualizer_keyframes.h
+++ b/tests/test_common/test_logger.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2017 Fred Sundvik
+/* Copyright 2021 Stefan Kerkmann
*
* 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
@@ -16,8 +16,20 @@
#pragma once
-#include "visualizer.h"
+#include <ostream>
+#include <sstream>
-// Some predefined keyframe functions that can be used by the user code
-// Does nothing, useful for adding delays
-bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state);
+class TestLogger : public std::ostream {
+ public:
+ TestLogger() : std::ostream(&m_log){};
+ TestLogger& info();
+ TestLogger& trace();
+ TestLogger& error();
+ void print_log();
+ void reset();
+
+ private:
+ std::stringbuf m_log;
+};
+
+extern TestLogger test_logger; \ No newline at end of file
diff --git a/tmk_core/common.mk b/tmk_core/common.mk
deleted file mode 100644
index b7b7db207a..0000000000
--- a/tmk_core/common.mk
+++ /dev/null
@@ -1,144 +0,0 @@
-PRINTF_PATH = $(LIB_PATH)/printf
-
-COMMON_DIR = common
-PLATFORM_COMMON_DIR = $(COMMON_DIR)/$(PLATFORM_KEY)
-
-TMK_COMMON_SRC += \
- $(COMMON_DIR)/host.c \
- $(COMMON_DIR)/report.c \
- $(COMMON_DIR)/sync_timer.c \
- $(COMMON_DIR)/usb_util.c \
- $(PLATFORM_COMMON_DIR)/platform.c \
- $(PLATFORM_COMMON_DIR)/suspend.c \
- $(PLATFORM_COMMON_DIR)/timer.c \
- $(PLATFORM_COMMON_DIR)/bootloader.c \
-
-# Use platform provided print if it exists
--include $(TMK_PATH)/$(PLATFORM_COMMON_DIR)/printf.mk
-
-SHARED_EP_ENABLE = no
-MOUSE_SHARED_EP ?= yes
-ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes)
- TMK_COMMON_DEFS += -DKEYBOARD_SHARED_EP
- SHARED_EP_ENABLE = yes
- # With the current usb_descriptor.c code,
- # you can't share kbd without sharing mouse;
- # that would be a very unexpected use case anyway
- MOUSE_SHARED_EP = yes
-endif
-
-ifeq ($(strip $(MOUSE_ENABLE)), yes)
- OPT_DEFS += -DMOUSE_ENABLE
- ifeq ($(strip $(MOUSE_SHARED_EP)), yes)
- TMK_COMMON_DEFS += -DMOUSE_SHARED_EP
- SHARED_EP_ENABLE = yes
- endif
-endif
-
-ifeq ($(strip $(EXTRAKEY_ENABLE)), yes)
- TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE
- SHARED_EP_ENABLE = yes
-endif
-
-ifeq ($(strip $(RAW_ENABLE)), yes)
- TMK_COMMON_DEFS += -DRAW_ENABLE
-endif
-
-ifeq ($(strip $(WEBUSB_ENABLE)), yes)
- TMK_COMMON_SRC += $(TMK_DIR)/common/webusb.c
- TMK_COMMON_DEFS += -DWEBUSB_ENABLE
-endif
-
-ifeq ($(strip $(CONSOLE_ENABLE)), yes)
- TMK_COMMON_DEFS += -DCONSOLE_ENABLE
-else
- # TODO: decouple this so other print backends can exist
- TMK_COMMON_DEFS += -DNO_PRINT
- TMK_COMMON_DEFS += -DNO_DEBUG
-endif
-
-ifeq ($(strip $(NKRO_ENABLE)), yes)
- ifeq ($(PROTOCOL), VUSB)
- $(info NKRO is not currently supported on V-USB, and has been disabled.)
- else ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
- $(info NKRO is not currently supported with Bluetooth, and has been disabled.)
- else ifneq ($(BLUETOOTH),)
- $(info NKRO is not currently supported with Bluetooth, and has been disabled.)
- else
- TMK_COMMON_DEFS += -DNKRO_ENABLE
- SHARED_EP_ENABLE = yes
- endif
-endif
-
-ifeq ($(strip $(RING_BUFFERED_6KRO_REPORT_ENABLE)), yes)
- TMK_COMMON_DEFS += -DRING_BUFFERED_6KRO_REPORT_ENABLE
-endif
-
-ifeq ($(strip $(SLEEP_LED_ENABLE)), yes)
- TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/sleep_led.c
- TMK_COMMON_DEFS += -DSLEEP_LED_ENABLE
- TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN
-endif
-
-ifeq ($(strip $(NO_SUSPEND_POWER_DOWN)), yes)
- TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN
-endif
-
-ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
- TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE
- TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
-endif
-
-ifeq ($(strip $(BLUETOOTH)), AdafruitBLE)
- TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE
- TMK_COMMON_DEFS += -DMODULE_ADAFRUIT_BLE
- TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
-endif
-
-ifeq ($(strip $(BLUETOOTH)), RN42)
- TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE
- TMK_COMMON_DEFS += -DMODULE_RN42
- TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
-endif
-
-ifeq ($(strip $(SWAP_HANDS_ENABLE)), yes)
- TMK_COMMON_DEFS += -DSWAP_HANDS_ENABLE
-endif
-
-ifeq ($(strip $(NO_USB_STARTUP_CHECK)), yes)
- TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
-endif
-
-ifeq ($(strip $(DIGITIZER_SHARED_EP)), yes)
- TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP
- SHARED_EP_ENABLE = yes
-endif
-
-ifeq ($(strip $(DIGITIZER_ENABLE)), yes)
- TMK_COMMON_DEFS += -DDIGITIZER_ENABLE
- ifeq ($(strip $(SHARED_EP_ENABLE)), yes)
- TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP
- SHARED_EP_ENABLE = yes
- endif
-endif
-
-ifeq ($(strip $(SHARED_EP_ENABLE)), yes)
- TMK_COMMON_DEFS += -DSHARED_EP_ENABLE
-endif
-
-ifeq ($(strip $(LTO_ENABLE)), yes)
- ifeq ($(PLATFORM),CHIBIOS)
- $(info Enabling LTO on ChibiOS-targeting boards is known to have a high likelihood of failure.)
- $(info If unsure, set LTO_ENABLE = no.)
- endif
- EXTRAFLAGS += -flto
- TMK_COMMON_DEFS += -DLTO_ENABLE
- TMK_COMMON_DEFS += -DLINK_TIME_OPTIMIZATON_ENABLE
-else ifdef LINK_TIME_OPTIMIZATION_ENABLE
- $(error The LINK_TIME_OPTIMIZATION_ENABLE flag has been renamed to LTO_ENABLE.)
-endif
-
-# Search Path
-VPATH += $(TMK_PATH)/$(COMMON_DIR)
-VPATH += $(TMK_PATH)/$(PLATFORM_COMMON_DIR)
-VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)
diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h
deleted file mode 100644
index 23c65f9428..0000000000
--- a/tmk_core/common/chibios/chibios_config.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright 2019
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#ifndef USB_VBUS_PIN
-# define SPLIT_USB_DETECT // Force this on when dedicated pin is not used
-#endif
-
-#if defined(STM32F1XX)
-# define USE_GPIOV1
-#endif
-
-#if defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32L1XX)
-# define USE_I2CV1
-#endif
-
-// teensy
-#if defined(K20x) || defined(KL2x)
-# define USE_I2CV1
-# define USE_I2CV1_CONTRIB // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed
-# define USE_GPIOV1
-# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY
-#endif
-
-#if defined(MK66F18)
-# define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY
-#endif
diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c
deleted file mode 100644
index 38517e06f0..0000000000
--- a/tmk_core/common/chibios/suspend.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* TODO */
-
-#include <ch.h>
-#include <hal.h>
-
-#include "matrix.h"
-#include "action.h"
-#include "action_util.h"
-#include "mousekey.h"
-#include "host.h"
-#include "suspend.h"
-#include "led.h"
-#include "wait.h"
-
-#ifdef AUDIO_ENABLE
-# include "audio.h"
-#endif /* AUDIO_ENABLE */
-
-#ifdef BACKLIGHT_ENABLE
-# include "backlight.h"
-#endif
-
-#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
-# include "rgblight.h"
-#endif
-
-#ifdef LED_MATRIX_ENABLE
-# include "led_matrix.h"
-#endif
-#ifdef RGB_MATRIX_ENABLE
-# include "rgb_matrix.h"
-#endif
-
-/** \brief suspend idle
- *
- * FIXME: needs doc
- */
-void suspend_idle(uint8_t time) {
- // TODO: this is not used anywhere - what units is 'time' in?
- wait_ms(time);
-}
-
-/** \brief Run keyboard level Power down
- *
- * FIXME: needs doc
- */
-__attribute__((weak)) void suspend_power_down_user(void) {}
-/** \brief Run keyboard level Power down
- *
- * FIXME: needs doc
- */
-__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
-
-/** \brief suspend power down
- *
- * FIXME: needs doc
- */
-void suspend_power_down(void) {
-#ifdef BACKLIGHT_ENABLE
- backlight_set(0);
-#endif
-
-#ifdef LED_MATRIX_ENABLE
- led_matrix_task();
-#endif
-#ifdef RGB_MATRIX_ENABLE
- rgb_matrix_task();
-#endif
-
- // Turn off LED indicators
- uint8_t leds_off = 0;
-#if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
- if (is_backlight_enabled()) {
- // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
- leds_off |= (1 << USB_LED_CAPS_LOCK);
- }
-#endif
- led_set(leds_off);
-
- // TODO: figure out what to power down and how
- // shouldn't power down TPM/FTM if we want a breathing LED
- // also shouldn't power down USB
-#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
- rgblight_suspend();
-#endif
-
-#if defined(LED_MATRIX_ENABLE)
- led_matrix_set_suspend_state(true);
-#endif
-#if defined(RGB_MATRIX_ENABLE)
- rgb_matrix_set_suspend_state(true);
-#endif
-#ifdef AUDIO_ENABLE
- stop_all_notes();
-#endif /* AUDIO_ENABLE */
-
- suspend_power_down_kb();
- // on AVR, this enables the watchdog for 15ms (max), and goes to
- // SLEEP_MODE_PWR_DOWN
-
- wait_ms(17);
-}
-
-/** \brief suspend wakeup condition
- *
- * FIXME: needs doc
- */
-__attribute__((weak)) void matrix_power_up(void) {}
-__attribute__((weak)) void matrix_power_down(void) {}
-bool suspend_wakeup_condition(void) {
- matrix_power_up();
- matrix_scan();
- matrix_power_down();
- for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
- if (matrix_get_row(r)) return true;
- }
- return false;
-}
-
-/** \brief run user level code immediately after wakeup
- *
- * FIXME: needs doc
- */
-__attribute__((weak)) void suspend_wakeup_init_user(void) {}
-
-/** \brief run keyboard level code immediately after wakeup
- *
- * FIXME: needs doc
- */
-__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
-
-/** \brief suspend wakeup condition
- *
- * run immediately after wakeup
- * FIXME: needs doc
- */
-void suspend_wakeup_init(void) {
- // clear keyboard state
- // need to do it manually, because we're running from ISR
- // and clear_keyboard() calls print
- // so only clear the variables in memory
- // the reports will be sent from main.c afterwards
- // or if the PC asks for GET_REPORT
- clear_mods();
- clear_weak_mods();
- clear_keys();
-#ifdef MOUSEKEY_ENABLE
- mousekey_clear();
-#endif /* MOUSEKEY_ENABLE */
-#ifdef EXTRAKEY_ENABLE
- host_system_send(0);
- host_consumer_send(0);
-#endif /* EXTRAKEY_ENABLE */
-#ifdef BACKLIGHT_ENABLE
- backlight_init();
-#endif /* BACKLIGHT_ENABLE */
- led_set(host_keyboard_leds());
-#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
- rgblight_wakeup();
-#endif
-
-#if defined(LED_MATRIX_ENABLE)
- led_matrix_set_suspend_state(false);
-#endif
-#if defined(RGB_MATRIX_ENABLE)
- rgb_matrix_set_suspend_state(false);
-#endif
- suspend_wakeup_init_kb();
-}
diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk
index b61f2f5463..31a6de76f1 100644
--- a/tmk_core/protocol.mk
+++ b/tmk_core/protocol.mk
@@ -1,57 +1,83 @@
-PROTOCOL_DIR = protocol
+TMK_COMMON_SRC += \
+ $(PROTOCOL_DIR)/host.c \
+ $(PROTOCOL_DIR)/report.c \
+ $(PROTOCOL_DIR)/usb_device_state.c \
+ $(PROTOCOL_DIR)/usb_util.c \
-ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes)
- SRC += $(PROTOCOL_DIR)/ps2_mouse.c
- OPT_DEFS += -DPS2_MOUSE_ENABLE
+SHARED_EP_ENABLE = no
+MOUSE_SHARED_EP ?= yes
+ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes)
+ TMK_COMMON_DEFS += -DKEYBOARD_SHARED_EP
+ SHARED_EP_ENABLE = yes
+ # With the current usb_descriptor.c code,
+ # you can't share kbd without sharing mouse;
+ # that would be a very unexpected use case anyway
+ MOUSE_SHARED_EP = yes
+endif
+
+ifeq ($(strip $(MOUSE_ENABLE)), yes)
OPT_DEFS += -DMOUSE_ENABLE
+ ifeq ($(strip $(MOUSE_SHARED_EP)), yes)
+ TMK_COMMON_DEFS += -DMOUSE_SHARED_EP
+ SHARED_EP_ENABLE = yes
+ endif
endif
-ifeq ($(strip $(PS2_USE_BUSYWAIT)), yes)
- SRC += protocol/ps2_busywait.c
- SRC += protocol/ps2_io_avr.c
- OPT_DEFS += -DPS2_USE_BUSYWAIT
+ifeq ($(strip $(EXTRAKEY_ENABLE)), yes)
+ TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE
+ SHARED_EP_ENABLE = yes
endif
-ifeq ($(strip $(PS2_USE_INT)), yes)
- SRC += protocol/ps2_interrupt.c
- SRC += protocol/ps2_io_$(PLATFORM_KEY).c
- OPT_DEFS += -DPS2_USE_INT
+ifeq ($(strip $(RAW_ENABLE)), yes)
+ TMK_COMMON_DEFS += -DRAW_ENABLE
endif
-ifeq ($(strip $(PS2_USE_USART)), yes)
- SRC += protocol/ps2_usart.c
- SRC += protocol/ps2_io_$(PLATFORM_KEY).c
- OPT_DEFS += -DPS2_USE_USART
+ifeq ($(strip $(CONSOLE_ENABLE)), yes)
+ TMK_COMMON_DEFS += -DCONSOLE_ENABLE
+else
+ # TODO: decouple this so other print backends can exist
+ TMK_COMMON_DEFS += -DNO_PRINT
+ TMK_COMMON_DEFS += -DNO_DEBUG
endif
+ifeq ($(strip $(NKRO_ENABLE)), yes)
+ ifeq ($(PROTOCOL), VUSB)
+ $(info NKRO is not currently supported on V-USB, and has been disabled.)
+ else ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
+ $(info NKRO is not currently supported with Bluetooth, and has been disabled.)
+ else
+ TMK_COMMON_DEFS += -DNKRO_ENABLE
+ SHARED_EP_ENABLE = yes
+ endif
+endif
-ifeq ($(strip $(SERIAL_MOUSE_MICROSOFT_ENABLE)), yes)
- SRC += $(PROTOCOL_DIR)/serial_mouse_microsoft.c
- OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MICROSOFT \
- -DMOUSE_ENABLE
+ifeq ($(strip $(RING_BUFFERED_6KRO_REPORT_ENABLE)), yes)
+ TMK_COMMON_DEFS += -DRING_BUFFERED_6KRO_REPORT_ENABLE
endif
-ifeq ($(strip $(SERIAL_MOUSE_MOUSESYSTEMS_ENABLE)), yes)
- SRC += $(PROTOCOL_DIR)/serial_mouse_mousesystems.c
- OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MOUSESYSTEMS \
- -DMOUSE_ENABLE
+ifeq ($(strip $(NO_SUSPEND_POWER_DOWN)), yes)
+ TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN
endif
-ifeq ($(strip $(SERIAL_MOUSE_USE_SOFT)), yes)
- SRC += $(PROTOCOL_DIR)/serial_soft.c
+ifeq ($(strip $(NO_USB_STARTUP_CHECK)), yes)
+ TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
endif
-ifeq ($(strip $(SERIAL_MOUSE_USE_UART)), yes)
- SRC += $(PROTOCOL_DIR)/serial_uart.c
+ifeq ($(strip $(DIGITIZER_SHARED_EP)), yes)
+ TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP
+ SHARED_EP_ENABLE = yes
endif
-ifeq ($(strip $(ADB_MOUSE_ENABLE)), yes)
- OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE
+ifeq ($(strip $(DIGITIZER_ENABLE)), yes)
+ TMK_COMMON_DEFS += -DDIGITIZER_ENABLE
+ ifeq ($(strip $(SHARED_EP_ENABLE)), yes)
+ TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP
+ SHARED_EP_ENABLE = yes
+ endif
endif
-ifeq ($(strip $(XT_ENABLE)), yes)
- SRC += $(PROTOCOL_DIR)/xt_interrupt.c
- OPT_DEFS += -DXT_ENABLE
+ifeq ($(strip $(SHARED_EP_ENABLE)), yes)
+ TMK_COMMON_DEFS += -DSHARED_EP_ENABLE
endif
ifeq ($(strip $(USB_HID_ENABLE)), yes)
diff --git a/tmk_core/protocol/adb.c b/tmk_core/protocol/adb.c
deleted file mode 100644
index 367f1b09fa..0000000000
--- a/tmk_core/protocol/adb.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
-Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
-Copyright 2013 Shay Green <gblargg@gmail.com>
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdbool.h>
-#include <util/delay.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include "adb.h"
-#include "print.h"
-
-// GCC doesn't inline functions normally
-#define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT))
-#define data_hi() (ADB_DDR &= ~(1 << ADB_DATA_BIT))
-#define data_in() (ADB_PIN & (1 << ADB_DATA_BIT))
-
-#ifdef ADB_PSW_BIT
-static inline void psw_lo(void);
-static inline void psw_hi(void);
-static inline bool psw_in(void);
-#endif
-
-static inline void attention(void);
-static inline void place_bit0(void);
-static inline void place_bit1(void);
-static inline void send_byte(uint8_t data);
-static inline uint16_t wait_data_lo(uint16_t us);
-static inline uint16_t wait_data_hi(uint16_t us);
-
-void adb_host_init(void) {
- ADB_PORT &= ~(1 << ADB_DATA_BIT);
- data_hi();
-#ifdef ADB_PSW_BIT
- psw_hi();
-#endif
-}
-
-#ifdef ADB_PSW_BIT
-bool adb_host_psw(void) { return psw_in(); }
-#endif
-
-/*
- * Don't call this in a row without the delay, otherwise it makes some of poor controllers
- * overloaded and misses strokes. Recommended interval is 12ms.
- *
- * Thanks a lot, blargg!
- * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919>
- * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139>
- */
-uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); }
-
-#ifdef ADB_MOUSE_ENABLE
-__attribute__((weak)) void adb_mouse_init(void) { return; }
-
-__attribute__((weak)) void adb_mouse_task(void) { return; }
-
-uint16_t adb_host_mouse_recv(void) { return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); }
-#endif
-
-// This sends Talk command to read data from register and returns length of the data.
-uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {
- for (int8_t i = 0; i < len; i++) buf[i] = 0;
-
- cli();
- attention();
- send_byte((addr << 4) | ADB_CMD_TALK | reg);
- place_bit0(); // Stopbit(0)
- // TODO: Service Request(Srq):
- // Device holds low part of comannd stopbit for 140-260us
- //
- // Command:
- // ......._ ______________________ ___ ............_ -------
- // | | | | | | |
- // Command | | | | | Data bytes | |
- // ........|___| | 140-260 |__| |_............|___|
- // |stop0 | Tlt Stop-to-Start |start1| |stop0 |
- //
- // Command without data:
- // ......._ __________________________
- // | |
- // Command | |
- // ........|___| | 140-260 |
- // |stop0 | Tlt Stop-to-Start |
- //
- // Service Request:
- // ......._ ______ ___ ............_ -------
- // | 140-260 | | | | | |
- // Command | Service Request | | | | Data bytes | |
- // ........|___________________| |__| |_............|___|
- // |stop0 | |start1| |stop0 |
- // ......._ __________
- // | 140-260 |
- // Command | Service Request |
- // ........|___________________|
- // |stop0 |
- // This can be happened?
- // ......._ ______________________ ___ ............_ -----
- // | | | | | | 140-260 |
- // Command | | | | | Data bytes | Service Request |
- // ........|___| | 140-260 |__| |_............|_________________|
- // |stop0 | Tlt Stop-to-Start |start1| |stop0 |
- //
- // "Service requests are issued by the devices during a very specific time at the
- // end of the reception of the command packet.
- // If a device in need of service issues a service request, it must do so within
- // the 65 µs of the Stop Bit’s low time and maintain the line low for a total of 300 µs."
- //
- // "A device sends a Service Request signal by holding the bus low during the low
- // portion of the stop bit of any command or data transaction. The device must lengthen
- // the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15."
- // http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf
- if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored
- xprintf("R");
- sei();
- return 0;
- }
- if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us)
- sei();
- return 0; // No data from device(not error);
- }
-
- // start bit(1)
- if (!wait_data_hi(40)) {
- xprintf("S");
- sei();
- return 0;
- }
- if (!wait_data_lo(100)) {
- xprintf("s");
- sei();
- return 0;
- }
-
- uint8_t n = 0; // bit count
- do {
- //
- // |<- bit_cell_max(130) ->|
- // | |<- lo ->|
- // | | |<-hi->|
- // _______
- // | | |
- // | 130-lo | lo-hi |
- // |________| |
- //
- uint8_t lo = (uint8_t)wait_data_hi(130);
- if (!lo) goto error; // no more bit or after stop bit
-
- uint8_t hi = (uint8_t)wait_data_lo(lo);
- if (!hi) goto error; // stop bit extedned by Srq?
-
- if (n / 8 >= len) continue; // can't store in buf
-
- buf[n / 8] <<= 1;
- if ((130 - lo) < (lo - hi)) {
- buf[n / 8] |= 1;
- }
- } while (++n);
-
-error:
- sei();
- return n / 8;
-}
-
-uint16_t adb_host_talk(uint8_t addr, uint8_t reg) {
- uint8_t len;
- uint8_t buf[8];
- len = adb_host_talk_buf(addr, reg, buf, 8);
- if (len != 2) return 0;
- return (buf[0] << 8 | buf[1]);
-}
-
-void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {
- cli();
- attention();
- send_byte((addr << 4) | ADB_CMD_LISTEN | reg);
- place_bit0(); // Stopbit(0)
- // TODO: Service Request
- _delay_us(200); // Tlt/Stop to Start
- place_bit1(); // Startbit(1)
- for (int8_t i = 0; i < len; i++) {
- send_byte(buf[i]);
- // xprintf("%02X ", buf[i]);
- }
- place_bit0(); // Stopbit(0);
- sei();
-}
-
-void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) {
- uint8_t buf[2] = {data_h, data_l};
- adb_host_listen_buf(addr, reg, buf, 2);
-}
-
-void adb_host_flush(uint8_t addr) {
- cli();
- attention();
- send_byte((addr << 4) | ADB_CMD_FLUSH);
- place_bit0(); // Stopbit(0)
- _delay_us(200); // Tlt/Stop to Start
- sei();
-}
-
-// send state of LEDs
-void adb_host_kbd_led(uint8_t led) {
- // Listen Register2
- // upper byte: not used
- // lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock
- adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_2, 0, led & 0x07);
-}
-
-#ifdef ADB_PSW_BIT
-static inline void psw_lo() {
- ADB_DDR |= (1 << ADB_PSW_BIT);
- ADB_PORT &= ~(1 << ADB_PSW_BIT);
-}
-static inline void psw_hi() {
- ADB_PORT |= (1 << ADB_PSW_BIT);
- ADB_DDR &= ~(1 << ADB_PSW_BIT);
-}
-static inline bool psw_in() {
- ADB_PORT |= (1 << ADB_PSW_BIT);
- ADB_DDR &= ~(1 << ADB_PSW_BIT);
- return ADB_PIN & (1 << ADB_PSW_BIT);
-}
-#endif
-
-static inline void attention(void) {
- data_lo();
- _delay_us(800 - 35); // bit1 holds lo for 35 more
- place_bit1();
-}
-
-static inline void place_bit0(void) {
- data_lo();
- _delay_us(65);
- data_hi();
- _delay_us(35);
-}
-
-static inline void place_bit1(void) {
- data_lo();
- _delay_us(35);
- data_hi();
- _delay_us(65);
-}
-
-static inline void send_byte(uint8_t data) {
- for (int i = 0; i < 8; i++) {
- if (data & (0x80 >> i))
- place_bit1();
- else
- place_bit0();
- }
-}
-
-// These are carefully coded to take 6 cycles of overhead.
-// inline asm approach became too convoluted
-static inline uint16_t wait_data_lo(uint16_t us) {
- do {
- if (!data_in()) break;
- _delay_us(1 - (6 * 1000000.0 / F_CPU));
- } while (--us);
- return us;
-}
-
-static inline uint16_t wait_data_hi(uint16_t us) {
- do {
- if (data_in()) break;
- _delay_us(1 - (6 * 1000000.0 / F_CPU));
- } while (--us);
- return us;
-}
-
-/*
-ADB Protocol
-============
-
-Resources
----------
-ADB - The Untold Story: Space Aliens Ate My Mouse
- http://developer.apple.com/legacy/mac/library/#technotes/hw/hw_01.html
-ADB Manager
- http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Devices/ADB_Manager.pdf
- Service request(5-17)
-Apple IIgs Hardware Reference Second Edition [Chapter6 p121]
- ftp://ftp.apple.asimov.net/pub/apple_II/documentation/Apple%20IIgs%20Hardware%20Reference.pdf
-ADB Keycode
- http://72.0.193.250/Documentation/macppc/adbkeycodes/
- http://m0115.web.fc2.com/m0115.jpg
- [Inside Macintosh volume V, pages 191-192]
- http://www.opensource.apple.com/source/IOHIDFamily/IOHIDFamily-421.18.3/IOHIDFamily/Cosmo_USB2ADB.c
-ADB Signaling
- http://kbdbabel.sourceforge.net/doc/kbd_signaling_pcxt_ps2_adb.pdf
-ADB Overview & History
- http://en.wikipedia.org/wiki/Apple_Desktop_Bus
-Microchip Application Note: ADB device(with code for PIC16C)
- http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011062
-AVR ATtiny2131 ADB to PS/2 converter(Japanese)
- http://hp.vector.co.jp/authors/VA000177/html/KeyBoardA5DEA5CBA5A2II.html
-
-
-Pinouts
--------
- ADB female socket from the front:
- __________
- | | <--- top
- | 4o o3 |
- |2o o1|
- | == |
- |________| <--- bottom
- | | <--- 4pins
-
-
- ADB female socket from bottom:
-
- ========== <--- front
- | |
- | |
- |2o o1|
- |4o o3|
- ---------- <--- back
-
- 1: Data
- 2: Power SW(low when press Power key)
- 3: Vcc(5V)
- 4: GND
-
-
-Commands
---------
- ADB command is 1byte and consists of 4bit-address, 2bit-command
- type and 2bit-register. The commands are always sent by Host.
-
- Command format:
- 7 6 5 4 3 2 1 0
- | | | |------------ address
- | |-------- command type
- | |---- register
-
- bits commands
- ------------------------------------------------------
- - - - - 0 0 0 0 Send Reset(reset all devices)
- A A A A 0 0 0 1 Flush(reset a device)
- - - - - 0 0 1 0 Reserved
- - - - - 0 0 1 1 Reserved
- - - - - 0 1 - - Reserved
- A A A A 1 0 R R Listen(write to a device)
- A A A A 1 1 R R Talk(read from a device)
-
- The command to read keycodes from keyboard is 0x2C which
- consist of keyboard address 2 and Talk against register 0.
-
- Address:
- 2: keyboard
- 3: mice
-
- Registers:
- 0: application(keyboard uses this to store its data.)
- 1: application
- 2: application(keyboard uses this for LEDs and state of modifiers)
- 3: status and command
-
-
-Communication
--------------
- This is a minimum information for keyboard communication.
- See "Resources" for detail.
-
- Signaling:
-
- ~~~~____________~~||||||||||||__~~~~~_~~|||||||||||||||__~~~~
-
- |800us | |7 Command 0| | | |15-64 Data 0|Stopbit(0)
- +Attention | | | +Startbit(1)
- +Startbit(1) | +Tlt(140-260us)
- +stopbit(0)
-
- Bit cells:
-
- bit0: ______~~~
- 65 :35us
-
- bit1: ___~~~~~~
- 35 :65us
-
- bit0 low time: 60-70% of bit cell(42-91us)
- bit1 low time: 30-40% of bit cell(21-52us)
- bit cell time: 70-130us
- [from Apple IIgs Hardware Reference Second Edition]
-
- Criterion for bit0/1:
- After 55us if line is low/high then bit is 0/1.
-
- Attention & start bit:
- Host asserts low in 560-1040us then places start bit(1).
-
- Tlt(Stop to Start):
- Bus stays high in 140-260us then device places start bit(1).
-
- Global reset:
- Host asserts low in 2.8-5.2ms. All devices are forced to reset.
-
- Service request from device(Srq):
- Device can request to send at commad(Global only?) stop bit.
- Requesting device keeps low for 140-260us at stop bit of command.
-
-
-Keyboard Data(Register0)
- This 16bit data can contains two keycodes and two released flags.
- First keycode is palced in upper byte. When one keyocode is sent,
- lower byte is 0xFF.
- Release flag is 1 when key is released.
-
- 1514 . . . . . 8 7 6 . . . . . 0
- | | | | | | | | | +-+-+-+-+-+-+- Keycode2
- | | | | | | | | +--------------- Released2(1 when the key is released)
- | +-+-+-+-+-+-+----------------- Keycode1
- +------------------------------- Released1(1 when the key is released)
-
- Keycodes:
- Scancode consists of 7bit keycode and 1bit release flag.
- Device can send two keycodes at once. If just one keycode is sent
- keycode1 contains it and keyocode2 is 0xFF.
-
- Power switch:
- You can read the state from PSW line(active low) however
- the switch has a special scancode 0x7F7F, so you can
- also read from Data line. It uses 0xFFFF for release scancode.
-
-Keyboard LEDs & state of keys(Register2)
- This register hold current state of three LEDs and nine keys.
- The state of LEDs can be changed by sending Listen command.
-
- 1514 . . . . . . 7 6 5 . 3 2 1 0
- | | | | | | | | | | | | | | | +- LED1(NumLock)
- | | | | | | | | | | | | | | +--- LED2(CapsLock)
- | | | | | | | | | | | | | +----- LED3(ScrollLock)
- | | | | | | | | | | +-+-+------- Reserved
- | | | | | | | | | +------------- ScrollLock
- | | | | | | | | +--------------- NumLock
- | | | | | | | +----------------- Apple/Command
- | | | | | | +------------------- Option
- | | | | | +--------------------- Shift
- | | | | +----------------------- Control
- | | | +------------------------- Reset/Power
- | | +--------------------------- CapsLock
- | +----------------------------- Delete
- +------------------------------- Reserved
-
-Address, Handler ID and bits(Register3)
- 1514131211 . . 8 7 . . . . . . 0
- | | | | | | | | | | | | | | | |
- | | | | | | | | +-+-+-+-+-+-+-+- Handler ID
- | | | | +-+-+-+----------------- Address
- | | | +------------------------- 0
- | | +--------------------------- Service request enable(1 = enabled)
- | +----------------------------- Exceptional event(alwyas 1 if not used)
- +------------------------------- 0
-
-ADB Bit Cells
- bit cell time: 70-130us
- low part of bit0: 60-70% of bit cell
- low part of bit1: 30-40% of bit cell
-
- bit cell time 70us 130us
- --------------------------------------------
- low part of bit0 42-49 78-91
- high part of bit0 21-28 39-52
- low part of bit1 21-28 39-52
- high part of bit1 42-49 78-91
-
-
- bit0:
- 70us bit cell:
- ____________~~~~~~
- 42-49 21-28
-
- 130us bit cell:
- ____________~~~~~~
- 78-91 39-52
-
- bit1:
- 70us bit cell:
- ______~~~~~~~~~~~~
- 21-28 42-49
-
- 130us bit cell:
- ______~~~~~~~~~~~~
- 39-52 78-91
-
- [from Apple IIgs Hardware Reference Second Edition]
-
-Keyboard Handle ID
- Apple Standard Keyboard M0116: 0x01
- Apple Extended Keyboard M0115: 0x02
- Apple Extended Keyboard II M3501: 0x02
- Apple Adjustable Keybaord: 0x10
-
- http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L802
-
-END_OF_ADB
-*/
diff --git a/tmk_core/protocol/adb.h b/tmk_core/protocol/adb.h
deleted file mode 100644
index fe8becc2d5..0000000000
--- a/tmk_core/protocol/adb.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#if !(defined(ADB_PORT) && defined(ADB_PIN) && defined(ADB_DDR) && defined(ADB_DATA_BIT))
-# error "ADB port setting is required in config.h"
-#endif
-
-#define ADB_POWER 0x7F
-#define ADB_CAPS 0x39
-
-/* ADB commands */
-// Default Address
-#define ADB_ADDR_0 0
-#define ADB_ADDR_DONGLE 1
-#define ADB_ADDR_KEYBOARD 2
-#define ADB_ADDR_MOUSE 3
-#define ADB_ADDR_TABLET 4
-#define ADB_ADDR_APPLIANCE 7
-#define ADB_ADDR_8 8
-#define ADB_ADDR_9 9
-#define ADB_ADDR_10 10
-#define ADB_ADDR_11 11
-#define ADB_ADDR_12 12
-#define ADB_ADDR_13 13
-#define ADB_ADDR_14 14
-#define ADB_ADDR_15 15
-// for temporary purpose, do not use for polling
-#define ADB_ADDR_TMP 15
-#define ADB_ADDR_MOUSE_POLL 10
-// Command Type
-#define ADB_CMD_RESET 0
-#define ADB_CMD_FLUSH 1
-#define ADB_CMD_LISTEN 8
-#define ADB_CMD_TALK 12
-// Register
-#define ADB_REG_0 0
-#define ADB_REG_1 1
-#define ADB_REG_2 2
-#define ADB_REG_3 3
-
-/* ADB keyboard handler id */
-#define ADB_HANDLER_STD 0x01 /* IIGS, M0116 */
-#define ADB_HANDLER_AEK 0x02 /* M0115, M3501 */
-#define ADB_HANDLER_AEK_RMOD 0x03 /* M0115, M3501, alternate mode enableing right modifiers */
-#define ADB_HANDLER_STD_ISO 0x04 /* M0118, ISO swapping keys */
-#define ADB_HANDLER_AEK_ISO 0x05 /* M0115, M3501, ISO swapping keys */
-#define ADB_HANDLER_M1242_ANSI 0x10 /* Adjustable keyboard */
-#define ADB_HANDLER_CLASSIC1_MOUSE 0x01
-#define ADB_HANDLER_CLASSIC2_MOUSE 0x02
-#define ADB_HANDLER_EXTENDED_MOUSE 0x04
-#define ADB_HANDLER_TURBO_MOUSE 0x32
-
-// ADB host
-void adb_host_init(void);
-bool adb_host_psw(void);
-uint16_t adb_host_talk(uint8_t addr, uint8_t reg);
-uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
-void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l);
-void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
-void adb_host_flush(uint8_t addr);
-void adb_host_kbd_led(uint8_t led);
-uint16_t adb_host_kbd_recv(void);
-uint16_t adb_host_mouse_recv(void);
-
-// ADB Mouse
-void adb_mouse_task(void);
-void adb_mouse_init(void);
diff --git a/tmk_core/protocol/arm_atsam.mk b/tmk_core/protocol/arm_atsam.mk
index 5bb45d658e..ffd1fa9f50 100644
--- a/tmk_core/protocol/arm_atsam.mk
+++ b/tmk_core/protocol/arm_atsam.mk
@@ -9,7 +9,8 @@ ifeq ($(RGB_MATRIX_DRIVER),custom)
SRC += $(ARM_ATSAM_DIR)/md_rgb_matrix.c
endif
SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c
-SRC += $(ARM_ATSAM_DIR)/spi.c
+SRC += $(ARM_ATSAM_DIR)/shift_register.c
+SRC += $(ARM_ATSAM_DIR)/spi_master.c
SRC += $(ARM_ATSAM_DIR)/startup.c
SRC += $(ARM_ATSAM_DIR)/usb/main_usb.c
@@ -19,10 +20,12 @@ SRC += $(ARM_ATSAM_DIR)/usb/udi_hid.c
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd.c
SRC += $(ARM_ATSAM_DIR)/usb/udi_hid_kbd_desc.c
SRC += $(ARM_ATSAM_DIR)/usb/ui.c
-SRC += $(ARM_ATSAM_DIR)/usb/usb2422.c
SRC += $(ARM_ATSAM_DIR)/usb/usb.c
SRC += $(ARM_ATSAM_DIR)/usb/usb_device_udd.c
+SRC += $(ARM_ATSAM_DIR)/usb/usb_hub.c
SRC += $(ARM_ATSAM_DIR)/usb/usb_util.c
+SRC += $(DRIVER_PATH)/usb2422.c
+
# Search Path
VPATH += $(TMK_DIR)/$(ARM_ATSAM_DIR)
diff --git a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h
index d126c66e7d..e1749f872d 100644
--- a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h
+++ b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h
@@ -27,9 +27,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "wait.h"
#include "adc.h"
#include "i2c_master.h"
-#include "spi.h"
+#include "shift_register.h"
-#include "./usb/usb2422.h"
+#include "./usb/usb_hub.h"
#ifndef MD_BOOTLOADER
diff --git a/tmk_core/protocol/arm_atsam/i2c_master.c b/tmk_core/protocol/arm_atsam/i2c_master.c
index dda2f85b00..af046625f4 100644
--- a/tmk_core/protocol/arm_atsam/i2c_master.c
+++ b/tmk_core/protocol/arm_atsam/i2c_master.c
@@ -564,4 +564,23 @@ uint8_t i2c_led_q_run(void) {
return 1;
}
+
+__attribute__((weak)) void i2c_init(void) {
+ static bool is_initialised = false;
+ if (!is_initialised) {
+ is_initialised = true;
+
+ i2c0_init();
+ }
+}
+
+i2c_status_t i2c_transmit(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout) {
+ uint8_t ret = i2c0_transmit(address, (uint8_t *)data, length, timeout);
+ SERCOM0->I2CM.CTRLB.bit.CMD = 0x03;
+ while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {
+ DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP);
+ }
+ return ret ? I2C_STATUS_SUCCESS : I2C_STATUS_ERROR;
+}
+
#endif // !defined(MD_BOOTLOADER) && defined(RGB_MATRIX_ENABLE)
diff --git a/tmk_core/protocol/arm_atsam/i2c_master.h b/tmk_core/protocol/arm_atsam/i2c_master.h
index 68773f213f..e11235d447 100644
--- a/tmk_core/protocol/arm_atsam/i2c_master.h
+++ b/tmk_core/protocol/arm_atsam/i2c_master.h
@@ -101,4 +101,13 @@ void i2c0_init(void);
uint8_t i2c0_transmit(uint8_t address, uint8_t *data, uint16_t length, uint16_t timeout);
void i2c0_stop(void);
+// Terrible interface compatiblity...
+#define I2C_STATUS_SUCCESS (0)
+#define I2C_STATUS_ERROR (-1)
+
+typedef int16_t i2c_status_t;
+
+void i2c_init(void);
+i2c_status_t i2c_transmit(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout);
+
#endif // _I2C_MASTER_H_
diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c
index 858b4cd9fc..de12821a74 100644
--- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c
+++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c
@@ -40,6 +40,10 @@ void send_mouse(report_mouse_t *report);
void send_system(uint16_t data);
void send_consumer(uint16_t data);
+#ifdef DEFERRED_EXEC_ENABLE
+void deferred_exec_task(void);
+#endif // DEFERRED_EXEC_ENABLE
+
host_driver_t arm_atsam_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
uint8_t led_states;
@@ -296,7 +300,7 @@ int main(void) {
matrix_init();
- USB2422_init();
+ USB_Hub_init();
DBGC(DC_MAIN_UDC_START_BEGIN);
udc_start();
@@ -306,7 +310,7 @@ int main(void) {
CDC_init();
DBGC(DC_MAIN_CDC_INIT_COMPLETE);
- while (USB2422_Port_Detect_Init() == 0) {
+ while (USB_Hub_Port_Detect_Init() == 0) {
}
DBG_LED_OFF;
@@ -360,6 +364,11 @@ int main(void) {
}
#endif // CONSOLE_ENABLE
+#ifdef DEFERRED_EXEC_ENABLE
+ // Run deferred executions
+ deferred_exec_task();
+#endif // DEFERRED_EXEC_ENABLE
+
// Run housekeeping
housekeeping_task();
}
diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c
index ddd74f1680..0741584439 100644
--- a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c
+++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c
@@ -15,6 +15,10 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define FLUSH_TIMEOUT 5000
+#define EECONFIG_MD_LED ((uint8_t*)(EECONFIG_SIZE + 64))
+#define MD_LED_CONFIG_VERSION 1
+
#ifdef RGB_MATRIX_ENABLE
# include "arm_atsam_protocol.h"
# include "led.h"
@@ -23,8 +27,41 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include <math.h>
# ifdef USE_MASSDROP_CONFIGURATOR
+// TODO?: wire these up to keymap.c
+md_led_config_t md_led_config = {0};
+
+EECONFIG_DEBOUNCE_HELPER(md_led, EECONFIG_MD_LED, md_led_config);
+
+void eeconfig_update_md_led_default(void) {
+ md_led_config.ver = MD_LED_CONFIG_VERSION;
+
+ gcr_desired = LED_GCR_MAX;
+ led_animation_orientation = 0;
+ led_animation_direction = 0;
+ led_animation_breathing = 0;
+ led_animation_id = 0;
+ led_animation_speed = 4.0f;
+ led_lighting_mode = LED_MODE_NORMAL;
+ led_enabled = 1;
+ led_animation_breathe_cur = BREATHE_MIN_STEP;
+ breathe_dir = 1;
+ led_animation_circular = 0;
+ led_edge_brightness = 1.0f;
+ led_ratio_brightness = 1.0f;
+ led_edge_mode = LED_EDGE_MODE_ALL;
+
+ eeconfig_flush_md_led(true);
+}
+
+void md_led_changed(void) { eeconfig_flag_md_led(true); }
+
+// todo: use real task rather than this bodge
+void housekeeping_task_kb(void) { eeconfig_flush_md_led_task(FLUSH_TIMEOUT); }
+
__attribute__((weak)) led_instruction_t led_instructions[] = {{.end = 1}};
static void md_rgb_matrix_config_override(int i);
+# else
+uint8_t gcr_desired;
# endif // USE_MASSDROP_CONFIGURATOR
void SERCOM1_0_Handler(void) {
@@ -56,7 +93,6 @@ issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
issi3733_led_t led_map[ISSI3733_LED_COUNT] = ISSI3733_LED_MAP;
RGB led_buffer[ISSI3733_LED_COUNT];
-uint8_t gcr_desired;
uint8_t gcr_actual;
uint8_t gcr_actual_last;
# ifdef USE_MASSDROP_CONFIGURATOR
@@ -218,6 +254,13 @@ static void led_set_all(uint8_t r, uint8_t g, uint8_t b) {
static void init(void) {
DBGC(DC_LED_MATRIX_INIT_BEGIN);
+# ifdef USE_MASSDROP_CONFIGURATOR
+ eeconfig_init_md_led();
+ if (md_led_config.ver != MD_LED_CONFIG_VERSION) {
+ eeconfig_update_md_led_default();
+ }
+# endif
+
issi3733_prepare_arrays();
md_rgb_matrix_prepare();
@@ -331,17 +374,6 @@ const rgb_matrix_driver_t rgb_matrix_driver = {.init = init, .flush = flush, .se
# ifdef USE_MASSDROP_CONFIGURATOR
// Ported from Massdrop QMK GitHub Repo
-// TODO?: wire these up to keymap.c
-uint8_t led_animation_orientation = 0;
-uint8_t led_animation_direction = 0;
-uint8_t led_animation_breathing = 0;
-uint8_t led_animation_id = 0;
-float led_animation_speed = 4.0f;
-uint8_t led_lighting_mode = LED_MODE_NORMAL;
-uint8_t led_enabled = 1;
-uint8_t led_animation_breathe_cur = BREATHE_MIN_STEP;
-uint8_t breathe_dir = 1;
-
static void led_run_pattern(led_setup_t* f, float* ro, float* go, float* bo, float pos) {
float po;
@@ -398,16 +430,32 @@ static void led_run_pattern(led_setup_t* f, float* ro, float* go, float* bo, flo
}
}
+# define RGB_MAX_DISTANCE 232.9635f
+
static void md_rgb_matrix_config_override(int i) {
float ro = 0;
float go = 0;
float bo = 0;
-
- float po = (led_animation_orientation) ? (float)g_led_config.point[i].y / 64.f * 100 : (float)g_led_config.point[i].x / 224.f * 100;
+ float po;
uint8_t highest_active_layer = biton32(layer_state);
- if (led_lighting_mode == LED_MODE_KEYS_ONLY && HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) {
+ if (led_animation_circular) {
+ // TODO: should use min/max values from LED configuration instead of
+ // hard-coded 224, 64
+ // po = sqrtf((powf(fabsf((disp.width / 2) - (led_cur->x - disp.left)), 2) + powf(fabsf((disp.height / 2) - (led_cur->y - disp.bottom)), 2))) / disp.max_distance * 100;
+ po = sqrtf((powf(fabsf((224 / 2) - (float)g_led_config.point[i].x), 2) + powf(fabsf((64 / 2) - (float)g_led_config.point[i].y), 2))) / RGB_MAX_DISTANCE * 100;
+ } else {
+ if (led_animation_orientation) {
+ po = (float)g_led_config.point[i].y / 64.f * 100;
+ } else {
+ po = (float)g_led_config.point[i].x / 224.f * 100;
+ }
+ }
+
+ if (led_edge_mode == LED_EDGE_MODE_ALTERNATE && LED_IS_EDGE_ALT(led_map[i].scan)) {
+ // Do not act on this LED (Edge alternate lighting mode)
+ } else if (led_lighting_mode == LED_MODE_KEYS_ONLY && HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) {
// Do not act on this LED
} else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && !HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) {
// Do not act on this LED
@@ -465,6 +513,26 @@ static void md_rgb_matrix_config_override(int i) {
}
}
+ // Adjust edge LED brightness
+ if (led_edge_brightness != 1 && LED_IS_EDGE(led_map[i].scan)) {
+ ro *= led_edge_brightness;
+ go *= led_edge_brightness;
+ bo *= led_edge_brightness;
+ }
+
+ // Adjust ratio of key vs. underglow (edge) LED brightness
+ if (LED_IS_EDGE(led_map[i].scan) && led_ratio_brightness > 1.0) {
+ // Decrease edge (underglow) LEDs
+ ro *= (2.0 - led_ratio_brightness);
+ go *= (2.0 - led_ratio_brightness);
+ bo *= (2.0 - led_ratio_brightness);
+ } else if (LED_IS_KEY(led_map[i].scan) && led_ratio_brightness < 1.0) {
+ // Decrease KEY LEDs
+ ro *= led_ratio_brightness;
+ go *= led_ratio_brightness;
+ bo *= led_ratio_brightness;
+ }
+
led_buffer[i].r = (uint8_t)ro;
led_buffer[i].g = (uint8_t)go;
led_buffer[i].b = (uint8_t)bo;
diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix.h b/tmk_core/protocol/arm_atsam/md_rgb_matrix.h
index 76ccaa678b..deea12b888 100644
--- a/tmk_core/protocol/arm_atsam/md_rgb_matrix.h
+++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.h
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define _LED_MATRIX_H_
#include "quantum.h"
+#include "eeprom.h"
// From keyboard
#include "config_led.h"
@@ -79,7 +80,6 @@ typedef struct issi3733_led_s {
extern issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
-extern uint8_t gcr_desired;
extern uint8_t gcr_breathe;
extern uint8_t gcr_actual;
extern uint8_t gcr_actual_last;
@@ -128,6 +128,8 @@ typedef struct led_instruction_s {
uint32_t id1; // Bitwise id, IDs 32-63
uint32_t id2; // Bitwise id, IDs 64-95
uint32_t id3; // Bitwise id, IDs 96-127
+ uint32_t id4; // Bitwise id, IDs 128-159
+ uint32_t id5; // Bitwise id, IDs 160-191
uint8_t layer;
uint8_t r;
uint8_t g;
@@ -138,14 +140,43 @@ typedef struct led_instruction_s {
extern led_instruction_t led_instructions[];
-extern uint8_t led_animation_breathing;
-extern uint8_t led_animation_id;
-extern float led_animation_speed;
-extern uint8_t led_lighting_mode;
-extern uint8_t led_enabled;
-extern uint8_t led_animation_breathe_cur;
-extern uint8_t led_animation_direction;
-extern uint8_t breathe_dir;
+typedef struct led_config_s {
+ uint8_t ver; // assumed to be zero on eeprom reset
+
+ uint8_t desired_gcr;
+ uint8_t animation_breathing;
+ uint8_t animation_id;
+ float animation_speed;
+ uint8_t lighting_mode;
+ uint8_t enabled;
+ uint8_t animation_breathe_cur;
+ uint8_t animation_direction;
+ uint8_t animation_breathe_dir;
+ uint8_t animation_orientation;
+ uint8_t animation_circular;
+ float edge_brightness;
+ float ratio_brightness;
+ uint8_t edge_mode;
+} md_led_config_t;
+
+extern md_led_config_t md_led_config;
+
+void md_led_changed(void);
+
+# define gcr_desired md_led_config.desired_gcr
+# define led_animation_breathing md_led_config.animation_breathing
+# define led_animation_id md_led_config.animation_id
+# define led_animation_speed md_led_config.animation_speed
+# define led_lighting_mode md_led_config.lighting_mode
+# define led_enabled md_led_config.enabled
+# define led_animation_breathe_cur md_led_config.animation_breathe_cur
+# define led_animation_direction md_led_config.animation_direction
+# define breathe_dir md_led_config.animation_breathe_dir
+# define led_animation_orientation md_led_config.animation_orientation
+# define led_animation_circular md_led_config.animation_circular
+# define led_edge_brightness md_led_config.edge_brightness
+# define led_ratio_brightness md_led_config.ratio_brightness
+# define led_edge_mode md_led_config.edge_mode
# define LED_MODE_NORMAL 0 // Must be 0
# define LED_MODE_KEYS_ONLY 1
@@ -153,6 +184,21 @@ extern uint8_t breathe_dir;
# define LED_MODE_INDICATORS_ONLY 3
# define LED_MODE_MAX_INDEX LED_MODE_INDICATORS_ONLY // Must be highest value
+# define LED_EDGE_MODE_ALL 0 // All edge LEDs are active (Must be 0)
+# define LED_EDGE_MODE_ALTERNATE 1 // Alternate mode of edge LEDs are active (Intention is for 'only every other edge LED' to be active)
+# define LED_EDGE_MODE_MAX LED_EDGE_MODE_ALTERNATE // Must be the highest valued LED edge mode
+
+# define LED_EDGE_FULL_MODE 255 // LEDs configured with this scan code will always be on for edge lighting modes
+# define LED_EDGE_ALT_MODE 254 // LEDs configured with this scan code will turn off in edge alternating mode
+# define LED_EDGE_MIN_SCAN 254 // LEDs configured with scan code >= to this are assigned as edge LEDs
+# define LED_INDICATOR_SCAN 253 // LEDs configured as dedicated indicators
+
+# define LED_IS_KEY(scan) (scan < LED_INDICATOR_SCAN) // Return true if an LED's scan value indicates it is a key LED
+# define LED_IS_EDGE(scan) (scan >= LED_EDGE_MIN_SCAN) // Return true if an LED's scan value indicates an edge LED
+# define LED_IS_EDGE_ALT(scan) (scan == LED_EDGE_ALT_MODE) // Return true if an LED's scan value indicates an alternate edge mode LED
+# define LED_IS_INDICATOR(scan) (scan == LED_INDICATOR_SCAN) // Return true if an LED's scan value indicates it is a dedicated Indicator
+#else
+extern uint8_t gcr_desired;
#endif // USE_MASSDROP_CONFIGURATOR
#endif //_LED_MATRIX_H_
diff --git a/tmk_core/protocol/arm_atsam/shift_register.c b/tmk_core/protocol/arm_atsam/shift_register.c
new file mode 100644
index 0000000000..8d63af1b59
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/shift_register.c
@@ -0,0 +1,118 @@
+/*
+Copyright 2018 Massdrop Inc.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "arm_atsam_protocol.h"
+
+#include "spi_master.h"
+#include "wait.h"
+#include "gpio.h"
+
+// #define SR_USE_BITBANG
+
+// Bodge for when spi_master is not available
+#ifdef SR_USE_BITBANG
+# define CLOCK_DELAY 10
+
+void shift_init_impl(void) {
+ setPinOutput(SR_EXP_RCLK_PIN);
+ setPinOutput(SPI_DATAOUT_PIN);
+ setPinOutput(SPI_SCLK_PIN);
+}
+
+void shift_out_impl(const uint8_t *data, uint16_t length) {
+ writePinLow(SR_EXP_RCLK_PIN);
+ for (uint16_t i = 0; i < length; i++) {
+ uint8_t val = data[i];
+
+ // shift out lsb first
+ for (uint8_t bit = 0; bit < 8; bit++) {
+ writePin(SPI_DATAOUT_PIN, !!(val & (1 << bit)));
+ writePin(SPI_SCLK_PIN, true);
+ wait_us(CLOCK_DELAY);
+
+ writePin(SPI_SCLK_PIN, false);
+ wait_us(CLOCK_DELAY);
+ }
+ }
+ writePinHigh(SR_EXP_RCLK_PIN);
+ return SPI_STATUS_SUCCESS;
+}
+
+#else
+
+void shift_init_impl(void) { spi_init(); }
+
+void shift_out_impl(const uint8_t *data, uint16_t length) {
+ spi_start(SR_EXP_RCLK_PIN, true, 0, 0);
+
+ spi_transmit(data, length);
+
+ spi_stop();
+}
+#endif
+
+// ***************************************************************
+
+void shift_out(const uint8_t *data, uint16_t length) { shift_out_impl(data, length); }
+
+void shift_enable(void) {
+ setPinOutput(SR_EXP_OE_PIN);
+ writePinLow(SR_EXP_OE_PIN);
+}
+
+void shift_disable(void) {
+ setPinOutput(SR_EXP_OE_PIN);
+ writePinHigh(SR_EXP_OE_PIN);
+}
+
+void shift_init(void) {
+ shift_disable();
+ shift_init_impl();
+}
+
+// ***************************************************************
+
+sr_exp_t sr_exp_data;
+
+void SR_EXP_WriteData(void) {
+ uint8_t data[2] = {
+ sr_exp_data.reg & 0xFF, // Shift in bits 7-0
+ (sr_exp_data.reg >> 8) & 0xFF, // Shift in bits 15-8
+ };
+ shift_out(data, 2);
+}
+
+void SR_EXP_Init(void) {
+ shift_init();
+
+ sr_exp_data.reg = 0;
+ sr_exp_data.bit.HUB_CONNECT = 0;
+ sr_exp_data.bit.HUB_RESET_N = 0;
+ sr_exp_data.bit.S_UP = 0;
+ sr_exp_data.bit.E_UP_N = 1;
+ sr_exp_data.bit.S_DN1 = 1;
+ sr_exp_data.bit.E_DN1_N = 1;
+ sr_exp_data.bit.E_VBUS_1 = 0;
+ sr_exp_data.bit.E_VBUS_2 = 0;
+ sr_exp_data.bit.SRC_1 = 1;
+ sr_exp_data.bit.SRC_2 = 1;
+ sr_exp_data.bit.IRST = 1;
+ sr_exp_data.bit.SDB_N = 0;
+ SR_EXP_WriteData();
+
+ shift_enable();
+}
diff --git a/tmk_core/protocol/arm_atsam/spi.h b/tmk_core/protocol/arm_atsam/shift_register.h
index dcd45f31af..56a8c7f717 100644
--- a/tmk_core/protocol/arm_atsam/spi.h
+++ b/tmk_core/protocol/arm_atsam/shift_register.h
@@ -15,28 +15,9 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _SPI_H_
-#define _SPI_H_
+#pragma once
-/* Macros for Shift Register control */
-#define SR_EXP_RCLK_LO PORT->Group[SR_EXP_RCLK_PORT].OUTCLR.reg = (1 << SR_EXP_RCLK_PIN)
-#define SR_EXP_RCLK_HI PORT->Group[SR_EXP_RCLK_PORT].OUTSET.reg = (1 << SR_EXP_RCLK_PIN)
-#define SR_EXP_OE_N_ENA PORT->Group[SR_EXP_OE_N_PORT].OUTCLR.reg = (1 << SR_EXP_OE_N_PIN)
-#define SR_EXP_OE_N_DIS PORT->Group[SR_EXP_OE_N_PORT].OUTSET.reg = (1 << SR_EXP_OE_N_PIN)
-
-/* Determine bits to set for mux selection */
-#if SR_EXP_DATAOUT_PIN % 2 == 0
-# define SR_EXP_DATAOUT_MUX_SEL PMUXE
-#else
-# define SR_EXP_DATAOUT_MUX_SEL PMUXO
-#endif
-
-/* Determine bits to set for mux selection */
-#if SR_EXP_SCLK_PIN % 2 == 0
-# define SR_EXP_SCLK_MUX_SEL PMUXE
-#else
-# define SR_EXP_SCLK_MUX_SEL PMUXO
-#endif
+#include <stdint.h>
/* Data structure to define Shift Register output expander hardware */
/* This structure gets shifted into registers LSB first */
@@ -66,5 +47,3 @@ extern sr_exp_t sr_exp_data;
void SR_EXP_WriteData(void);
void SR_EXP_Init(void);
-
-#endif //_SPI_H_
diff --git a/tmk_core/protocol/arm_atsam/spi.c b/tmk_core/protocol/arm_atsam/spi.c
deleted file mode 100644
index 3b118bc1f1..0000000000
--- a/tmk_core/protocol/arm_atsam/spi.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-Copyright 2018 Massdrop Inc.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "arm_atsam_protocol.h"
-
-sr_exp_t sr_exp_data;
-
-void SR_EXP_WriteData(void) {
- SR_EXP_RCLK_LO;
-
- while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.DRE)) {
- DBGC(DC_SPI_WRITE_DRE);
- }
-
- SR_EXP_SERCOM->SPI.DATA.bit.DATA = sr_exp_data.reg & 0xFF; // Shift in bits 7-0
- while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) {
- DBGC(DC_SPI_WRITE_TXC_1);
- }
-
- SR_EXP_SERCOM->SPI.DATA.bit.DATA = (sr_exp_data.reg >> 8) & 0xFF; // Shift in bits 15-8
- while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) {
- DBGC(DC_SPI_WRITE_TXC_2);
- }
-
- SR_EXP_RCLK_HI;
-}
-
-void SR_EXP_Init(void) {
- DBGC(DC_SPI_INIT_BEGIN);
-
- CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
-
- // Set up MCU Shift Register pins
- PORT->Group[SR_EXP_RCLK_PORT].DIRSET.reg = (1 << SR_EXP_RCLK_PIN);
- PORT->Group[SR_EXP_OE_N_PORT].DIRSET.reg = (1 << SR_EXP_OE_N_PIN);
-
- // Set up MCU SPI pins
- PORT->Group[SR_EXP_DATAOUT_PORT].PMUX[SR_EXP_DATAOUT_PIN / 2].bit.SR_EXP_DATAOUT_MUX_SEL = SR_EXP_DATAOUT_MUX; // MUX select for sercom
- PORT->Group[SR_EXP_SCLK_PORT].PMUX[SR_EXP_SCLK_PIN / 2].bit.SR_EXP_SCLK_MUX_SEL = SR_EXP_SCLK_MUX; // MUX select for sercom
- PORT->Group[SR_EXP_DATAOUT_PORT].PINCFG[SR_EXP_DATAOUT_PIN].bit.PMUXEN = 1; // MUX Enable
- PORT->Group[SR_EXP_SCLK_PORT].PINCFG[SR_EXP_SCLK_PIN].bit.PMUXEN = 1; // MUX Enable
-
- // Initialize Shift Register
- SR_EXP_OE_N_DIS;
- SR_EXP_RCLK_HI;
-
- SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1; // Data Order - LSB is transferred first
- SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1; // Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
- SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1; // Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
- SR_EXP_SERCOM->SPI.CTRLA.bit.DIPO = 3; // Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.)
- SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0; // Data Output PAD[0], Serial Clock PAD[1]
- SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3; // Operating Mode - Master operation
-
- SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1; // Enable - Peripheral is enabled or being enabled
- while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) {
- DBGC(DC_SPI_SYNC_ENABLING);
- }
-
- sr_exp_data.reg = 0;
- sr_exp_data.bit.HUB_CONNECT = 0;
- sr_exp_data.bit.HUB_RESET_N = 0;
- sr_exp_data.bit.S_UP = 0;
- sr_exp_data.bit.E_UP_N = 1;
- sr_exp_data.bit.S_DN1 = 1;
- sr_exp_data.bit.E_DN1_N = 1;
- sr_exp_data.bit.E_VBUS_1 = 0;
- sr_exp_data.bit.E_VBUS_2 = 0;
- sr_exp_data.bit.SRC_1 = 1;
- sr_exp_data.bit.SRC_2 = 1;
- sr_exp_data.bit.IRST = 1;
- sr_exp_data.bit.SDB_N = 0;
- SR_EXP_WriteData();
-
- // Enable Shift Register output
- SR_EXP_OE_N_ENA;
-
- DBGC(DC_SPI_INIT_COMPLETE);
-}
diff --git a/tmk_core/protocol/arm_atsam/spi_master.c b/tmk_core/protocol/arm_atsam/spi_master.c
new file mode 100644
index 0000000000..9781d45b1e
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/spi_master.c
@@ -0,0 +1,109 @@
+/*
+Copyright 2018 Massdrop Inc.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "arm_atsam_protocol.h"
+#include "spi_master.h"
+#include "gpio.h"
+
+/* Determine bits to set for mux selection */
+#if SPI_DATAOUT_PIN % 2 == 0
+# define SPI_DATAOUT_MUX_SEL PMUXE
+#else
+# define SPI_DATAOUT_MUX_SEL PMUXO
+#endif
+
+/* Determine bits to set for mux selection */
+#if SPI_SCLK_PIN % 2 == 0
+# define SPI_SCLK_MUX_SEL PMUXE
+#else
+# define SPI_SCLK_MUX_SEL PMUXO
+#endif
+
+static pin_t currentSelectPin = NO_PIN;
+
+__attribute__((weak)) void spi_init(void) {
+ static bool is_initialised = false;
+ if (!is_initialised) {
+ is_initialised = true;
+
+ DBGC(DC_SPI_INIT_BEGIN);
+
+ CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
+
+ // Set up MCU SPI pins
+ PORT->Group[SAMD_PORT(SPI_DATAOUT_PIN)].PMUX[SAMD_PIN(SPI_DATAOUT_PIN) / 2].bit.SPI_DATAOUT_MUX_SEL = SPI_DATAOUT_MUX; // MUX select for sercom
+ PORT->Group[SAMD_PORT(SPI_SCLK_PIN)].PMUX[SAMD_PIN(SPI_SCLK_PIN) / 2].bit.SPI_SCLK_MUX_SEL = SPI_SCLK_MUX; // MUX select for sercom
+ PORT->Group[SAMD_PORT(SPI_DATAOUT_PIN)].PINCFG[SAMD_PIN(SPI_DATAOUT_PIN)].bit.PMUXEN = 1; // MUX Enable
+ PORT->Group[SAMD_PORT(SPI_SCLK_PIN)].PINCFG[SAMD_PIN(SPI_SCLK_PIN)].bit.PMUXEN = 1; // MUX Enable
+
+ DBGC(DC_SPI_INIT_COMPLETE);
+ }
+}
+
+bool spi_start(pin_t csPin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
+ if (currentSelectPin != NO_PIN || csPin == NO_PIN) {
+ return false;
+ }
+
+ currentSelectPin = csPin;
+ setPinOutput(currentSelectPin);
+ writePinLow(currentSelectPin);
+
+ SPI_SERCOM->SPI.CTRLA.bit.DORD = lsbFirst; // Data Order - LSB is transferred first
+ SPI_SERCOM->SPI.CTRLA.bit.CPOL = 1; // Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising.
+ SPI_SERCOM->SPI.CTRLA.bit.CPHA = 1; // Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample
+ SPI_SERCOM->SPI.CTRLA.bit.DIPO = 3; // Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.)
+ SPI_SERCOM->SPI.CTRLA.bit.DOPO = 0; // Data Output PAD[0], Serial Clock PAD[1]
+ SPI_SERCOM->SPI.CTRLA.bit.MODE = 3; // Operating Mode - Master operation
+
+ SPI_SERCOM->SPI.CTRLA.bit.ENABLE = 1; // Enable - Peripheral is enabled or being enabled
+ while (SPI_SERCOM->SPI.SYNCBUSY.bit.ENABLE) {
+ DBGC(DC_SPI_SYNC_ENABLING);
+ }
+ return true;
+}
+
+spi_status_t spi_transmit(const uint8_t *data, uint16_t length) {
+ while (!(SPI_SERCOM->SPI.INTFLAG.bit.DRE)) {
+ DBGC(DC_SPI_WRITE_DRE);
+ }
+
+ for (uint16_t i = 0; i < length; i++) {
+ SPI_SERCOM->SPI.DATA.bit.DATA = data[i];
+ while (!(SPI_SERCOM->SPI.INTFLAG.bit.TXC)) {
+ DBGC(DC_SPI_WRITE_TXC_1);
+ }
+ }
+
+ return SPI_STATUS_SUCCESS;
+}
+
+void spi_stop(void) {
+ if (currentSelectPin != NO_PIN) {
+ setPinOutput(currentSelectPin);
+ writePinHigh(currentSelectPin);
+ currentSelectPin = NO_PIN;
+ }
+}
+
+// Not implemented yet....
+
+spi_status_t spi_write(uint8_t data);
+
+spi_status_t spi_read(void);
+
+spi_status_t spi_receive(uint8_t *data, uint16_t length);
diff --git a/tmk_core/protocol/arm_atsam/spi_master.h b/tmk_core/protocol/arm_atsam/spi_master.h
new file mode 100644
index 0000000000..26c55128be
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/spi_master.h
@@ -0,0 +1,48 @@
+/* Copyright 2021 QMK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+typedef int16_t spi_status_t;
+
+#define SPI_STATUS_SUCCESS (0)
+#define SPI_STATUS_ERROR (-1)
+#define SPI_STATUS_TIMEOUT (-2)
+
+#define SPI_TIMEOUT_IMMEDIATE (0)
+#define SPI_TIMEOUT_INFINITE (0xFFFF)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void spi_init(void);
+
+bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor);
+
+spi_status_t spi_write(uint8_t data);
+
+spi_status_t spi_read(void);
+
+spi_status_t spi_transmit(const uint8_t *data, uint16_t length);
+
+spi_status_t spi_receive(uint8_t *data, uint16_t length);
+
+void spi_stop(void);
+#ifdef __cplusplus
+}
+#endif
diff --git a/tmk_core/protocol/arm_atsam/usb/usb2422.c b/tmk_core/protocol/arm_atsam/usb/usb_hub.c
index a878cb6b7c..c5fd284aab 100644
--- a/tmk_core/protocol/arm_atsam/usb/usb2422.c
+++ b/tmk_core/protocol/arm_atsam/usb/usb_hub.c
@@ -16,25 +16,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "arm_atsam_protocol.h"
+#include "drivers/usb2422.h"
#include <string.h>
-Usb2422 USB2422_shadow;
-unsigned char i2c0_buf[34];
-
-const uint16_t MFRNAME[] = {'M', 'a', 's', 's', 'd', 'r', 'o', 'p', ' ', 'I', 'n', 'c', '.'}; // Massdrop Inc.
-const uint16_t PRDNAME[] = {'M', 'a', 's', 's', 'd', 'r', 'o', 'p', ' ', 'H', 'u', 'b'}; // Massdrop Hub
-#ifndef MD_BOOTLOADER
-// Serial number reported stops before first found space character or at last found character
-const uint16_t SERNAME[] = {'U', 'n', 'a', 'v', 'a', 'i', 'l', 'a', 'b', 'l', 'e'}; // Unavailable
-#else
-// In production, this field is found, modified, and offset noted as the last 32-bit word in the bootloader space
-// The offset allows the application to use the factory programmed serial (which may differ from the physical serial label)
-// Serial number reported stops before first found space character or when max size is reached
-__attribute__((__aligned__(4))) const uint16_t SERNAME[BOOTLOADER_SERIAL_MAX_SIZE] = {'M', 'D', 'H', 'U', 'B', 'B', 'O', 'O', 'T', 'L', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
-// NOTE: Serial replacer will not write a string longer than given here as a precaution, so give enough
-// space as needed and adjust BOOTLOADER_SERIAL_MAX_SIZE to match amount given
-#endif // MD_BOOTLOADER
-
uint8_t usb_host_port;
#ifndef MD_BOOTLOADER
@@ -47,29 +31,7 @@ uint8_t usb_gcr_auto;
uint16_t adc_extra;
-void USB_write2422_block(void) {
- unsigned char *dest = i2c0_buf;
- unsigned char *src;
- unsigned char *base = (unsigned char *)&USB2422_shadow;
-
- DBGC(DC_USB_WRITE2422_BLOCK_BEGIN);
-
- for (src = base; src < base + 256; src += 32) {
- dest[0] = src - base;
- dest[1] = 32;
- memcpy(&dest[2], src, 32);
- i2c0_transmit(USB2422_ADDR, dest, 34, 50000);
- SERCOM0->I2CM.CTRLB.bit.CMD = 0x03;
- while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) {
- DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP);
- }
- wait_us(100);
- }
-
- DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE);
-}
-
-void USB2422_init(void) {
+void USB_Hub_init(void) {
Gclk * pgclk = GCLK;
Mclk * pmclk = MCLK;
Port * pport = PORT;
@@ -147,9 +109,7 @@ void USB2422_init(void) {
pusb->DEVICE.QOSCTRL.bit.DQOS = 2;
pusb->DEVICE.QOSCTRL.bit.CQOS = 2;
- pport->Group[USB2422_HUB_ACTIVE_GROUP].PINCFG[USB2422_HUB_ACTIVE_PIN].bit.INEN = 1;
-
- i2c0_init(); // IC2 clk must be high at USB2422 reset release time to signal SMB configuration
+ USB2422_init();
sr_exp_data.bit.HUB_CONNECT = 1; // connect signal
sr_exp_data.bit.HUB_RESET_N = 1; // reset high
@@ -181,62 +141,16 @@ void USB_reset(void) {
}
void USB_configure(void) {
- Usb2422 *pusb2422 = &USB2422_shadow;
- memset(pusb2422, 0, sizeof(Usb2422));
-
- uint16_t *serial_use = (uint16_t *)SERNAME; // Default to use SERNAME from this file
- uint8_t serial_length = sizeof(SERNAME) / sizeof(uint16_t); // Default to use SERNAME from this file
-#ifndef MD_BOOTLOADER
- uint32_t serial_ptrloc = (uint32_t)&_srom - 4;
-#else // MD_BOOTLOADER
- uint32_t serial_ptrloc = (uint32_t)&_erom - 4;
-#endif // MD_BOOTLOADER
- uint32_t serial_address = *(uint32_t *)serial_ptrloc; // Address of bootloader's serial number if available
-
DBGC(DC_USB_CONFIGURE_BEGIN);
- if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) // Check for factory programmed serial address
- {
- if ((serial_address & 0xFF) % 4 == 0) // Check alignment
- {
- serial_use = (uint16_t *)(serial_address);
- serial_length = 0;
- while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) && serial_length < BOOTLOADER_SERIAL_MAX_SIZE) {
- serial_length++;
- DBGC(DC_USB_CONFIGURE_GET_SERIAL);
- }
- }
- }
-
- // configure Usb2422 registers
- pusb2422->VID.reg = 0x04D8; // from Microchip 4/19/2018
- pusb2422->PID.reg = 0xEEC5; // from Microchip 4/19/2018 = Massdrop, Inc. USB Hub
- pusb2422->DID.reg = 0x0101; // BCD 01.01
- pusb2422->CFG1.bit.SELF_BUS_PWR = 1; // self powered for now
- pusb2422->CFG1.bit.HS_DISABLE = 1; // full or high speed
- // pusb2422->CFG2.bit.COMPOUND = 0; // compound device
- pusb2422->CFG3.bit.STRING_EN = 1; // strings enabled
- // pusb2422->NRD.bit.PORT2_NR = 0; // MCU is non-removable
- pusb2422->MAXPB.reg = 20; // 0mA
- pusb2422->HCMCB.reg = 20; // 0mA
- pusb2422->MFRSL.reg = sizeof(MFRNAME) / sizeof(uint16_t);
- pusb2422->PRDSL.reg = sizeof(PRDNAME) / sizeof(uint16_t);
- pusb2422->SERSL.reg = serial_length;
- memcpy(pusb2422->MFRSTR, MFRNAME, sizeof(MFRNAME));
- memcpy(pusb2422->PRDSTR, PRDNAME, sizeof(PRDNAME));
- memcpy(pusb2422->SERSTR, serial_use, serial_length * sizeof(uint16_t));
- // pusb2422->BOOSTUP.bit.BOOST=3; //upstream port
- // pusb2422->BOOSTDOWN.bit.BOOST1=0; // extra port
- // pusb2422->BOOSTDOWN.bit.BOOST2=2; //MCU is close
- pusb2422->STCD.bit.USB_ATTACH = 1;
- USB_write2422_block();
+ USB2422_configure();
adc_extra = 0;
DBGC(DC_USB_CONFIGURE_COMPLETE);
}
-uint16_t USB_active(void) { return (PORT->Group[USB2422_HUB_ACTIVE_GROUP].IN.reg & (1 << USB2422_HUB_ACTIVE_PIN)) != 0; }
+uint16_t USB_active(void) { return USB2422_active(); }
void USB_set_host_by_voltage(void) {
// UP is upstream device (HOST)
@@ -314,7 +228,7 @@ void USB_set_host_by_voltage(void) {
DBGC(DC_USB_SET_HOST_BY_VOLTAGE_COMPLETE);
}
-uint8_t USB2422_Port_Detect_Init(void) {
+uint8_t USB_Hub_Port_Detect_Init(void) {
uint32_t port_detect_retry_ms;
uint32_t tmod;
diff --git a/tmk_core/protocol/arm_atsam/usb/usb_hub.h b/tmk_core/protocol/arm_atsam/usb/usb_hub.h
new file mode 100644
index 0000000000..76b1e0a326
--- /dev/null
+++ b/tmk_core/protocol/arm_atsam/usb/usb_hub.h
@@ -0,0 +1,51 @@
+/*
+Copyright 2018 Massdrop Inc.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _USB2422_H_
+#define _USB2422_H_
+
+#define REV_USB2422 0x100
+
+#define PORT_DETECT_RETRY_INTERVAL 2000
+
+#define USB_EXTRA_ADC_THRESHOLD 900
+
+#define USB_EXTRA_STATE_DISABLED 0
+#define USB_EXTRA_STATE_ENABLED 1
+#define USB_EXTRA_STATE_UNKNOWN 2
+#define USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG 3
+
+#define USB_HOST_PORT_1 0
+#define USB_HOST_PORT_2 1
+#define USB_HOST_PORT_UNKNOWN 2
+
+extern uint8_t usb_host_port;
+extern uint8_t usb_extra_state;
+extern uint8_t usb_extra_manual;
+extern uint8_t usb_gcr_auto;
+
+void USB_Hub_init(void);
+uint8_t USB_Hub_Port_Detect_Init(void);
+void USB_reset(void);
+void USB_configure(void);
+uint16_t USB_active(void);
+void USB_set_host_by_voltage(void);
+uint16_t adc_get(uint8_t muxpos);
+void USB_HandleExtraDevice(void);
+void USB_ExtraSetState(uint8_t state);
+
+#endif //_USB2422_H_
diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c
index fece8903d2..29a26a9ce8 100644
--- a/tmk_core/protocol/chibios/chibios.c
+++ b/tmk_core/protocol/chibios/chibios.c
@@ -27,6 +27,7 @@
#include "keyboard.h"
#include "action.h"
#include "action_util.h"
+#include "usb_device_state.h"
#include "mousekey.h"
#include "led.h"
#include "sendchar.h"
@@ -42,12 +43,6 @@
#ifdef SLEEP_LED_ENABLE
# include "sleep_led.h"
#endif
-#ifdef SERIAL_LINK_ENABLE
-# include "serial_link/system/serial_link.h"
-#endif
-#ifdef VISUALIZER_ENABLE
-# include "visualizer/visualizer.h"
-#endif
#ifdef MIDI_ENABLE
# include "qmk_midi.h"
#endif
@@ -143,13 +138,15 @@ void boardInit(void) {
}
void protocol_setup(void) {
+ usb_device_state_init();
+
// TESTING
// chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
-
- keyboard_setup();
}
-void protocol_init(void) {
+static host_driver_t *driver = NULL;
+
+void protocol_pre_init(void) {
/* Init USB */
usb_event_queue_init();
init_usb_driver(&USB_DRIVER);
@@ -158,19 +155,9 @@ void protocol_init(void) {
setup_midi();
#endif
-#ifdef SERIAL_LINK_ENABLE
- init_serial_link();
-#endif
-
-#ifdef VISUALIZER_ENABLE
- visualizer_init();
-#endif
-
- host_driver_t *driver = NULL;
-
- /* Wait until the USB or serial link is active */
+ /* Wait until USB is active */
while (true) {
-#if defined(WAIT_FOR_USB) || defined(SERIAL_LINK_ENABLE)
+#if defined(WAIT_FOR_USB)
if (USB_DRIVER.state == USB_ACTIVE) {
driver = &chibios_driver;
break;
@@ -179,13 +166,6 @@ void protocol_init(void) {
driver = &chibios_driver;
break;
#endif
-#ifdef SERIAL_LINK_ENABLE
- if (is_serial_link_connected()) {
- driver = get_serial_link_driver();
- break;
- }
- serial_link_update();
-#endif
wait_ms(50);
}
@@ -197,32 +177,18 @@ void protocol_init(void) {
wait_ms(50);
print("USB configured.\n");
-
- /* init TMK modules */
- keyboard_init();
- host_set_driver(driver);
-
-#ifdef SLEEP_LED_ENABLE
- sleep_led_init();
-#endif
-
- print("Keyboard start.\n");
}
-void protocol_task(void) {
+void protocol_post_init(void) { host_set_driver(driver); }
+
+void protocol_pre_task(void) {
usb_event_queue_task();
#if !defined(NO_USB_STARTUP_CHECK)
if (USB_DRIVER.state == USB_SUSPENDED) {
print("[s]");
-# ifdef VISUALIZER_ENABLE
- visualizer_suspend();
-# endif
while (USB_DRIVER.state == USB_SUSPENDED) {
/* Do this in the suspended state */
-# ifdef SERIAL_LINK_ENABLE
- serial_link_update();
-# endif
suspend_power_down(); // on AVR this deep sleeps for 15ms
/* Remote wakeup */
if (suspend_wakeup_condition()) {
@@ -236,14 +202,11 @@ void protocol_task(void) {
# ifdef MOUSEKEY_ENABLE
mousekey_send();
# endif /* MOUSEKEY_ENABLE */
-
-# ifdef VISUALIZER_ENABLE
- visualizer_resume();
-# endif
}
#endif
+}
- keyboard_task();
+void protocol_post_task(void) {
#ifdef CONSOLE_ENABLE
console_task();
#endif
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index 697566e27a..14de2fc8cc 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -39,6 +39,7 @@
# include "led.h"
#endif
#include "wait.h"
+#include "usb_device_state.h"
#include "usb_descriptor.h"
#include "usb_driver.h"
@@ -74,7 +75,12 @@ uint8_t keyboard_protocol __attribute__((aligned(2))) = 1;
uint8_t keyboard_led_state = 0;
volatile uint16_t keyboard_idle_count = 0;
static virtual_timer_t keyboard_idle_timer;
-static void keyboard_idle_timer_cb(void *arg);
+
+#if CH_KERNEL_MAJOR >= 7
+static void keyboard_idle_timer_cb(struct ch_virtual_timer *, void *arg);
+#elif CH_KERNEL_MAJOR <= 6
+static void keyboard_idle_timer_cb(void *arg);
+#endif
report_keyboard_t keyboard_report_sent = {{0}};
#ifdef MOUSE_ENABLE
@@ -443,6 +449,7 @@ static inline bool usb_event_queue_dequeue(usbevent_t *event) {
}
static inline void usb_event_suspend_handler(void) {
+ usb_device_state_set_suspend(USB_DRIVER.configuration != 0, USB_DRIVER.configuration);
#ifdef SLEEP_LED_ENABLE
sleep_led_enable();
#endif /* SLEEP_LED_ENABLE */
@@ -450,6 +457,7 @@ static inline void usb_event_suspend_handler(void) {
static inline void usb_event_wakeup_handler(void) {
suspend_wakeup_init();
+ usb_device_state_set_resume(USB_DRIVER.configuration != 0, USB_DRIVER.configuration);
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
// NOTE: converters may not accept this
@@ -471,6 +479,15 @@ void usb_event_queue_task(void) {
last_suspend_state = false;
usb_event_wakeup_handler();
break;
+ case USB_EVENT_CONFIGURED:
+ usb_device_state_set_configuration(USB_DRIVER.configuration != 0, USB_DRIVER.configuration);
+ break;
+ case USB_EVENT_UNCONFIGURED:
+ usb_device_state_set_configuration(false, 0);
+ break;
+ case USB_EVENT_RESET:
+ usb_device_state_set_reset();
+ break;
default:
// Nothing to do, we don't handle it.
break;
@@ -513,13 +530,14 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
if (last_suspend_state) {
usb_event_queue_enqueue(USB_EVENT_WAKEUP);
}
+ usb_event_queue_enqueue(USB_EVENT_CONFIGURED);
return;
case USB_EVENT_SUSPEND:
- usb_event_queue_enqueue(USB_EVENT_SUSPEND);
/* Falls into.*/
case USB_EVENT_UNCONFIGURED:
/* Falls into.*/
case USB_EVENT_RESET:
+ usb_event_queue_enqueue(event);
for (int i = 0; i < NUM_USB_DRIVERS; i++) {
chSysLockFromISR();
/* Disconnection event on suspend.*/
@@ -813,7 +831,12 @@ void kbd_sof_cb(USBDriver *usbp) { (void)usbp; }
/* Idle requests timer code
* callback (called from ISR, unlocked state) */
+#if CH_KERNEL_MAJOR >= 7
+static void keyboard_idle_timer_cb(struct ch_virtual_timer *timer, void *arg) {
+ (void)timer;
+#elif CH_KERNEL_MAJOR <= 6
static void keyboard_idle_timer_cb(void *arg) {
+#endif
USBDriver *usbp = (USBDriver *)arg;
osalSysLockFromISR();
@@ -973,6 +996,17 @@ static void send_extra(uint8_t report_id, uint16_t data) {
return;
}
+ if (usbGetTransmitStatusI(&USB_DRIVER, SHARED_IN_EPNUM)) {
+ /* Need to either suspend, or loop and call unlock/lock during
+ * every iteration - otherwise the system will remain locked,
+ * no interrupts served, so USB not going through as well.
+ * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
+ if (osalThreadSuspendTimeoutS(&(&USB_DRIVER)->epc[SHARED_IN_EPNUM]->in_state->thread, TIME_MS2I(10)) == MSG_TIMEOUT) {
+ osalSysUnlock();
+ return;
+ }
+ }
+
static report_extra_t report;
report = (report_extra_t){.report_id = report_id, .usage = data};
@@ -1142,6 +1176,8 @@ void midi_ep_task(void) {
#ifdef VIRTSER_ENABLE
+void virtser_init(void) {}
+
void virtser_send(const uint8_t byte) { chnWrite(&drivers.serial_driver.driver, &byte, 1); }
__attribute__((weak)) void virtser_recv(uint8_t c) {
diff --git a/tmk_core/common/host.c b/tmk_core/protocol/host.c
index f0c396b189..56d4bb0847 100644
--- a/tmk_core/common/host.c
+++ b/tmk_core/protocol/host.c
@@ -30,8 +30,9 @@ extern keymap_config_t keymap_config;
#endif
static host_driver_t *driver;
-static uint16_t last_system_report = 0;
-static uint16_t last_consumer_report = 0;
+static uint16_t last_system_report = 0;
+static uint16_t last_consumer_report = 0;
+static uint32_t last_programmable_button_report = 0;
void host_set_driver(host_driver_t *d) { driver = d; }
@@ -122,6 +123,16 @@ void host_digitizer_send(digitizer_t *digitizer) {
__attribute__((weak)) void send_digitizer(report_digitizer_t *report) {}
+void host_programmable_button_send(uint32_t report) {
+ if (report == last_programmable_button_report) return;
+ last_programmable_button_report = report;
+
+ if (!driver) return;
+ (*driver->send_programmable_button)(report);
+}
+
uint16_t host_last_system_report(void) { return last_system_report; }
uint16_t host_last_consumer_report(void) { return last_consumer_report; }
+
+uint32_t host_last_programmable_button_report(void) { return last_programmable_button_report; }
diff --git a/tmk_core/common/host.h b/tmk_core/protocol/host.h
index 2cffef6e15..6b15f0d0c1 100644
--- a/tmk_core/common/host.h
+++ b/tmk_core/protocol/host.h
@@ -47,9 +47,11 @@ void host_keyboard_send(report_keyboard_t *report);
void host_mouse_send(report_mouse_t *report);
void host_system_send(uint16_t data);
void host_consumer_send(uint16_t data);
+void host_programmable_button_send(uint32_t data);
uint16_t host_last_system_report(void);
uint16_t host_last_consumer_report(void);
+uint32_t host_last_programmable_button_report(void);
#ifdef __cplusplus
}
diff --git a/tmk_core/common/host_driver.h b/tmk_core/protocol/host_driver.h
index 2aebca043d..affd0dcb34 100644
--- a/tmk_core/common/host_driver.h
+++ b/tmk_core/protocol/host_driver.h
@@ -29,6 +29,7 @@ typedef struct {
void (*send_mouse)(report_mouse_t *);
void (*send_system)(uint16_t);
void (*send_consumer)(uint16_t);
+ void (*send_programmable_button)(uint32_t);
} host_driver_t;
void send_digitizer(report_digitizer_t *report); \ No newline at end of file
diff --git a/tmk_core/protocol/ibm4704.c b/tmk_core/protocol/ibm4704.c
deleted file mode 100644
index a19443976e..0000000000
--- a/tmk_core/protocol/ibm4704.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
-Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
-*/
-#include <stdbool.h>
-#include <util/delay.h>
-#include "debug.h"
-#include "ring_buffer.h"
-#include "ibm4704.h"
-
-#define WAIT(stat, us, err) \
- do { \
- if (!wait_##stat(us)) { \
- ibm4704_error = err; \
- goto ERROR; \
- } \
- } while (0)
-
-uint8_t ibm4704_error = 0;
-
-void ibm4704_init(void) {
- inhibit(); // keep keyboard from sending
- IBM4704_INT_INIT();
- IBM4704_INT_ON();
- idle(); // allow keyboard sending
-}
-
-/*
-Host to Keyboard
-----------------
-Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
-
- ____ __ __ __ __ __ __ __ __ __ ________
-Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
- ^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
-Data ____|__/ X____X____X____X____X____X____X____X____X____X \___
- | Start 0 1 2 3 4 5 6 7 P Stop
- Request by host
-
-Start bit: can be long as 300-350us.
-Request: Host pulls Clock line down to request to send a command.
-Timing: After Request keyboard pull up Data and down Clock line to low for start bit.
- After request host release Clock line once Data line becomes hi.
- Host writes a bit while Clock is hi and Keyboard reads while low.
-Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keyboard pull down the line to lo.
-*/
-uint8_t ibm4704_send(uint8_t data) {
- bool parity = true; // odd parity
- ibm4704_error = 0;
-
- IBM4704_INT_OFF();
-
- /* Request to send */
- idle();
- clock_lo();
-
- /* wait for Start bit(Clock:lo/Data:hi) */
- WAIT(data_hi, 300, 0x30);
-
- /* Data bit */
- for (uint8_t i = 0; i < 8; i++) {
- WAIT(clock_hi, 100, 0x40 + i);
- if (data & (1 << i)) {
- parity = !parity;
- data_hi();
- } else {
- data_lo();
- }
- WAIT(clock_lo, 100, 0x48 + i);
- }
-
- /* Parity bit */
- WAIT(clock_hi, 100, 0x34);
- if (parity) {
- data_hi();
- } else {
- data_lo();
- }
- WAIT(clock_lo, 100, 0x35);
-
- /* Stop bit */
- WAIT(clock_hi, 100, 0x34);
- data_hi();
-
- /* End */
- WAIT(data_lo, 100, 0x36);
-
- idle();
- IBM4704_INT_ON();
- return 0;
-ERROR:
- idle();
- if (ibm4704_error > 0x30) {
- xprintf("S:%02X ", ibm4704_error);
- }
- IBM4704_INT_ON();
- return -1;
-}
-
-/* wait forever to receive data */
-uint8_t ibm4704_recv_response(void) {
- while (!rbuf_has_data()) {
- _delay_ms(1);
- }
- return rbuf_dequeue();
-}
-
-uint8_t ibm4704_recv(void) {
- if (rbuf_has_data()) {
- return rbuf_dequeue();
- } else {
- return -1;
- }
-}
-
-/*
-Keyboard to Host
-----------------
-Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
-
- ____ __ __ __ __ __ __ __ __ __ _______
-Clock \_____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
- ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
-Data ____/ X____X____X____X____X____X____X____X____X____X________
- Start 0 1 2 3 4 5 6 7 P Stop
-
-Start bit: can be long as 300-350us.
-Inhibit: Pull Data line down to inhibit keyboard to send.
-Timing: Host reads bit while Clock is hi.(rising edge)
-Stop bit: Keyboard pulls down Data line to lo after 9th clock.
-*/
-ISR(IBM4704_INT_VECT) {
- static enum { BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, STOP } state = BIT0;
- // LSB first
- static uint8_t data = 0;
- // Odd parity
- static uint8_t parity = false;
-
- ibm4704_error = 0;
-
- switch (state) {
- case BIT0:
- case BIT1:
- case BIT2:
- case BIT3:
- case BIT4:
- case BIT5:
- case BIT6:
- case BIT7:
- data >>= 1;
- if (data_in()) {
- data |= 0x80;
- parity = !parity;
- }
- break;
- case PARITY:
- if (data_in()) {
- parity = !parity;
- }
- if (!parity) goto ERROR;
- break;
- case STOP:
- // Data:Low
- WAIT(data_lo, 100, state);
- if (!rbuf_enqueue(data)) {
- print("rbuf: full\n");
- }
- ibm4704_error = IBM4704_ERR_NONE;
- goto DONE;
- break;
- default:
- goto ERROR;
- }
- state++;
- goto RETURN;
-ERROR:
- ibm4704_error = state;
- while (ibm4704_send(0xFE)) _delay_ms(1); // resend
- xprintf("R:%02X%02X\n", state, data);
-DONE:
- state = BIT0;
- data = 0;
- parity = false;
-RETURN:
- return;
-}
diff --git a/tmk_core/protocol/ibm4704.h b/tmk_core/protocol/ibm4704.h
deleted file mode 100644
index 4f88d148b3..0000000000
--- a/tmk_core/protocol/ibm4704.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-Copyright 2014 Jun WAKO <wakojun@gmail.com>
-*/
-
-#pragma once
-
-#define IBM4704_ERR_NONE 0
-#define IBM4704_ERR_PARITY 0x70
-
-void ibm4704_init(void);
-uint8_t ibm4704_send(uint8_t data);
-uint8_t ibm4704_recv_response(void);
-uint8_t ibm4704_recv(void);
-
-/* Check pin configuration */
-#if !(defined(IBM4704_CLOCK_PORT) && defined(IBM4704_CLOCK_PIN) && defined(IBM4704_CLOCK_DDR) && defined(IBM4704_CLOCK_BIT))
-# error "ibm4704 clock pin configuration is required in config.h"
-#endif
-
-#if !(defined(IBM4704_DATA_PORT) && defined(IBM4704_DATA_PIN) && defined(IBM4704_DATA_DDR) && defined(IBM4704_DATA_BIT))
-# error "ibm4704 data pin configuration is required in config.h"
-#endif
-
-/*--------------------------------------------------------------------
- * static functions
- *------------------------------------------------------------------*/
-static inline void clock_lo(void) {
- IBM4704_CLOCK_PORT &= ~(1 << IBM4704_CLOCK_BIT);
- IBM4704_CLOCK_DDR |= (1 << IBM4704_CLOCK_BIT);
-}
-static inline void clock_hi(void) {
- /* input with pull up */
- IBM4704_CLOCK_DDR &= ~(1 << IBM4704_CLOCK_BIT);
- IBM4704_CLOCK_PORT |= (1 << IBM4704_CLOCK_BIT);
-}
-static inline bool clock_in(void) {
- IBM4704_CLOCK_DDR &= ~(1 << IBM4704_CLOCK_BIT);
- IBM4704_CLOCK_PORT |= (1 << IBM4704_CLOCK_BIT);
- _delay_us(1);
- return IBM4704_CLOCK_PIN & (1 << IBM4704_CLOCK_BIT);
-}
-static inline void data_lo(void) {
- IBM4704_DATA_PORT &= ~(1 << IBM4704_DATA_BIT);
- IBM4704_DATA_DDR |= (1 << IBM4704_DATA_BIT);
-}
-static inline void data_hi(void) {
- /* input with pull up */
- IBM4704_DATA_DDR &= ~(1 << IBM4704_DATA_BIT);
- IBM4704_DATA_PORT |= (1 << IBM4704_DATA_BIT);
-}
-static inline bool data_in(void) {
- IBM4704_DATA_DDR &= ~(1 << IBM4704_DATA_BIT);
- IBM4704_DATA_PORT |= (1 << IBM4704_DATA_BIT);
- _delay_us(1);
- return IBM4704_DATA_PIN & (1 << IBM4704_DATA_BIT);
-}
-
-static inline uint16_t wait_clock_lo(uint16_t us) {
- while (clock_in() && us) {
- asm("");
- _delay_us(1);
- us--;
- }
- return us;
-}
-static inline uint16_t wait_clock_hi(uint16_t us) {
- while (!clock_in() && us) {
- asm("");
- _delay_us(1);
- us--;
- }
- return us;
-}
-static inline uint16_t wait_data_lo(uint16_t us) {
- while (data_in() && us) {
- asm("");
- _delay_us(1);
- us--;
- }
- return us;
-}
-static inline uint16_t wait_data_hi(uint16_t us) {
- while (!data_in() && us) {
- asm("");
- _delay_us(1);
- us--;
- }
- return us;
-}
-
-/* idle state that device can send */
-static inline void idle(void) {
- clock_hi();
- data_hi();
-}
-
-/* inhibit device to send
- * keyboard checks Data line on start bit(Data:hi) and it stops sending if Data line is low.
- */
-static inline void inhibit(void) {
- clock_hi();
- data_lo();
-}
diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk
index c8935dacb7..00fec478ac 100644
--- a/tmk_core/protocol/lufa.mk
+++ b/tmk_core/protocol/lufa.mk
@@ -3,7 +3,6 @@ LUFA_DIR = protocol/lufa
# Path to the LUFA library
LUFA_PATH = $(LIB_PATH)/lufa
-
# Create the LUFA source path variables by including the LUFA makefile
ifneq (, $(wildcard $(LUFA_PATH)/LUFA/Build/lufa_sources.mk))
# New build system from 20120730
@@ -22,23 +21,6 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)
include $(TMK_PATH)/protocol/midi.mk
endif
-ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
- LUFA_SRC += outputselect.c \
- $(TMK_DIR)/protocol/serial_uart.c
-endif
-
-ifeq ($(strip $(BLUETOOTH)), AdafruitBLE)
- LUFA_SRC += spi_master.c \
- analog.c \
- outputselect.c \
- $(LUFA_DIR)/adafruit_ble.cpp
-endif
-
-ifeq ($(strip $(BLUETOOTH)), RN42)
- LUFA_SRC += outputselect.c \
- $(TMK_DIR)/protocol/serial_uart.c
-endif
-
ifeq ($(strip $(VIRTSER_ENABLE)), yes)
LUFA_SRC += $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c
endif
@@ -50,19 +32,10 @@ SRC += $(LUFA_DIR)/usb_util.c
VPATH += $(TMK_PATH)/$(LUFA_DIR)
VPATH += $(LUFA_PATH)
-# Option modules
-#ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
-#endif
-
-#ifdef EXTRAKEY_ENABLE
-#endif
-
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -DUSB_DEVICE_ONLY
LUFA_OPTS += -DUSE_FLASH_DESCRIPTORS
LUFA_OPTS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
-#LUFA_OPTS += -DINTERRUPT_CONTROL_ENDPOINT
-LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 92070a8fa3..3804d54375 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -52,6 +52,7 @@
#include "usb_descriptor.h"
#include "lufa.h"
#include "quantum.h"
+#include "usb_device_state.h"
#include <util/atomic.h>
#ifdef NKRO_ENABLE
@@ -145,7 +146,8 @@ static void send_keyboard(report_keyboard_t *report);
static void send_mouse(report_mouse_t *report);
static void send_system(uint16_t data);
static void send_consumer(uint16_t data);
-host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
+static void send_programmable_button(uint32_t data);
+host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};
#ifdef VIRTSER_ENABLE
// clang-format off
@@ -476,7 +478,10 @@ void EVENT_USB_Device_Disconnect(void) {
*
* FIXME: Needs doc
*/
-void EVENT_USB_Device_Reset(void) { print("[R]"); }
+void EVENT_USB_Device_Reset(void) {
+ print("[R]");
+ usb_device_state_set_reset();
+}
/** \brief Event USB Device Connect
*
@@ -484,6 +489,8 @@ void EVENT_USB_Device_Reset(void) { print("[R]"); }
*/
void EVENT_USB_Device_Suspend() {
print("[S]");
+ usb_device_state_set_suspend(USB_Device_ConfigurationNumber != 0, USB_Device_ConfigurationNumber);
+
#ifdef SLEEP_LED_ENABLE
sleep_led_enable();
#endif
@@ -499,6 +506,8 @@ void EVENT_USB_Device_WakeUp() {
suspend_wakeup_init();
#endif
+ usb_device_state_set_resume(USB_DeviceState == DEVICE_STATE_Configured, USB_Device_ConfigurationNumber);
+
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
// NOTE: converters may not accept this
@@ -597,6 +606,8 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
/* Setup digitizer endpoint */
ConfigSuccess &= Endpoint_ConfigureEndpoint((DIGITIZER_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, DIGITIZER_EPSIZE, 1);
#endif
+
+ usb_device_state_set_configuration(USB_DeviceState == DEVICE_STATE_Configured, USB_Device_ConfigurationNumber);
}
/* FIXME: Expose this table in the docs somehow
@@ -871,29 +882,35 @@ static void send_mouse(report_mouse_t *report) {
#endif
}
-/** \brief Send Extra
- *
- * FIXME: Needs doc
- */
-#ifdef EXTRAKEY_ENABLE
-static void send_extra(uint8_t report_id, uint16_t data) {
+#if defined(EXTRAKEY_ENABLE) || defined(PROGRAMMABLE_BUTTON_ENABLE)
+static void send_report(void *report, size_t size) {
uint8_t timeout = 255;
if (USB_DeviceState != DEVICE_STATE_Configured) return;
- static report_extra_t r;
- r = (report_extra_t){.report_id = report_id, .usage = data};
Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
/* Check if write ready for a polling interval around 10ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
- Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
+ Endpoint_Write_Stream_LE(report, size, NULL);
Endpoint_ClearIN();
}
#endif
+/** \brief Send Extra
+ *
+ * FIXME: Needs doc
+ */
+#ifdef EXTRAKEY_ENABLE
+static void send_extra(uint8_t report_id, uint16_t data) {
+ static report_extra_t r;
+ r = (report_extra_t){.report_id = report_id, .usage = data};
+ send_report(&r, sizeof(r));
+}
+#endif
+
/** \brief Send System
*
* FIXME: Needs doc
@@ -945,6 +962,14 @@ static void send_consumer(uint16_t data) {
#endif
}
+static void send_programmable_button(uint32_t data) {
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ static report_programmable_button_t r;
+ r = (report_programmable_button_t){.report_id = REPORT_ID_PROGRAMMABLE_BUTTON, .usage = data};
+ send_report(&r, sizeof(r));
+#endif
+}
+
/*******************************************************************************
* sendchar
******************************************************************************/
@@ -1171,10 +1196,10 @@ void protocol_setup(void) {
#endif
setup_mcu();
- keyboard_setup();
+ usb_device_state_init();
}
-void protocol_init(void) {
+void protocol_pre_init(void) {
setup_usb();
sei();
@@ -1196,21 +1221,11 @@ void protocol_init(void) {
#else
USB_USBTask();
#endif
- /* init modules */
- keyboard_init();
- host_set_driver(&lufa_driver);
-#ifdef SLEEP_LED_ENABLE
- sleep_led_init();
-#endif
-
-#ifdef VIRTSER_ENABLE
- virtser_init();
-#endif
-
- print("Keyboard start.\n");
}
-void protocol_task(void) {
+void protocol_post_init(void) { host_set_driver(&lufa_driver); }
+
+void protocol_pre_task(void) {
#if !defined(NO_USB_STARTUP_CHECK)
if (USB_DeviceState == DEVICE_STATE_Suspended) {
print("[s]");
@@ -1234,9 +1249,9 @@ void protocol_task(void) {
suspend_wakeup_init();
}
#endif
+}
- keyboard_task();
-
+void protocol_post_task(void) {
#ifdef MIDI_ENABLE
MIDI_Device_USBTask(&USB_MIDI_Interface);
#endif
diff --git a/tmk_core/protocol/lufa/lufa.h b/tmk_core/protocol/lufa/lufa.h
index 348a84c031..6a5205609e 100644
--- a/tmk_core/protocol/lufa/lufa.h
+++ b/tmk_core/protocol/lufa/lufa.h
@@ -56,14 +56,3 @@ extern host_driver_t lufa_driver;
#ifdef __cplusplus
}
#endif
-
-#ifdef API_ENABLE
-# include "api.h"
-#endif
-
-#ifdef API_SYSEX_ENABLE
-# include "api_sysex.h"
-// Allocate space for encoding overhead.
-// The header and terminator are not stored to save a few bytes of precious ram
-# define MIDI_SYSEX_BUFFER (API_SYSEX_MAX_SIZE + API_SYSEX_MAX_SIZE / 7 + (API_SYSEX_MAX_SIZE % 7 ? 1 : 0))
-#endif
diff --git a/tmk_core/protocol/m0110.c b/tmk_core/protocol/m0110.c
deleted file mode 100644
index 64f2fa50ab..0000000000
--- a/tmk_core/protocol/m0110.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
-Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-/* M0110A Support was contributed by skagon@github */
-
-#include <stdbool.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <util/delay.h>
-#include "m0110.h"
-#include "debug.h"
-
-static inline uint8_t raw2scan(uint8_t raw);
-static inline uint8_t inquiry(void);
-static inline uint8_t instant(void);
-static inline void clock_lo(void);
-static inline void clock_hi(void);
-static inline bool clock_in(void);
-static inline void data_lo(void);
-static inline void data_hi(void);
-static inline bool data_in(void);
-static inline uint16_t wait_clock_lo(uint16_t us);
-static inline uint16_t wait_clock_hi(uint16_t us);
-static inline uint16_t wait_data_lo(uint16_t us);
-static inline uint16_t wait_data_hi(uint16_t us);
-static inline void idle(void);
-static inline void request(void);
-
-#define WAIT_US(stat, us, err) \
- do { \
- if (!wait_##stat(us)) { \
- m0110_error = err; \
- goto ERROR; \
- } \
- } while (0)
-
-#define WAIT_MS(stat, ms, err) \
- do { \
- uint16_t _ms = ms; \
- while (_ms) { \
- if (wait_##stat(1000)) { \
- break; \
- } \
- _ms--; \
- } \
- if (_ms == 0) { \
- m0110_error = err; \
- goto ERROR; \
- } \
- } while (0)
-
-#define KEY(raw) ((raw)&0x7f)
-#define IS_BREAK(raw) (((raw)&0x80) == 0x80)
-
-uint8_t m0110_error = 0;
-
-void m0110_init(void) {
- idle();
- _delay_ms(1000);
-
- /* Not needed to initialize in fact.
- uint8_t data;
- m0110_send(M0110_MODEL);
- data = m0110_recv();
- print("m0110_init model: "); print_hex8(data); print("\n");
-
- m0110_send(M0110_TEST);
- data = m0110_recv();
- print("m0110_init test: "); print_hex8(data); print("\n");
- */
-}
-
-uint8_t m0110_send(uint8_t data) {
- m0110_error = 0;
-
- request();
- WAIT_MS(clock_lo, 250, 1); // keyboard may block long time
- for (uint8_t bit = 0x80; bit; bit >>= 1) {
- WAIT_US(clock_lo, 250, 3);
- if (data & bit) {
- data_hi();
- } else {
- data_lo();
- }
- WAIT_US(clock_hi, 200, 4);
- }
- _delay_us(100); // hold last bit for 80us
- idle();
- return 1;
-ERROR:
- print("m0110_send err: ");
- print_hex8(m0110_error);
- print("\n");
- _delay_ms(500);
- idle();
- return 0;
-}
-
-uint8_t m0110_recv(void) {
- uint8_t data = 0;
- m0110_error = 0;
-
- WAIT_MS(clock_lo, 250, 1); // keyboard may block long time
- for (uint8_t i = 0; i < 8; i++) {
- data <<= 1;
- WAIT_US(clock_lo, 200, 2);
- WAIT_US(clock_hi, 200, 3);
- if (data_in()) {
- data |= 1;
- }
- }
- idle();
- return data;
-ERROR:
- print("m0110_recv err: ");
- print_hex8(m0110_error);
- print("\n");
- _delay_ms(500);
- idle();
- return 0xFF;
-}
-
-/*
-Handling for exceptional case of key combinations for M0110A
-
-Shift and Calc/Arrow key could be operated simultaneously:
-
- Case Shift Arrow Events Interpret
- -------------------------------------------------------------------
- 1 Down Down 71, 79, DD Calc(d)*a *b
- 2 Down Up 71, 79, UU Arrow&Calc(u)*a
- 3 Up Down F1, 79, DD Shift(u) *c
- 4 Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a
-
- Case Shift Calc Events Interpret
- -------------------------------------------------------------------
- 5(1) Down Down 71, 71, 79, DD Shift(d) and Cacl(d)
- 6(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a
- 7(1) Up Down F1, 71, 79, DD Shift(u) and Calc(d)
- 8(4) Up Up F1, F1, 79, UU Shift(ux2) and Arrow&Calc(u)*a
-
-During Calc key is hold:
- Case Shift Arrow Events Interpret
- -------------------------------------------------------------------
- A(3) ---- Down F1, 79, DD Shift(u) *c
- B ---- Up 79, UU Arrow&Calc(u)*a
- C Down ---- F1, 71 Shift(u) and Shift(d)
- D Up ---- F1 Shift(u)
- E Hold Down 79, DD Normal
- F Hold Up 79, UU Arrow&Calc(u)*a
- G(1) Down Down F1, 71, 79, DD Shift(u)*b and Calc(d)*a
- H(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a
- I(3) Up Down F1, F1, 79, DD Shift(ux2) *c
- J(4) Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a
-
- Case Shift Calc Events Interpret
- -------------------------------------------------------------------
- K(1) ---- Down 71, 79, DD Calc(d)*a
- L(4) ---- Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a
- M(1) Hold Down 71, 79, DD Calc(d)*a
- N Hold Up 79, UU Arrow&Calc(u)*a
-
- Where DD/UU indicates part of Keypad Down/Up event.
- *a: Impossible to distinguish btween Arrow and Calc event.
- *b: Shift(d) event is ignored.
- *c: Arrow/Calc(d) event is ignored.
-*/
-uint8_t m0110_recv_key(void) {
- static uint8_t keybuf = 0x00;
- static uint8_t keybuf2 = 0x00;
- static uint8_t rawbuf = 0x00;
- uint8_t raw, raw2, raw3;
-
- if (keybuf) {
- raw = keybuf;
- keybuf = 0x00;
- return raw;
- }
- if (keybuf2) {
- raw = keybuf2;
- keybuf2 = 0x00;
- return raw;
- }
-
- if (rawbuf) {
- raw = rawbuf;
- rawbuf = 0x00;
- } else {
- raw = instant(); // Use INSTANT for better response. Should be INQUIRY ?
- }
- switch (KEY(raw)) {
- case M0110_KEYPAD:
- raw2 = instant();
- switch (KEY(raw2)) {
- case M0110_ARROW_UP:
- case M0110_ARROW_DOWN:
- case M0110_ARROW_LEFT:
- case M0110_ARROW_RIGHT:
- if (IS_BREAK(raw2)) {
- // Case B,F,N:
- keybuf = (raw2scan(raw2) | M0110_CALC_OFFSET); // Calc(u)
- return (raw2scan(raw2) | M0110_KEYPAD_OFFSET); // Arrow(u)
- }
- break;
- }
- // Keypad or Arrow
- return (raw2scan(raw2) | M0110_KEYPAD_OFFSET);
- break;
- case M0110_SHIFT:
- raw2 = instant();
- switch (KEY(raw2)) {
- case M0110_SHIFT:
- // Case: 5-8,C,G,H
- rawbuf = raw2;
- return raw2scan(raw); // Shift(d/u)
- break;
- case M0110_KEYPAD:
- // Shift + Arrow, Calc, or etc.
- raw3 = instant();
- switch (KEY(raw3)) {
- case M0110_ARROW_UP:
- case M0110_ARROW_DOWN:
- case M0110_ARROW_LEFT:
- case M0110_ARROW_RIGHT:
- if (IS_BREAK(raw)) {
- if (IS_BREAK(raw3)) {
- // Case 4:
- print("(4)\n");
- keybuf2 = raw2scan(raw); // Shift(u)
- keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u)
- return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u)
- } else {
- // Case 3:
- print("(3)\n");
- return (raw2scan(raw)); // Shift(u)
- }
- } else {
- if (IS_BREAK(raw3)) {
- // Case 2:
- print("(2)\n");
- keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u)
- return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u)
- } else {
- // Case 1:
- print("(1)\n");
- return (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(d)
- }
- }
- break;
- default:
- // Shift + Keypad
- keybuf = (raw2scan(raw3) | M0110_KEYPAD_OFFSET);
- return raw2scan(raw); // Shift(d/u)
- break;
- }
- break;
- default:
- // Shift + Normal keys
- keybuf = raw2scan(raw2);
- return raw2scan(raw); // Shift(d/u)
- break;
- }
- break;
- default:
- // Normal keys
- return raw2scan(raw);
- break;
- }
-}
-
-static inline uint8_t raw2scan(uint8_t raw) { return (raw == M0110_NULL) ? M0110_NULL : ((raw == M0110_ERROR) ? M0110_ERROR : (((raw & 0x80) | ((raw & 0x7F) >> 1)))); }
-
-static inline uint8_t inquiry(void) {
- m0110_send(M0110_INQUIRY);
- return m0110_recv();
-}
-
-static inline uint8_t instant(void) {
- m0110_send(M0110_INSTANT);
- uint8_t data = m0110_recv();
- if (data != M0110_NULL) {
- debug_hex(data);
- debug(" ");
- }
- return data;
-}
-
-static inline void clock_lo() {
- M0110_CLOCK_PORT &= ~(1 << M0110_CLOCK_BIT);
- M0110_CLOCK_DDR |= (1 << M0110_CLOCK_BIT);
-}
-static inline void clock_hi() {
- /* input with pull up */
- M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT);
- M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT);
-}
-static inline bool clock_in() {
- M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT);
- M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT);
- _delay_us(1);
- return M0110_CLOCK_PIN & (1 << M0110_CLOCK_BIT);
-}
-static inline void data_lo() {
- M0110_DATA_PORT &= ~(1 << M0110_DATA_BIT);
- M0110_DATA_DDR |= (1 << M0110_DATA_BIT);
-}
-static inline void data_hi() {
- /* input with pull up */
- M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT);
- M0110_DATA_PORT |= (1 << M0110_DATA_BIT);
-}
-static inline bool data_in() {
- M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT);
- M0110_DATA_PORT |= (1 << M0110_DATA_BIT);
- _delay_us(1);
- return M0110_DATA_PIN & (1 << M0110_DATA_BIT);
-}
-
-static inline uint16_t wait_clock_lo(uint16_t us) {
- while (clock_in() && us) {
- asm("");
- _delay_us(1);
- us--;
- }
- return us;
-}
-static inline uint16_t wait_clock_hi(uint16_t us) {
- while (!clock_in() && us) {
- asm("");
- _delay_us(1);
- us--;
- }
- return us;
-}
-static inline uint16_t wait_data_lo(uint16_t us) {
- while (data_in() && us) {
- asm("");
- _delay_us(1);
- us--;
- }
- return us;
-}
-static inline uint16_t wait_data_hi(uint16_t us) {
- while (!data_in() && us) {
- asm("");
- _delay_us(1);
- us--;
- }
- return us;
-}
-
-static inline void idle(void) {
- clock_hi();
- data_hi();
-}
-
-static inline void request(void) {
- clock_hi();
- data_lo();
-}
-
-/*
-Primitive M0110 Library for AVR
-==============================
-
-
-Signaling
----------
-CLOCK is always from KEYBOARD. DATA are sent with MSB first.
-
-1) IDLE: both lines are high.
- CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- DATA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-2) KEYBOARD->HOST: HOST reads bit on rising edge.
- CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
- DATA ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
- <--> 160us(clock low)
- <---> 180us(clock high)
-
-3) HOST->KEYBOARD: HOST asserts bit on falling edge.
- CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
- DATA ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
- <----> 840us(request to send by host) <---> 80us(hold DATA)
- <--> 180us(clock low)
- <---> 220us(clock high)
-
-
-Protocol
---------
-COMMAND:
- Inquiry 0x10 get key event with block
- Instant 0x12 get key event
- Model 0x14 get model number(M0110 responds with 0x09)
- bit 7 1 if another device connected(used when keypad exists?)
- bit4-6 next device model number
- bit1-3 keyboard model number
- bit 0 always 1
- Test 0x16 test(ACK:0x7D/NAK:0x77)
-
-KEY EVENT:
- bit 7 key state(0:press 1:release)
- bit 6-1 scan code(see below)
- bit 0 always 1
- To get scan code use this: ((bits&(1<<7)) | ((bits&0x7F))>>1).
-
- Note: On the M0110A, Keypad keys and Arrow keys are preceded by 0x79.
- Moreover, some Keypad keys(=, /, * and +) are preceded by 0x71 on press and 0xF1 on release.
-
-ARROW KEYS:
- Arrow keys and Calc keys(+,*,/,= on keypad) share same byte sequence and preceding byte of
- Calc keys(0x71 and 0xF1) means press and release event of SHIFT. This causes a very confusing situation,
- it is difficult or impossible to tell Calc key from Arrow key plus SHIFT in some cases.
-
- Raw key events:
- press release
- ---------------- ----------------
- Left: 0x79, 0x0D 0x79, 0x8D
- Right: 0x79, 0x05 0x79, 0x85
- Up: 0x79, 0x1B 0x79, 0x9B
- Down: 0x79, 0x11 0x79, 0x91
- Pad+: 0x71, 0x79, 0x0D 0xF1, 0x79, 0x8D
- Pad*: 0x71, 0x79, 0x05 0xF1, 0x79, 0x85
- Pad/: 0x71, 0x79, 0x1B 0xF1, 0x79, 0x9B
- Pad=: 0x71, 0x79, 0x11 0xF1, 0x79, 0x91
-
-
-RAW CODE:
- M0110A
- ,---------------------------------------------------------. ,---------------.
- | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *|
- |---------------------------------------------------------| |---------------|
- |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -|
- |-----------------------------------------------------' | |---------------|
- |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +|
- |---------------------------------------------------------| |---------------|
- |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| |
- |---------------------------------------------------------' |-----------|Ent|
- |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| |
- `---------------------------------------------------------' `---------------'
- ,---------------------------------------------------------. ,---------------.
- | 65| 25| 27| 29| 2B| 2F| 2D| 35| 39| 33| 3B| 37| 31| 67| |+0F|*11|*1B|*05|
- |---------------------------------------------------------| |---------------|
- | 61| 19| 1B| 1D| 1F| 23| 21| 41| 45| 3F| 47| 43| 3D| | |+33|+37|+39|+1D|
- |-----------------------------------------------------' | |---------------|
- | 73| 01| 03| 05| 07| 0B| 09| 4D| 51| 4B| 53| 4F| 49| |+2D|+2F|+31|*0D|
- |---------------------------------------------------------| |---------------|
- | 71| 0D| 0F| 11| 13| 17| 5B| 5D| 27| 5F| 59| 71|+1B| |+27|+29|+2B| |
- |---------------------------------------------------------' |-----------|+19|
- | 75| 6F| 63 | 55|+0D|+05|+11| | +25|+03| |
- `---------------------------------------------------------' `---------------'
- + 0x79, 0xDD / 0xF1, 0xUU
- * 0x71, 0x79,DD / 0xF1, 0x79, 0xUU
-
-
-MODEL NUMBER:
- M0110: 0x09 00001001 : model number 4 (100)
- M0110A: 0x0B 00001011 : model number 5 (101)
- M0110 & M0120: ???
-
-
-Scan Code
----------
- m0110_recv_key() function returns following scan codes instead of M0110 raw codes.
- Scan codes are 1 byte size and MSB(bit7) is set when key is released.
-
- scancode = ((raw&0x80) | ((raw&0x7F)>>1))
-
- M0110 M0120
- ,---------------------------------------------------------. ,---------------.
- | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Clr| -|Lft|Rgt|
- |---------------------------------------------------------| |---------------|
- |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | 7| 8| 9|Up |
- |---------------------------------------------------------| |---------------|
- |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6|Dn |
- |---------------------------------------------------------| |---------------|
- |Shift | Z| X| C| V| B| N| M| ,| ,| /| | | 1| 2| 3| |
- `---------------------------------------------------------' |-----------|Ent|
- |Opt|Mac | Space |Enter|Opt| | 0| .| |
- `------------------------------------------------' `---------------'
- ,---------------------------------------------------------. ,---------------.
- | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 4E| 46| 42|
- |---------------------------------------------------------| |---------------|
- | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| | 59| 5B| 5C| 4D|
- |---------------------------------------------------------| |---------------|
- | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 48|
- |---------------------------------------------------------| |---------------|
- | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| | 53| 54| 55| |
- `---------------------------------------------------------' |-----------| 4C|
- | 3A| 37| 31 | 34| 3A| | 52| 41| |
- `------------------------------------------------' `---------------'
-
- International keyboard(See page 22 of "Technical Info for 128K/512K")
- ,---------------------------------------------------------.
- | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33|
- |---------------------------------------------------------|
- | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A|
- |------------------------------------------------------ |
- | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| |
- |---------------------------------------------------------|
- | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 0A| 38|
- `---------------------------------------------------------'
- | 3A| 37| 34 | 31| 3A|
- `------------------------------------------------'
-
- M0110A
- ,---------------------------------------------------------. ,---------------.
- | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *|
- |---------------------------------------------------------| |---------------|
- |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -|
- |-----------------------------------------------------' | |---------------|
- |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +|
- |---------------------------------------------------------| |---------------|
- |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| |
- |---------------------------------------------------------' |-----------|Ent|
- |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| |
- `---------------------------------------------------------' `---------------'
- ,---------------------------------------------------------. ,---------------.
- | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 68| 6D| 62|
- |---------------------------------------------------------| |---------------|
- | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| | | 59| 5B| 5C| 4E|
- |-----------------------------------------------------' | |---------------|
- | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 66|
- |---------------------------------------------------------| |---------------|
- | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| 4D| | 53| 54| 55| |
- |---------------------------------------------------------' |-----------| 4C|
- | 3A| 37| 31 | 2A| 46| 42| 48| | 52| 41| |
- `---------------------------------------------------------' `---------------'
-
-
-References
-----------
-Technical Info for 128K/512K and Plus
- ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf
- ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf
-Protocol:
- Page 20 of Tech Info for 128K/512K
- http://www.mac.linux-m68k.org/devel/plushw.php
-Connector:
- Page 20 of Tech Info for 128K/512K
- http://www.kbdbabel.org/conn/kbd_connector_macplus.png
-Signaling:
- http://www.kbdbabel.org/signaling/kbd_signaling_mac.png
- http://typematic.blog.shinobi.jp/Entry/14/
-M0110 raw scan codes:
- Page 22 of Tech Info for 128K/512K
- Page 07 of Tech Info for Plus
- http://m0115.web.fc2.com/m0110.jpg
- http://m0115.web.fc2.com/m0110a.jpg
-*/
diff --git a/tmk_core/protocol/m0110.h b/tmk_core/protocol/m0110.h
deleted file mode 100644
index 63ff3e90ec..0000000000
--- a/tmk_core/protocol/m0110.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#pragma once
-
-/* port settings for clock and data line */
-#if !(defined(M0110_CLOCK_PORT) && defined(M0110_CLOCK_PIN) && defined(M0110_CLOCK_DDR) && defined(M0110_CLOCK_BIT))
-# error "M0110 clock port setting is required in config.h"
-#endif
-
-#if !(defined(M0110_DATA_PORT) && defined(M0110_DATA_PIN) && defined(M0110_DATA_DDR) && defined(M0110_DATA_BIT))
-# error "M0110 data port setting is required in config.h"
-#endif
-
-/* Commands */
-#define M0110_INQUIRY 0x10
-#define M0110_INSTANT 0x14
-#define M0110_MODEL 0x16
-#define M0110_TEST 0x36
-
-/* Response(raw byte from M0110) */
-#define M0110_NULL 0x7B
-#define M0110_KEYPAD 0x79
-#define M0110_TEST_ACK 0x7D
-#define M0110_TEST_NAK 0x77
-#define M0110_SHIFT 0x71
-#define M0110_ARROW_UP 0x1B
-#define M0110_ARROW_DOWN 0x11
-#define M0110_ARROW_LEFT 0x0D
-#define M0110_ARROW_RIGHT 0x05
-
-/* This inidcates no response. */
-#define M0110_ERROR 0xFF
-
-/* scan code offset for keypad and arrow keys */
-#define M0110_KEYPAD_OFFSET 0x40
-#define M0110_CALC_OFFSET 0x60
-
-extern uint8_t m0110_error;
-
-/* host role */
-void m0110_init(void);
-uint8_t m0110_send(uint8_t data);
-uint8_t m0110_recv(void);
-uint8_t m0110_recv_key(void);
-uint8_t m0110_inquiry(void);
-uint8_t m0110_instant(void);
diff --git a/tmk_core/protocol/midi/qmk_midi.c b/tmk_core/protocol/midi/qmk_midi.c
index c18dbf9930..3a454d61ae 100644
--- a/tmk_core/protocol/midi/qmk_midi.c
+++ b/tmk_core/protocol/midi/qmk_midi.c
@@ -4,9 +4,6 @@
#include "midi.h"
#include "usb_descriptor.h"
#include "process_midi.h"
-#if API_SYSEX_ENABLE
-# include "api_sysex.h"
-#endif
/*******************************************************************************
* MIDI
@@ -124,41 +121,6 @@ static void cc_callback(MidiDevice* device, uint8_t chan, uint8_t num, uint8_t v
// midi_send_cc(device, (chan + 1) % 16, num, val);
}
-#ifdef API_SYSEX_ENABLE
-uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0};
-
-static void sysex_callback(MidiDevice* device, uint16_t start, uint8_t length, uint8_t* data) {
- // SEND_STRING("\n");
- // send_word(start);
- // SEND_STRING(": ");
- // Don't store the header
- int16_t pos = start - 4;
- for (uint8_t place = 0; place < length; place++) {
- // send_byte(*data);
- if (pos >= 0) {
- if (*data == 0xF7) {
- // SEND_STRING("\nRD: ");
- // for (uint8_t i = 0; i < start + place + 1; i++){
- // send_byte(midi_buffer[i]);
- // SEND_STRING(" ");
- // }
- const unsigned decoded_length = sysex_decoded_length(pos);
- uint8_t decoded[API_SYSEX_MAX_SIZE];
- sysex_decode(decoded, midi_buffer, pos);
- process_api(decoded_length, decoded);
- return;
- } else if (pos >= MIDI_SYSEX_BUFFER) {
- return;
- }
- midi_buffer[pos] = *data;
- }
- // SEND_STRING(" ");
- data++;
- pos++;
- }
-}
-#endif
-
void midi_init(void);
void setup_midi(void) {
@@ -170,7 +132,4 @@ void setup_midi(void) {
midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
midi_register_cc_callback(&midi_device, cc_callback);
-#ifdef API_SYSEX_ENABLE
- midi_register_sysex_callback(&midi_device, sysex_callback);
-#endif
}
diff --git a/tmk_core/protocol/news.c b/tmk_core/protocol/news.c
deleted file mode 100644
index 4463e8dd42..0000000000
--- a/tmk_core/protocol/news.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
-Copyright 2012 Jun WAKO <wakojun@gmail.com>
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdbool.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include "news.h"
-
-void news_init(void) { NEWS_KBD_RX_INIT(); }
-
-// RX ring buffer
-#define RBUF_SIZE 8
-static uint8_t rbuf[RBUF_SIZE];
-static uint8_t rbuf_head = 0;
-static uint8_t rbuf_tail = 0;
-
-uint8_t news_recv(void) {
- uint8_t data = 0;
- if (rbuf_head == rbuf_tail) {
- return 0;
- }
-
- data = rbuf[rbuf_tail];
- rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
- return data;
-}
-
-// USART RX complete interrupt
-ISR(NEWS_KBD_RX_VECT) {
- uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
- if (next != rbuf_tail) {
- rbuf[rbuf_head] = NEWS_KBD_RX_DATA;
- rbuf_head = next;
- }
-}
-
-/*
-SONY NEWS Keyboard Protocol
-===========================
-
-Resources
----------
- Mouse protocol of NWA-5461(Japanese)
- http://groups.google.com/group/fj.sys.news/browse_thread/thread/a01b3e3ac6ae5b2d
-
- SONY NEWS Info(Japanese)
- http://katsu.watanabe.name/doc/sonynews/
-
-
-Pinouts
--------
- EIA 232 male connector from NWP-5461
- -------------
- \ 1 2 3 4 5 /
- \ 6 7 8 9 /
- ---------
- 1 VCC
- 2 BZ(Speaker)
- 3 Keyboard Data(from keyboard MCU TxD)
- 4 NC
- 5 GND
- 6 Unknown Input(to keyboard MCU RxD via schmitt trigger)
- 7 Mouse Data(from Mouse Ext connector)
- 8 Unknown Input(to Keyboard MCU Input via diode and buffer)
- 9 FG
- NOTE: Two LED on keyboard are controlled by pin 6,8?
-
- EIA 232 male connector from NWP-411A
- -------------
- \ 1 2 3 4 5 /
- \ 6 7 8 9 /
- ---------
- 1 VCC
- 2 BZ(Speaker)
- 3 Keyboard Data(from keyboard MCU TxD)
- 4 NC
- 5 GND
- 6 NC
- 7 Mouse Data(from Mouse Ext connector)
- 8 NC
- 9 FG
- NOTE: These are just from my guess and not confirmed.
-
-
-Signaling
----------
- ~~~~~~~~~~ ____XOO0X111X222X333X444X555X666X777~~~~ ~~~~~~~
- Idle Start LSB MSB Stop Idle
-
- Idle: High
- Start bit: Low
- Stop bit: High
- Bit order: LSB first
-
- Baud rate: 9600
- Interface: TTL level(5V) UART
-
- NOTE: This is observed on NWP-5461 with its DIP switch all OFF.
-
-
-Format
-------
- MSB LSB
- 7 6 5 4 3 2 1 0 bit
- | | | | | | | |
- | +-+-+-+-+-+-+-- scan code(00-7F)
- +---------------- break flag: sets when released
-
-
-Scan Codes
-----------
- SONY NEWS NWP-5461
- ,---. ,------------------------, ,------------------------. ,---------.
- | 7A| | 01 | 02 | 03 | 04 | 05 | | 06 | 07 | 08 | 09 | 0A | | 68 | 69 | ,-----------.
- `---' `------------------------' `------------------------' `---------' | 64| 65| 52|
- ,-------------------------------------------------------------. ,---. ,---------------|
- | 0B| 0C| 0D| 0E| 0F| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19 | | 6A| | 4B| 4C| 4D| 4E|
- |-------------------------------------------------------------| |---| |---------------|
- | 1A | 1B| 1C| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| | | 6B| | 4F| 50| 51| 56|
- |---------------------------------------------------------' | |---| |---------------|
- | 28 | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 35 | | 6C| | 53| 54| 55| |
- |-------------------------------------------------------------| |---| |-----------| 5A|
- | 36 | 37| 38| 39| 3A| 3B| 3C| 3D| 3E| 3F| 40| 41| 42 | | 6D| | 57| 59| 58| |
- |-------------------------------------------------------------| |---| |---------------|
- | 43 | 44 | 45 | 46 | 47 | 48| 49| 4A | | 6E| | 66| 5B| 5C| 5D|
- `-------------------------------------------------------------' `---' `---------------'
-*/
diff --git a/tmk_core/protocol/news.h b/tmk_core/protocol/news.h
deleted file mode 100644
index 327a13856d..0000000000
--- a/tmk_core/protocol/news.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-Copyright 2012 Jun WAKO <wakojun@gmail.com>
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#pragma once
-
-/*
- * Primitive PS/2 Library for AVR
- */
-
-/* host role */
-void news_init(void);
-uint8_t news_recv(void);
-
-/* device role */
diff --git a/tmk_core/protocol/next_kbd.c b/tmk_core/protocol/next_kbd.c
deleted file mode 100644
index 6f118e6172..0000000000
--- a/tmk_core/protocol/next_kbd.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
-
-NeXT non-ADB Keyboard Protocol
-
-Copyright 2013, Benjamin Gould (bgould@github.com)
-
-Based on:
-TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
-Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
-
-Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
-Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
-Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-*/
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <util/atomic.h>
-#include <util/delay.h>
-#include "next_kbd.h"
-#include "debug.h"
-
-static inline void out_lo(void);
-static inline void out_hi(void);
-static inline void query(void);
-static inline void reset(void);
-static inline uint32_t response(void);
-
-/* The keyboard sends signal with 50us pulse width on OUT line
- * while it seems to miss the 50us pulse on In line.
- * next_kbd_set_leds() often fails to sync LED status with 50us
- * but it works well with 51us(+1us) on TMK converter(ATMeaga32u2) at least.
- * TODO: test on Teensy and Pro Micro configuration
- */
-#define out_hi_delay(intervals) \
- do { \
- out_hi(); \
- _delay_us((NEXT_KBD_TIMING + 1) * intervals); \
- } while (0);
-#define out_lo_delay(intervals) \
- do { \
- out_lo(); \
- _delay_us((NEXT_KBD_TIMING + 1) * intervals); \
- } while (0);
-#define query_delay(intervals) \
- do { \
- query(); \
- _delay_us((NEXT_KBD_TIMING + 1) * intervals); \
- } while (0);
-#define reset_delay(intervals) \
- do { \
- reset(); \
- _delay_us((NEXT_KBD_TIMING + 1) * intervals); \
- } while (0);
-
-void next_kbd_init(void) {
- out_hi();
- NEXT_KBD_IN_DDR &= ~(1 << NEXT_KBD_IN_BIT); // KBD_IN to input
- NEXT_KBD_IN_PORT |= (1 << NEXT_KBD_IN_BIT); // KBD_IN pull up
-
- query_delay(5);
- reset_delay(8);
-
- query_delay(5);
- reset_delay(8);
-}
-
-void next_kbd_set_leds(bool left, bool right) {
- cli();
- out_lo_delay(9);
-
- out_hi_delay(3);
- out_lo_delay(1);
-
- if (left) {
- out_hi_delay(1);
- } else {
- out_lo_delay(1);
- }
-
- if (right) {
- out_hi_delay(1);
- } else {
- out_lo_delay(1);
- }
-
- out_lo_delay(7);
- out_hi();
- sei();
-}
-
-#define NEXT_KBD_READ (NEXT_KBD_IN_PIN & (1 << NEXT_KBD_IN_BIT))
-uint32_t next_kbd_recv(void) {
- // First check to make sure that the keyboard is actually connected;
- // if not, just return
- // TODO: reflect the status of the keyboard in a return code
- if (!NEXT_KBD_READ) {
- sei();
- return 0;
- }
-
- query();
- uint32_t resp = response();
-
- return resp;
-}
-
-static inline uint32_t response(void) {
- cli();
-
- // try a 5ms read; this should be called after the query method has
- // been run so if a key is pressed we should get a response within
- // 5ms; if not then send a reset and exit
- uint8_t i = 0;
- uint32_t data = 0;
- uint16_t reset_timeout = 50000;
- while (NEXT_KBD_READ && reset_timeout) {
- asm("");
- _delay_us(1);
- reset_timeout--;
- }
- if (!reset_timeout) {
- reset();
- sei();
- return 0;
- }
- _delay_us(NEXT_KBD_TIMING / 2);
- for (; i < 22; i++) {
- if (NEXT_KBD_READ) {
- data |= ((uint32_t)1 << i);
- /* Note:
- * My testing with the ATmega32u4 showed that there might
- * something wrong with the timing here; by the end of the
- * second data byte some of the modifiers can get bumped out
- * to the next bit over if we just cycle through the data
- * based on the expected interval. There is a bit (i = 10)
- * in the middle of the data that is always on followed by
- * one that is always off - so we'll use that to reset our
- * timing in case we've gotten ahead of the keyboard;
- */
- if (i == 10) {
- i++;
- while (NEXT_KBD_READ)
- ;
- _delay_us(NEXT_KBD_TIMING / 2);
- }
- } else {
- /* redundant - but I don't want to remove if it might screw
- * up the timing
- */
- data |= ((uint32_t)0 << i);
- }
- _delay_us(NEXT_KBD_TIMING);
- }
-
- sei();
-
- return data;
-}
-
-static inline void out_lo(void) {
- NEXT_KBD_OUT_PORT &= ~(1 << NEXT_KBD_OUT_BIT);
- NEXT_KBD_OUT_DDR |= (1 << NEXT_KBD_OUT_BIT);
-}
-
-static inline void out_hi(void) {
- /* input with pull up */
- NEXT_KBD_OUT_DDR &= ~(1 << NEXT_KBD_OUT_BIT);
- NEXT_KBD_OUT_PORT |= (1 << NEXT_KBD_OUT_BIT);
-}
-
-static inline void query(void) {
- out_lo_delay(5);
- out_hi_delay(1);
- out_lo_delay(3);
- out_hi();
-}
-
-static inline void reset(void) {
- out_lo_delay(1);
- out_hi_delay(4);
- out_lo_delay(1);
- out_hi_delay(6);
- out_lo_delay(10);
- out_hi();
-}
diff --git a/tmk_core/protocol/next_kbd.h b/tmk_core/protocol/next_kbd.h
deleted file mode 100644
index 1249ebf392..0000000000
--- a/tmk_core/protocol/next_kbd.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-NeXT non-ADB Keyboard Protocol
-
-Copyright 2013, Benjamin Gould (bgould@github.com)
-
-Based on:
-TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
-Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
-
-Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
-Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
-Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-*/
-
-#pragma once
-
-#include <stdbool.h>
-
-#define NEXT_KBD_KMBUS_IDLE 0x300600
-#define NEXT_KBD_TIMING 50
-
-extern uint8_t next_kbd_error;
-
-/* host role */
-void next_kbd_init(void);
-void next_kbd_set_leds(bool left, bool right);
-uint32_t next_kbd_recv(void);
diff --git a/tmk_core/protocol/ps2_io_avr.c b/tmk_core/protocol/ps2_io_avr.c
deleted file mode 100644
index a9ac5d338d..0000000000
--- a/tmk_core/protocol/ps2_io_avr.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <stdbool.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-/* Check port settings for clock and data line */
-#if !(defined(PS2_CLOCK_PORT) && defined(PS2_CLOCK_PIN) && defined(PS2_CLOCK_DDR) && defined(PS2_CLOCK_BIT))
-# error "PS/2 clock port setting is required in config.h"
-#endif
-
-#if !(defined(PS2_DATA_PORT) && defined(PS2_DATA_PIN) && defined(PS2_DATA_DDR) && defined(PS2_DATA_BIT))
-# error "PS/2 data port setting is required in config.h"
-#endif
-
-/*
- * Clock
- */
-void clock_init(void) {}
-
-void clock_lo(void) {
- PS2_CLOCK_PORT &= ~(1 << PS2_CLOCK_BIT);
- PS2_CLOCK_DDR |= (1 << PS2_CLOCK_BIT);
-}
-
-void clock_hi(void) {
- /* input with pull up */
- PS2_CLOCK_DDR &= ~(1 << PS2_CLOCK_BIT);
- PS2_CLOCK_PORT |= (1 << PS2_CLOCK_BIT);
-}
-
-bool clock_in(void) {
- PS2_CLOCK_DDR &= ~(1 << PS2_CLOCK_BIT);
- PS2_CLOCK_PORT |= (1 << PS2_CLOCK_BIT);
- _delay_us(1);
- return PS2_CLOCK_PIN & (1 << PS2_CLOCK_BIT);
-}
-
-/*
- * Data
- */
-void data_init(void) {}
-
-void data_lo(void) {
- PS2_DATA_PORT &= ~(1 << PS2_DATA_BIT);
- PS2_DATA_DDR |= (1 << PS2_DATA_BIT);
-}
-
-void data_hi(void) {
- /* input with pull up */
- PS2_DATA_DDR &= ~(1 << PS2_DATA_BIT);
- PS2_DATA_PORT |= (1 << PS2_DATA_BIT);
-}
-
-bool data_in(void) {
- PS2_DATA_DDR &= ~(1 << PS2_DATA_BIT);
- PS2_DATA_PORT |= (1 << PS2_DATA_BIT);
- _delay_us(1);
- return PS2_DATA_PIN & (1 << PS2_DATA_BIT);
-}
diff --git a/tmk_core/protocol/ps2_io_chibios.c b/tmk_core/protocol/ps2_io_chibios.c
deleted file mode 100644
index b672bd1f47..0000000000
--- a/tmk_core/protocol/ps2_io_chibios.c
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <stdbool.h>
-#include "ps2_io.h"
-
-// chibiOS headers
-#include "ch.h"
-#include "hal.h"
-
-/* Check port settings for clock and data line */
-#if !(defined(PS2_CLOCK))
-# error "PS/2 clock setting is required in config.h"
-#endif
-
-#if !(defined(PS2_DATA))
-# error "PS/2 data setting is required in config.h"
-#endif
-
-/*
- * Clock
- */
-void clock_init(void) {}
-
-void clock_lo(void) {
- palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN);
- palWriteLine(PS2_CLOCK, PAL_LOW);
-}
-
-void clock_hi(void) {
- palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN);
- palWriteLine(PS2_CLOCK, PAL_HIGH);
-}
-
-bool clock_in(void) {
- palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT);
- return palReadLine(PS2_CLOCK);
-}
-
-/*
- * Data
- */
-void data_init(void) {}
-
-void data_lo(void) {
- palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN);
- palWriteLine(PS2_DATA, PAL_LOW);
-}
-
-void data_hi(void) {
- palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN);
- palWriteLine(PS2_DATA, PAL_HIGH);
-}
-
-bool data_in(void) {
- palSetLineMode(PS2_DATA, PAL_MODE_INPUT);
- return palReadLine(PS2_DATA);
-}
diff --git a/tmk_core/common/report.c b/tmk_core/protocol/report.c
index 2a7fc006c4..854b59ae48 100644
--- a/tmk_core/common/report.c
+++ b/tmk_core/protocol/report.c
@@ -24,8 +24,8 @@
#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE
# define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
# define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
-# define RO_INC(a) RO_ADD(a, 1)
-# define RO_DEC(a) RO_SUB(a, 1)
+# define RO_INC(a) RO_ADD(a, 1)
+# define RO_DEC(a) RO_SUB(a, 1)
static int8_t cb_head = 0;
static int8_t cb_tail = 0;
static int8_t cb_count = 0;
diff --git a/tmk_core/common/report.h b/tmk_core/protocol/report.h
index f2223e8063..1adc892f3b 100644
--- a/tmk_core/common/report.h
+++ b/tmk_core/protocol/report.h
@@ -29,6 +29,7 @@ enum hid_report_ids {
REPORT_ID_MOUSE,
REPORT_ID_SYSTEM,
REPORT_ID_CONSUMER,
+ REPORT_ID_PROGRAMMABLE_BUTTON,
REPORT_ID_NKRO,
REPORT_ID_JOYSTICK,
REPORT_ID_DIGITIZER
@@ -196,6 +197,11 @@ typedef struct {
} __attribute__((packed)) report_extra_t;
typedef struct {
+ uint8_t report_id;
+ uint32_t usage;
+} __attribute__((packed)) report_programmable_button_t;
+
+typedef struct {
#ifdef MOUSE_SHARED_EP
uint8_t report_id;
#endif
diff --git a/tmk_core/protocol/serial_mouse_microsoft.c b/tmk_core/protocol/serial_mouse_microsoft.c
deleted file mode 100644
index eff0bf6e45..0000000000
--- a/tmk_core/protocol/serial_mouse_microsoft.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-Copyright 2014 Robin Haberkorn <robin.haberkorn@googlemail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdint.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "serial.h"
-#include "serial_mouse.h"
-#include "report.h"
-#include "host.h"
-#include "timer.h"
-#include "print.h"
-#include "debug.h"
-
-#ifdef MAX
-# undef MAX
-#endif
-#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
-
-static void print_usb_data(const report_mouse_t *report);
-
-void serial_mouse_task(void) {
- /* 3 byte ring buffer */
- static uint8_t buffer[3];
- static int buffer_cur = 0;
-
- static report_mouse_t report = {};
-
- int16_t rcv;
-
- rcv = serial_recv2();
- if (rcv < 0) /* no new data */
- return;
-
- if (debug_mouse) xprintf("serial_mouse: byte: %04X\n", rcv);
-
- /*
- * If bit 6 is one, this signals the beginning
- * of a 3 byte sequence/packet.
- */
- if (rcv & (1 << 6)) buffer_cur = 0;
-
- buffer[buffer_cur] = (uint8_t)rcv;
-
- if (buffer_cur == 0 && buffer[buffer_cur] == 0x20) {
- /*
- * Logitech extension: This must be a follow-up on
- * the last 3-byte packet signaling a middle button click
- */
- report.buttons |= MOUSE_BTN3;
- report.x = report.y = 0;
-
- print_usb_data(&report);
- host_mouse_send(&report);
- return;
- }
-
- buffer_cur++;
-
- if (buffer_cur < 3) return;
- buffer_cur = 0;
-
- /*
- * parse 3 byte packet.
- * NOTE: We only get a complete packet
- * if the mouse moved or the button states
- * change.
- */
- report.buttons = 0;
- if (buffer[0] & (1 << 5)) report.buttons |= MOUSE_BTN1;
- if (buffer[0] & (1 << 4)) report.buttons |= MOUSE_BTN2;
-
- report.x = (buffer[0] << 6) | buffer[1];
- report.y = ((buffer[0] << 4) & 0xC0) | buffer[2];
-
- /* USB HID uses values from -127 to 127 only */
- report.x = MAX(report.x, -127);
- report.y = MAX(report.y, -127);
-
-#if 0
- if (!report.buttons && !report.x && !report.y) {
- /*
- * Microsoft extension: Middle mouse button pressed
- * FIXME: I don't know how exactly this extension works.
- */
- report.buttons |= MOUSE_BTN3;
- }
-#endif
-
- print_usb_data(&report);
- host_mouse_send(&report);
-}
-
-static void print_usb_data(const report_mouse_t *report) {
- if (!debug_mouse) return;
-
- xprintf("serial_mouse usb: [%02X|%d %d %d %d]\n", report->buttons, report->x, report->y, report->v, report->h);
-}
diff --git a/tmk_core/protocol/serial_mouse_mousesystems.c b/tmk_core/protocol/serial_mouse_mousesystems.c
deleted file mode 100644
index 0ec2b0399a..0000000000
--- a/tmk_core/protocol/serial_mouse_mousesystems.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
-Copyright 2014 Robin Haberkorn <robin.haberkorn@googlemail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdint.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "serial.h"
-#include "serial_mouse.h"
-#include "report.h"
-#include "host.h"
-#include "timer.h"
-#include "print.h"
-#include "debug.h"
-
-#ifdef MAX
-# undef MAX
-#endif
-#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
-
-//#define SERIAL_MOUSE_CENTER_SCROLL
-
-static void print_usb_data(const report_mouse_t *report);
-
-void serial_mouse_task(void) {
- /* 5 byte ring buffer */
- static uint8_t buffer[5];
- static int buffer_cur = 0;
-
- int16_t rcv;
-
- report_mouse_t report = {0, 0, 0, 0, 0};
-
- rcv = serial_recv2();
- if (rcv < 0) /* no new data */
- return;
-
- if (debug_mouse) xprintf("serial_mouse: byte: %04X\n", rcv);
-
- /*
- * Synchronization: mouse(4) says that all
- * bytes but the first one in the packet have
- * bit 7 == 0, but this is untrue.
- * Therefore we discard all bytes up to the
- * first one with the characteristic bit pattern.
- */
- if (buffer_cur == 0 && (rcv >> 3) != 0x10) return;
-
- buffer[buffer_cur++] = (uint8_t)rcv;
-
- if (buffer_cur < 5) return;
- buffer_cur = 0;
-
-#ifdef SERIAL_MOUSE_CENTER_SCROLL
- if ((buffer[0] & 0x7) == 0x5 && (buffer[1] || buffer[2])) {
- /* USB HID uses only values from -127 to 127 */
- report.h = MAX((int8_t)buffer[1], -127);
- report.v = MAX((int8_t)buffer[2], -127);
-
- print_usb_data(&report);
- host_mouse_send(&report);
-
- if (buffer[3] || buffer[4]) {
- report.h = MAX((int8_t)buffer[3], -127);
- report.v = MAX((int8_t)buffer[4], -127);
-
- print_usb_data(&report);
- host_mouse_send(&report);
- }
-
- return;
- }
-#endif
-
- /*
- * parse 5 byte packet.
- * NOTE: We only get a complete packet
- * if the mouse moved or the button states
- * change.
- */
- if (!(buffer[0] & (1 << 2))) report.buttons |= MOUSE_BTN1;
- if (!(buffer[0] & (1 << 1))) report.buttons |= MOUSE_BTN3;
- if (!(buffer[0] & (1 << 0))) report.buttons |= MOUSE_BTN2;
-
- /* USB HID uses only values from -127 to 127 */
- report.x = MAX((int8_t)buffer[1], -127);
- report.y = MAX(-(int8_t)buffer[2], -127);
-
- print_usb_data(&report);
- host_mouse_send(&report);
-
- if (buffer[3] || buffer[4]) {
- report.x = MAX((int8_t)buffer[3], -127);
- report.y = MAX(-(int8_t)buffer[4], -127);
-
- print_usb_data(&report);
- host_mouse_send(&report);
- }
-}
-
-static void print_usb_data(const report_mouse_t *report) {
- if (!debug_mouse) return;
-
- xprintf("serial_mouse usb: [%02X|%d %d %d %d]\n", report->buttons, report->x, report->y, report->v, report->h);
-}
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index 9688d6d656..f047b4719a 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -240,6 +240,25 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
HID_RI_END_COLLECTION(0),
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ HID_RI_USAGE_PAGE(8, 0x0C), // Consumer
+ HID_RI_USAGE(8, 0x01), // Consumer Control
+ HID_RI_COLLECTION(8, 0x01), // Application
+ HID_RI_REPORT_ID(8, REPORT_ID_PROGRAMMABLE_BUTTON),
+ HID_RI_USAGE(8, 0x03), // Programmable Buttons
+ HID_RI_COLLECTION(8, 0x04), // Named Array
+ HID_RI_USAGE_PAGE(8, 0x09), // Button
+ HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1
+ HID_RI_USAGE_MAXIMUM(8, 0x20), // Button 32
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+ HID_RI_REPORT_COUNT(8, 32),
+ HID_RI_REPORT_SIZE(8, 1),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+ HID_RI_END_COLLECTION(0),
+ HID_RI_END_COLLECTION(0),
+#endif
+
#ifdef NKRO_ENABLE
HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
HID_RI_USAGE(8, 0x06), // Keyboard
diff --git a/tmk_core/protocol/usb_device_state.c b/tmk_core/protocol/usb_device_state.c
new file mode 100644
index 0000000000..84f01943be
--- /dev/null
+++ b/tmk_core/protocol/usb_device_state.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2021 Andrei Purdea <andrei@purdea.ro>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "usb_device_state.h"
+#if defined(HAPTIC_ENABLE)
+# include "haptic.h"
+#endif
+
+enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT;
+
+__attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state) { notify_usb_device_state_change_user(usb_device_state); }
+
+__attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {}
+
+static void notify_usb_device_state_change(enum usb_device_state usb_device_state) {
+#if defined(HAPTIC_ENABLE) && HAPTIC_OFF_IN_LOW_POWER
+ haptic_notify_usb_device_state_change();
+#endif
+ notify_usb_device_state_change_kb(usb_device_state);
+}
+
+void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) {
+ usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT;
+ notify_usb_device_state_change(usb_device_state);
+}
+
+void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber) {
+ usb_device_state = USB_DEVICE_STATE_SUSPEND;
+ notify_usb_device_state_change(usb_device_state);
+}
+
+void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber) {
+ usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT;
+ notify_usb_device_state_change(usb_device_state);
+}
+
+void usb_device_state_set_reset(void) {
+ usb_device_state = USB_DEVICE_STATE_INIT;
+ notify_usb_device_state_change(usb_device_state);
+}
+
+void usb_device_state_init(void) {
+ usb_device_state = USB_DEVICE_STATE_INIT;
+ notify_usb_device_state_change(usb_device_state);
+}
diff --git a/tmk_core/protocol/usb_device_state.h b/tmk_core/protocol/usb_device_state.h
new file mode 100644
index 0000000000..c229311d46
--- /dev/null
+++ b/tmk_core/protocol/usb_device_state.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 Andrei Purdea <andrei@purdea.ro>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber);
+void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber);
+void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber);
+void usb_device_state_set_reset(void);
+void usb_device_state_init(void);
+
+enum usb_device_state {
+ USB_DEVICE_STATE_NO_INIT = 0, // We're in this state before calling usb_device_state_init()
+ USB_DEVICE_STATE_INIT = 1, // Can consume up to 100mA
+ USB_DEVICE_STATE_CONFIGURED = 2, // Can consume up to what is specified in configuration descriptor, typically 500mA
+ USB_DEVICE_STATE_SUSPEND = 3 // Can consume only suspend current
+};
+
+extern enum usb_device_state usb_device_state;
+
+void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state);
+void notify_usb_device_state_change_user(enum usb_device_state usb_device_state);
diff --git a/tmk_core/protocol/usb_hid/override_wiring.c b/tmk_core/protocol/usb_hid/override_wiring.c
index 52f03c300f..adc6645f8e 100644
--- a/tmk_core/protocol/usb_hid/override_wiring.c
+++ b/tmk_core/protocol/usb_hid/override_wiring.c
@@ -3,7 +3,7 @@
*/
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
-#include "common/timer.h"
+#include "platforms/timer.h"
unsigned long millis(void)
diff --git a/tmk_core/protocol/usb_hid/parser.h b/tmk_core/protocol/usb_hid/parser.h
index 036281fa66..ba35b7af5a 100644
--- a/tmk_core/protocol/usb_hid/parser.h
+++ b/tmk_core/protocol/usb_hid/parser.h
@@ -1,5 +1,4 @@
-#ifndef PARSER_H
-#define PARSER_H
+#pragma once
#include "hid.h"
#include "report.h"
@@ -11,5 +10,3 @@ public:
uint16_t time_stamp;
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};
-
-#endif
diff --git a/tmk_core/protocol/usb_hid/usb_hid.h b/tmk_core/protocol/usb_hid/usb_hid.h
index 083b68d1f5..5cb5f5d035 100644
--- a/tmk_core/protocol/usb_hid/usb_hid.h
+++ b/tmk_core/protocol/usb_hid/usb_hid.h
@@ -1,10 +1,6 @@
-#ifndef USB_HID_H
-#define USB_HID_H
+#pragma once
#include "report.h"
-
extern report_keyboard_t usb_hid_keyboard_report;
extern uint16_t usb_hid_time_stamp;
-
-#endif
diff --git a/tmk_core/common/usb_util.c b/tmk_core/protocol/usb_util.c
index dd1deeaa11..dd1deeaa11 100644
--- a/tmk_core/common/usb_util.c
+++ b/tmk_core/protocol/usb_util.c
diff --git a/tmk_core/common/usb_util.h b/tmk_core/protocol/usb_util.h
index 13db9fbfbd..13db9fbfbd 100644
--- a/tmk_core/common/usb_util.h
+++ b/tmk_core/protocol/usb_util.h
diff --git a/tmk_core/protocol/vusb/protocol.c b/tmk_core/protocol/vusb/protocol.c
index 89dc795b21..644e77e021 100644
--- a/tmk_core/protocol/vusb/protocol.c
+++ b/tmk_core/protocol/vusb/protocol.c
@@ -111,22 +111,16 @@ void protocol_setup(void) {
// clock prescaler
clock_prescale_set(clock_div_1);
#endif
- keyboard_setup();
}
-void protocol_init(void) {
+void protocol_pre_init(void) {
setup_usb();
sei();
+}
- keyboard_init();
-
+void protocol_post_init(void) {
host_set_driver(vusb_driver());
-
wait_ms(50);
-
-#ifdef SLEEP_LED_ENABLE
- sleep_led_init();
-#endif
}
void protocol_task(void) {
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index 485b20c900..bd0f1c21aa 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -226,8 +226,9 @@ static void send_keyboard(report_keyboard_t *report);
static void send_mouse(report_mouse_t *report);
static void send_system(uint16_t data);
static void send_consumer(uint16_t data);
+static void send_programmable_button(uint32_t data);
-static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
+static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};
host_driver_t *vusb_driver(void) { return &driver; }
@@ -300,6 +301,20 @@ void send_digitizer(report_digitizer_t *report) {
#endif
}
+static void send_programmable_button(uint32_t data) {
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ static report_programmable_button_t report = {
+ .report_id = REPORT_ID_PROGRAMMABLE_BUTTON,
+ };
+
+ report.usage = data;
+
+ if (usbInterruptIsReadyShared()) {
+ usbSetInterruptShared((void *)&report, sizeof(report));
+ }
+#endif
+}
+
/*------------------------------------------------------------------*
* Request from host *
*------------------------------------------------------------------*/
@@ -555,7 +570,27 @@ const PROGMEM uchar shared_hid_report[] = {
0x09, 0x31, // Usage (Y)
0x81, 0x02, // Input (Data, Variable, Absolute)
0xC0, // End Collection
- 0xC0 // End Collection
+ 0xC0, // End Collection
+#endif
+
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ // Programmable buttons report descriptor
+ 0x05, 0x0C, // Usage Page (Consumer)
+ 0x09, 0x01, // Usage (Consumer Control)
+ 0xA1, 0x01, // Collection (Application)
+ 0x85, REPORT_ID_PROGRAMMABLE_BUTTON, // Report ID
+ 0x09, 0x03, // Usage (Programmable Buttons)
+ 0xA1, 0x04, // Collection (Named Array)
+ 0x05, 0x09, // Usage Page (Button)
+ 0x19, 0x01, // Usage Minimum (Button 1)
+ 0x29, 0x20, // Usage Maximum (Button 32)
+ 0x15, 0x00, // Logical Minimum (0)
+ 0x25, 0x01, // Logical Maximum (1)
+ 0x95, 0x20, // Report Count (32)
+ 0x75, 0x01, // Report Size (1)
+ 0x81, 0x02, // Input (Data, Variable, Absolute)
+ 0xC0, // End Collection
+ 0xC0, // End Collection
#endif
#ifdef SHARED_EP_ENABLE
diff --git a/tmk_core/protocol/xt.h b/tmk_core/protocol/xt.h
deleted file mode 100644
index 538ff0e459..0000000000
--- a/tmk_core/protocol/xt.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Copyright 2018 Jun WAKO <wakojun@gmail.com>
-Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#pragma once
-
-#include "quantum.h"
-
-#define XT_DATA_IN() \
- do { \
- setPinInput(XT_DATA_PIN); \
- writePinHigh(XT_DATA_PIN); \
- } while (0)
-
-#define XT_DATA_READ() readPin(XT_DATA_PIN)
-
-#define XT_DATA_LO() \
- do { \
- writePinLow(XT_DATA_PIN); \
- setPinOutput(XT_DATA_PIN); \
- } while (0)
-
-#define XT_CLOCK_IN() \
- do { \
- setPinInput(XT_CLOCK_PIN); \
- writePinHigh(XT_CLOCK_PIN); \
- } while (0)
-
-#define XT_CLOCK_READ() readPin(XT_CLOCK_PIN)
-
-#define XT_CLOCK_LO() \
- do { \
- writePinLow(XT_CLOCK_PIN); \
- setPinOutput(XT_CLOCK_PIN); \
- } while (0)
-
-void xt_host_init(void);
-
-uint8_t xt_host_recv(void);
diff --git a/tmk_core/protocol/xt_interrupt.c b/tmk_core/protocol/xt_interrupt.c
deleted file mode 100644
index ba9d71848f..0000000000
--- a/tmk_core/protocol/xt_interrupt.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
-Copyright 2018 Jun WAKO <wakojun@gmail.com>
-Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-* Neither the name of the copyright holders nor the names of
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdbool.h>
-#include <avr/interrupt.h>
-#include "xt.h"
-#include "wait.h"
-#include "debug.h"
-
-static inline uint8_t pbuf_dequeue(void);
-static inline void pbuf_enqueue(uint8_t data);
-static inline bool pbuf_has_data(void);
-static inline void pbuf_clear(void);
-
-void xt_host_init(void) {
- XT_INT_INIT();
- XT_INT_OFF();
-
- /* hard reset */
-#ifdef XT_RESET
- XT_RESET();
-#endif
-
- /* soft reset: pull clock line down for 20ms */
- XT_DATA_LO();
- XT_CLOCK_LO();
- wait_ms(20);
-
- /* input mode with pullup */
- XT_CLOCK_IN();
- XT_DATA_IN();
-
- XT_INT_ON();
-}
-
-/* get data received by interrupt */
-uint8_t xt_host_recv(void) {
- if (pbuf_has_data()) {
- return pbuf_dequeue();
- } else {
- return 0;
- }
-}
-
-ISR(XT_INT_VECT) {
- /*
- * XT signal format consits of 10 or 9 clocks and sends start bits and 8-bit data,
- * which should be read on falling edge of clock.
- *
- * start(0), start(1), bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7
- *
- * Original IBM XT keyboard sends start(0) bit while some of clones don't.
- * Start(0) bit is read as low on data line while start(1) as high.
- *
- * https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol
- */
- static enum { START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7 } state = START;
- static uint8_t data = 0;
-
- uint8_t dbit = XT_DATA_READ();
-
- // This is needed if using PCINT which can be called on both falling and rising edge
- // if (XT_CLOCK_READ()) return;
-
- switch (state) {
- case START:
- // ignore start(0) bit
- if (!dbit) return;
- break;
- case BIT0 ... BIT7:
- data >>= 1;
- if (dbit) data |= 0x80;
- break;
- }
- if (state++ == BIT7) {
- pbuf_enqueue(data);
- state = START;
- data = 0;
- }
- return;
-}
-
-/*--------------------------------------------------------------------
- * Ring buffer to store scan codes from keyboard
- *------------------------------------------------------------------*/
-#define PBUF_SIZE 32
-static uint8_t pbuf[PBUF_SIZE];
-static uint8_t pbuf_head = 0;
-static uint8_t pbuf_tail = 0;
-
-static inline void pbuf_enqueue(uint8_t data) {
- uint8_t sreg = SREG;
- cli();
- uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
- if (next != pbuf_tail) {
- pbuf[pbuf_head] = data;
- pbuf_head = next;
- } else {
- dprintf("pbuf: full\n");
- }
- SREG = sreg;
-}
-
-static inline uint8_t pbuf_dequeue(void) {
- uint8_t val = 0;
-
- uint8_t sreg = SREG;
- cli();
- if (pbuf_head != pbuf_tail) {
- val = pbuf[pbuf_tail];
- pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
- }
- SREG = sreg;
-
- return val;
-}
-
-static inline bool pbuf_has_data(void) {
- uint8_t sreg = SREG;
- cli();
- bool has_data = (pbuf_head != pbuf_tail);
- SREG = sreg;
- return has_data;
-}
-
-static inline void pbuf_clear(void) {
- uint8_t sreg = SREG;
- cli();
- pbuf_head = pbuf_tail = 0;
- SREG = sreg;
-}
diff --git a/tmk_core/readme.md b/tmk_core/readme.md
index a754cfee42..a47dc88185 100644
--- a/tmk_core/readme.md
+++ b/tmk_core/readme.md
@@ -25,7 +25,6 @@ These features can be used in your keyboard.
* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc
* USB NKRO - 248 keys(+ 8 modifiers) simultaneously
* PS/2 mouse support - PS/2 mouse(TrackPoint) as composite device
-* Keyboard protocols - PS/2, ADB, M0110, Sun and other old keyboard protocols
* User Function - Customizable function of key with writing code
* Macro - Very primitive at this time
* Keyboard Tricks - Oneshot modifier and modifier with tapping feature
@@ -84,9 +83,9 @@ Architecture
/ /| Keys/Mouse | Protocol |d| | Action | | | Protocol |
/__________/ |<-----------| LUFA |r| | Layer, Tap | | | Matrix |
|.--------.| | LED | V-USB |i| |-------------| | | PS/2,IBM | __________________
- || || |----------->| UART |v| | Keymap | | | ADB,M0110| Keys / /_/_/_/_/_/_/_/ /|
- || Host || | Console | |e| | Mousekey | | | SUN/NEWS |<----------/ /_/_/_/_/_/_/_/ / /
- ||________||/.<-----------| |r| | Report | | | X68K/PC98| Control / /_/_/_/_/_/_/_/ / /
+ || || |----------->| UART |v| | Keymap | | | | Keys / /_/_/_/_/_/_/_/ /|
+ || Host || | Console | |e| | Mousekey | | | |<----------/ /_/_/_/_/_/_/_/ / /
+ ||________||/.<-----------| |r| | Report | | | | Control / /_/_/_/_/_/_/_/ / /
`_========_'/| |---------------------------------------------|-------->/___ /_______/ ___/ /
|_o______o_|/ | Sendchar, Print, Debug, Command, ... | |_________________|/
+---------------------------------------------+ Keyboard
@@ -134,10 +133,6 @@ Files and Directories
* lufa/ - LUFA USB stack
* vusb/ - Objective Development V-USB
* ps2.c - PS/2 protocol
-* adb.c - Apple Desktop Bus protocol
-* m0110.c - Macintosh 128K/512K/Plus keyboard protocol
-* news.c - Sony NEWS keyboard protocol
-* x68k.c - Sharp X68000 keyboard protocol
* serial_soft.c - Asynchronous Serial protocol implemented by software
diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk
index 5a629d1eb0..6767a8e4af 100644
--- a/tmk_core/rules.mk
+++ b/tmk_core/rules.mk
@@ -69,8 +69,11 @@ CSTANDARD = -std=gnu99
#CXXDEFS += -D__STDC_CONSTANT_MACROS
#CXXDEFS +=
-
-
+# Speed up recompilations by opt-in usage of ccache
+USE_CCACHE ?= no
+ifneq ($(USE_CCACHE),no)
+ CC_PREFIX ?= ccache
+endif
#---------------- Compiler Options C ----------------
# -g*: generate debugging information
@@ -78,7 +81,15 @@ CSTANDARD = -std=gnu99
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
-# -adhlns...: create assembler listing
+ifeq ($(strip $(LTO_ENABLE)), yes)
+ ifeq ($(PLATFORM),CHIBIOS)
+ $(info Enabling LTO on ChibiOS-targeting boards is known to have a high likelihood of failure.)
+ $(info If unsure, set LTO_ENABLE = no.)
+ endif
+ CDEFS += -flto
+ CDEFS += -DLTO_ENABLE
+endif
+
DEBUG_ENABLE ?= yes
ifeq ($(strip $(SKIP_DEBUG_INFO)),yes)
DEBUG_ENABLE=no
@@ -105,10 +116,6 @@ endif
#CFLAGS += -Wundef
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
-GCC_VERSION := $(shell gcc --version 2>/dev/null)
-ifeq ($(findstring clang, ${GCC_VERSION}),)
-CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
-endif
CFLAGS += $(CSTANDARD)
# This fixes lots of keyboards linking errors but SHOULDN'T BE A FINAL SOLUTION
@@ -121,7 +128,6 @@ CFLAGS += -fcommon
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
-# -adhlns...: create assembler listing
ifeq ($(strip $(DEBUG_ENABLE)),yes)
CXXFLAGS += -g$(DEBUG)
endif
@@ -140,28 +146,10 @@ endif
#CXXFLAGS += -Wstrict-prototypes
#CXXFLAGS += -Wunreachable-code
#CXXFLAGS += -Wsign-compare
-ifeq ($(findstring clang, ${GCC_VERSION}),)
-CXXFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
-endif
#CXXFLAGS += $(CSTANDARD)
#---------------- Assembler Options ----------------
-# -Wa,...: tell GCC to pass this to the assembler.
-# -adhlns: create listing
-# -gstabs: have the assembler create line number information; note that
-# for use in COFF files, additional information about filenames
-# and function names needs to be present in the assembler source
-# files -- see avr-libc docs [FIXME: not yet described there]
-# -listing-cont-lines: Sets the maximum number of continuation lines of hex
-# dump that will be displayed for a given single line of source input.
ASFLAGS += $(ADEFS)
-ifeq ($(findstring clang, ${GCC_VERSION}),)
-ifeq ($(strip $(DEBUG_ENABLE)),yes)
- ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
-else
- ASFLAGS += -Wa,-adhlns=$(@:%.o=%.lst),--listing-cont-lines=100
-endif
-endif
ifeq ($(VERBOSE_AS_CMD),yes)
ASFLAGS += -v
endif
@@ -218,6 +206,32 @@ LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
# You can give EXTRALDFLAGS at 'make' command line.
LDFLAGS += $(EXTRALDFLAGS)
+#---------------- Assembler Listings ----------------
+# -Wa,...: tell GCC to pass this to the assembler.
+# -adhlns: create listing
+# -gstabs: have the assembler create line number information; note that
+# for use in COFF files, additional information about filenames
+# and function names needs to be present in the assembler source
+# files -- see avr-libc docs [FIXME: not yet described there]
+# -listing-cont-lines: Sets the maximum number of continuation lines of hex
+# dump that will be displayed for a given single line of source input.
+
+ADHLNS_ENABLE ?= no
+ifeq ($(ADHLNS_ENABLE),yes)
+ # Avoid "Options to '-Xassembler' do not match" - only specify assembler options at LTO link time
+ ifeq ($(strip $(LTO_ENABLE)), yes)
+ LDFLAGS += -Wa,-adhlns=$(BUILD_DIR)/$(TARGET).lst
+ else
+ CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
+ CXXFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
+ ifeq ($(strip $(DEBUG_ENABLE)),yes)
+ ASFLAGS = -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
+ else
+ ASFLAGS = -Wa,-adhlns=$(@:%.o=%.lst),--listing-cont-lines=100
+ endif
+ endif
+endif
+
# Define programs and commands.
SHELL = sh
REMOVE = rm -f
@@ -347,7 +361,7 @@ BEGIN = gccversion sizebefore
# Note the obj.txt depeendency is there to force linking if a source file is deleted
%.elf: $(OBJ) $(MASTER_OUTPUT)/cflags.txt $(MASTER_OUTPUT)/ldflags.txt $(MASTER_OUTPUT)/obj.txt | $(BEGIN)
@$(SILENT) || printf "$(MSG_LINKING) $@" | $(AWK_CMD)
- $(eval CMD=$(CC) $(ALL_CFLAGS) $(filter-out %.txt,$^) --output $@ $(LDFLAGS))
+ $(eval CMD=MAKE=$(MAKE) $(CC) $(ALL_CFLAGS) $(filter-out %.txt,$^) --output $@ $(LDFLAGS))
@$(BUILD_CMD)
@@ -465,7 +479,7 @@ ifeq ($(findstring avr-gcc,$(CC)),avr-gcc)
SIZE_MARGIN = 1024
check-size:
- $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0))
+ $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) -D__ASSEMBLER__ $(CFLAGS) $(OPT_DEFS) platforms/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0))
$(eval CURRENT_SIZE=$(shell if [ -f $(BUILD_DIR)/$(TARGET).hex ]; then $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex | $(AWK) 'NR==2 {print $$4}'; else printf 0; fi))
$(eval FREE_SIZE=$(shell expr $(MAX_SIZE) - $(CURRENT_SIZE)))
$(eval OVER_SIZE=$(shell expr $(CURRENT_SIZE) - $(MAX_SIZE)))
diff --git a/util/chibios_conf_updater.sh b/util/chibios_conf_updater.sh
index 5ba8aa677b..a5699ca3cb 100755
--- a/util/chibios_conf_updater.sh
+++ b/util/chibios_conf_updater.sh
@@ -3,6 +3,17 @@
set -eEuo pipefail
umask 022
+#####################
+# You will need to get an older JDK -- JDK 8
+#
+# !!!!!!!! DO NOT INSTALL THIS IF YOU HAVE AN EXISTING JDK OR JRE INSTALLED !!!!!!!!
+#
+# For Debian 10-ish distro's:
+# wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add -
+# sudo add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/
+# sudo apt-get update && sudo apt-get install adoptopenjdk-8-hotspot
+
+
sinfo() { echo "$@" >&2 ; }
shead() { sinfo "" ; sinfo "---------------------------------" ; sinfo "-- $@" ; sinfo "---------------------------------" ; }
havecmd() { command command type "${1}" >/dev/null 2>&1 || return 1 ; }
@@ -11,8 +22,6 @@ this_script="$(realpath "${BASH_SOURCE[0]}")"
script_dir="$(realpath "$(dirname "$this_script")")"
qmk_firmware_dir="$(realpath "$script_dir/../")"
-declare -A file_hashes
-
export PATH="$PATH:$script_dir/fmpp/bin"
build_fmpp() {
@@ -38,74 +47,13 @@ find_chibi_files() {
local search_path="$1"
shift
local conditions=( "$@" )
- for file in $(find -L "$search_path" -not -path '*/lib/chibios*' -and -not -path '*/lib/ugfx*' -and -not -path '*/util/*' -and \( "${conditions[@]}" \) | sort) ; do
+ for file in $(find -L "$search_path" -not -path '*/lib/chibios*' -and -not -path '*/util/*' -and \( "${conditions[@]}" \) | sort) ; do
if [ -z "$(grep 'include_next' "$file")" ] ; then
echo $file
fi
done
}
-revert_chibi_files() {
- local search_path="$1"
- shead "Reverting ChibiOS config/board files..."
- for file in $(find_chibi_files "$search_path" -name chconf.h -or -name halconf.h -or -name mcuconf.h -or -name board.c -or -name board.h -or -name board.mk -or -name board.chcfg) ; do
- pushd "$search_path" >/dev/null 2>&1
- local relpath=$(realpath --relative-to="$search_path" "$file")
- git checkout upstream/develop -- "$relpath" || git checkout origin/develop -- "$relpath" || true
- popd >/dev/null 2>&1
- done
-}
-
-populate_file_hashes() {
- local search_path="$1"
- shead "Determining duplicate config/board files..."
- for file in $(find_chibi_files "$search_path" -name chconf.h -or -name halconf.h -or -name mcuconf.h -or -name board.c -or -name board.h) ; do
- local key="file_$(clang-format "$file" | sha1sum | cut -d' ' -f1)"
- local relpath=$(realpath --relative-to="$search_path" "$file")
- file_hashes[$key]="${file_hashes[$key]:-} $relpath"
- done
- for file in $(find_chibi_files "$search_path" -name board.mk -or -name board.chcfg) ; do
- local key="file_$(cat "$file" | sha1sum | cut -d' ' -f1)"
- local relpath=$(realpath --relative-to="$search_path" "$file")
- file_hashes[$key]="${file_hashes[$key]:-} $relpath"
- done
-}
-
-determine_equivalent_files() {
- local search_file="$1"
- for K in "${!file_hashes[@]}"; do
- for V in ${file_hashes[$K]}; do
- if [[ "$V" == "$search_file" ]] ; then
- for V in ${file_hashes[$K]}; do
- echo "$V"
- done
- return 0
- fi
- done
- done
- return 1
-}
-
-deploy_staged_files() {
- shead "Deploying staged files..."
- for file in $(find "$qmk_firmware_dir/util/chibios-upgrade-staging" -type f) ; do
- local relpath=$(realpath --relative-to="$qmk_firmware_dir/util/chibios-upgrade-staging" "$file")
- sinfo "Deploying staged file: $relpath"
- for other in $(determine_equivalent_files "$relpath") ; do
- sinfo " => $other"
- cp "$qmk_firmware_dir/util/chibios-upgrade-staging/$relpath" "$qmk_firmware_dir/$other"
- done
- done
-}
-
-swap_mcuconf_f3xx_f303() {
- shead "Swapping STM32F3xx_MCUCONF -> STM32F303_MCUCONF..."
- for file in $(find_chibi_files "$qmk_firmware_dir" -name mcuconf.h) ; do
- sed -i 's#STM32F3xx_MCUCONF#STM32F303_MCUCONF#g' "$file"
- dos2unix "$file" >/dev/null 2>&1
- done
-}
-
upgrade_conf_files_generic() {
local search_filename="$1"
local update_script="$2"
@@ -150,35 +98,8 @@ upgrade_mcuconf_files() {
popd >/dev/null 2>&1
}
-update_staged_files() {
- shead "Updating staged files with ChibiOS upgraded versions..."
- for file in $(find "$qmk_firmware_dir/util/chibios-upgrade-staging" -type f) ; do
- local relpath=$(realpath --relative-to="$qmk_firmware_dir/util/chibios-upgrade-staging" "$file")
- sinfo "Updating staged file: $relpath"
- cp "$qmk_firmware_dir/$relpath" "$qmk_firmware_dir/util/chibios-upgrade-staging/$relpath"
- done
-}
-
havecmd fmpp || build_fmpp
-revert_chibi_files "$qmk_firmware_dir"
-populate_file_hashes "$qmk_firmware_dir"
-
-shead "Showing duplicate ChibiOS files..."
-for K in "${!file_hashes[@]}"; do
- sinfo ${K#file_}:
- for V in ${file_hashes[$K]}; do
- sinfo " $V"
- done
-done
-
-if [ "${1:-}" == "-r" ] ; then
- exit 0
-fi
-
-swap_mcuconf_f3xx_f303
-deploy_staged_files
upgrade_mcuconf_files
upgrade_chconf_files
upgrade_halconf_files
-update_staged_files
diff --git a/util/install/arch.sh b/util/install/arch.sh
index bef98ac37f..33c39212d3 100755
--- a/util/install/arch.sh
+++ b/util/install/arch.sh
@@ -6,7 +6,8 @@ _qmk_install() {
sudo pacman --needed --noconfirm -S \
base-devel clang diffutils gcc git unzip wget zip python-pip \
avr-binutils arm-none-eabi-binutils arm-none-eabi-gcc \
- arm-none-eabi-newlib avrdude dfu-programmer dfu-util
+ arm-none-eabi-newlib avrdude dfu-programmer dfu-util \
+ riscv64-elf-binutils riscv64-elf-gcc riscv64-elf-newlib
sudo pacman --needed --noconfirm -U https://archive.archlinux.org/packages/a/avr-gcc/avr-gcc-8.3.0-1-x86_64.pkg.tar.xz
sudo pacman --needed --noconfirm -S avr-libc # Must be installed after the above, or it will bring in the latest avr-gcc instead
diff --git a/util/install/debian.sh b/util/install/debian.sh
index 57588e371a..3e02919bdd 100755
--- a/util/install/debian.sh
+++ b/util/install/debian.sh
@@ -11,11 +11,18 @@ _qmk_install_prepare() {
_qmk_install() {
echo "Installing dependencies"
- sudo apt-get -yq install \
+ sudo apt-get --quiet --yes install \
build-essential clang-format diffutils gcc git unzip wget zip \
python3-pip binutils-avr gcc-avr avr-libc binutils-arm-none-eabi \
gcc-arm-none-eabi libnewlib-arm-none-eabi avrdude dfu-programmer \
dfu-util teensy-loader-cli libhidapi-hidraw0 libusb-dev
- python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt
+ # RISC-V toolchains with picolibc support are only available for distributions based on Debian 11+.
+ if sudo apt-get install --simulate --quiet --yes picolibc-riscv64-unknown-elf gcc-riscv64-unknown-elf binutils-riscv64-unknown-elf > /dev/null 2>&1; then
+ sudo apt-get --quiet --yes install picolibc-riscv64-unknown-elf \
+ gcc-riscv64-unknown-elf \
+ binutils-riscv64-unknown-elf
+ fi
+
+ python3 -m pip install --user -r "$QMK_FIRMWARE_DIR"/requirements.txt
}
diff --git a/util/size_regression.sh b/util/size_regression.sh
new file mode 100755
index 0000000000..988d1d9b5b
--- /dev/null
+++ b/util/size_regression.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+
+# Copyright 2021 Nick Brassel (@tzarc)
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+set -eEuo pipefail
+
+job_count=$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)
+source_ref="0.11.0"
+dest_ref="develop"
+ignore_ref="master"
+unset skip_zero
+
+function usage() {
+ echo "Usage: $(basename "$0") [-h] [-j <jobs>] [-s <source>] [-d <dest>] [-n] planck/rev6:default"
+ echo " -h : Shows this usage page."
+ echo " -j <threads> : Change the number of threads to execute with. Defaults to \`$job_count\`."
+ echo " -s <source> : Use source commit, branch, tag, or sha1 to start the search. Defaults to \`$source_ref\`."
+ echo " -d <dest> : Use destination commit, branch, tag, or sha1 to end the search. Defaults to \`$dest_ref\`."
+ echo " -i <ignore> : The branch to ignore refs from. Defaults to \`$ignore_ref\`."
+ echo " -n : Skips printing changes if the delta is zero."
+ exit 1
+}
+
+if [[ ${#} -eq 0 ]]; then
+ usage
+fi
+
+while getopts "hj:s:d:i:n" opt "$@" ; do
+ case "$opt" in
+ h) usage; exit 0;;
+ j) job_count="${OPTARG:-}";;
+ s) source_ref="${OPTARG:-}";;
+ d) dest_ref="${OPTARG:-}";;
+ i) ignore_ref="${OPTARG:-}";;
+ n) skip_zero=1;;
+ \?) usage >&2; exit 1;;
+ esac
+done
+
+# Work out the target board
+shift $((OPTIND-1))
+keyboard_target=$1
+
+last_size=0
+last_line=""
+function build_executor() {
+ git rev-list --oneline --no-merges ${source_ref}...${dest_ref} ^${ignore_ref} | while IFS= read -r line ; do
+ revision=$(echo $line | cut -d' ' -f1)
+
+ make distclean >/dev/null 2>&1
+ git checkout $revision >/dev/null 2>&1 || { echo "Failed to check out revision ${revision}" >&2 ; exit 1 ; }
+ make -j${job_count} $keyboard_target >/dev/null 2>&1 || true
+ file_size=$(arm-none-eabi-size .build/*.elf 2>/dev/null | awk '/elf/ {print $1}' 2>/dev/null || true)
+
+ if [[ "$last_size" == 0 ]] ; then last_size=$file_size ; fi
+ if [[ -z "$file_size" ]] ; then file_size=0 ; fi
+
+ if [[ -n "$last_line" ]] ; then
+ size_delta=$(( $last_size - $file_size ))
+ if { [[ -n "${skip_zero:-}" ]] && [[ $size_delta -ne 0 ]] ; } || [[ $file_size -eq 0 ]] ; then
+ printf "Size: %8d, delta: %+6d -- %s\n" "$last_size" "$size_delta" "$last_line"
+ fi
+ fi
+
+ last_size=$file_size
+ last_line=$line
+ done
+
+ if [ -n "$last_line" ] ; then
+ size_delta=0
+ printf "Size: %8d, delta: %+6d -- %s\n" "$last_size" "$size_delta" "$last_line"
+ fi
+}
+
+# The actual execution of all the builds needs to be the last command in the entire script
+# - During builds, this script file will disappear, so we need the entire script to be
+# loaded into the script interpreter at the time of execution. Do not refactor.
+build_executor
diff --git a/util/udev/50-qmk.rules b/util/udev/50-qmk.rules
index db27d4dc81..57806f9df0 100644
--- a/util/udev/50-qmk.rules
+++ b/util/udev/50-qmk.rules
@@ -33,6 +33,9 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05dc", TAG+="uacc
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="6124", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
# Caterina (Pro Micro)
+## pid.codes shared PID
+### Keyboardio Atreus 2 Bootloader
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="2302", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
## Spark Fun Electronics
### Pro Micro 3V3/8MHz
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b4f", ATTRS{idProduct}=="9203", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
diff --git a/util/update_chibios_mirror.sh b/util/update_chibios_mirror.sh
index 83aee22817..0bf648ebfd 100755
--- a/util/update_chibios_mirror.sh
+++ b/util/update_chibios_mirror.sh
@@ -7,10 +7,10 @@
chibios_branches="trunk stable_20.3.x stable_21.6.x"
# The ChibiOS tags to mirror
-chibios_tags="ver20.3.1 ver20.3.2 ver20.3.3 ver21.6.0"
+chibios_tags="ver20.3.1 ver20.3.2 ver20.3.3 ver20.3.4 ver21.6.0"
# The ChibiOS-Contrib branches to mirror
-contrib_branches="chibios-20.3.x"
+contrib_branches="chibios-20.3.x chibios-21.6.x"
################################
# Actions