aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Vagrantfile2
-rw-r--r--build_json.mk12
-rw-r--r--build_keyboard.mk18
-rw-r--r--build_test.mk1
-rw-r--r--common_features.mk42
-rw-r--r--data/schemas/api_keyboard.jsonschema44
-rw-r--r--data/schemas/definitions.jsonschema107
-rw-r--r--data/schemas/keyboard.jsonschema251
-rw-r--r--docs/_summary.md1
-rw-r--r--docs/breaking_changes.md4
-rw-r--r--docs/chibios_upgrade_instructions.md56
-rw-r--r--docs/config_options.md29
-rw-r--r--docs/custom_quantum_functions.md8
-rw-r--r--docs/eeprom_driver.md3
-rw-r--r--docs/feature_debounce_type.md4
-rw-r--r--docs/feature_haptic_feedback.md26
-rw-r--r--docs/feature_oled_driver.md4
-rw-r--r--docs/feature_rgb_matrix.md69
-rw-r--r--docs/feature_split_keyboard.md114
-rw-r--r--docs/feature_st7565.md274
-rw-r--r--drivers/avr/i2c_master.c19
-rw-r--r--drivers/avr/i2c_slave.c29
-rw-r--r--drivers/avr/i2c_slave.h13
-rw-r--r--drivers/avr/serial.c82
-rw-r--r--drivers/avr/serial.h62
-rw-r--r--drivers/awinic/aw20216.c170
-rw-r--r--drivers/awinic/aw20216.h251
-rw-r--r--drivers/chibios/serial.c52
-rw-r--r--drivers/chibios/serial.h62
-rw-r--r--drivers/chibios/serial_usart.c47
-rw-r--r--drivers/chibios/spi_master.c70
-rw-r--r--drivers/chibios/spi_master.h19
-rw-r--r--drivers/eeprom/eeprom_i2c.c23
-rw-r--r--drivers/haptic/haptic.c71
-rw-r--r--drivers/lcd/st7565.c496
-rw-r--r--drivers/lcd/st7565.h219
-rw-r--r--drivers/oled/oled_driver.c26
-rw-r--r--drivers/oled/oled_driver.h4
-rw-r--r--drivers/sensors/adns5050.c (renamed from keyboards/ploopyco/adns5050.c)10
-rw-r--r--drivers/sensors/adns5050.h (renamed from keyboards/ploopyco/adns5050.h)0
-rw-r--r--drivers/sensors/adns9800.c (renamed from keyboards/oddball/adns/adns.c)2
-rw-r--r--drivers/sensors/adns9800.h (renamed from keyboards/oddball/adns/adns.h)0
-rw-r--r--drivers/sensors/adns9800_srom_A6.h (renamed from keyboards/oddball/adns/adns9800_srom_A6.h)0
-rw-r--r--drivers/sensors/pimoroni_trackball.c (renamed from keyboards/draculad/keymaps/pimoroni/pimoroni_trackball.c)55
-rw-r--r--drivers/sensors/pimoroni_trackball.h (renamed from users/drashna/pimoroni_trackball.h)0
-rw-r--r--drivers/sensors/pmw3360.c (renamed from keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.c)42
-rw-r--r--drivers/sensors/pmw3360.h (renamed from keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.h)1
-rw-r--r--drivers/sensors/pmw3360_firmware.h (renamed from keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360_firmware.h)0
-rw-r--r--drivers/serial.h46
-rw-r--r--keyboards/anavi/macropad8/keymaps/default/config.h19
-rw-r--r--keyboards/basekeys/trifecta/config.h4
-rwxr-xr-xkeyboards/bm40hsrgb/config.h4
-rw-r--r--keyboards/bm68rgb/keymaps/peepeetee/config.h2
-rw-r--r--keyboards/boardsource/the_mark/config.h2
-rw-r--r--keyboards/checkerboards/nop60/info.json138
-rw-r--r--keyboards/crkbd/keymaps/devdev/config.h14
-rw-r--r--keyboards/crkbd/keymaps/gotham/config.h2
-rw-r--r--keyboards/crkbd/keymaps/kidbrazil/config.h2
-rw-r--r--keyboards/crkbd/keymaps/rpbaptist/config.h2
-rw-r--r--keyboards/crkbd/keymaps/soundmonster/config.h4
-rw-r--r--keyboards/crkbd/readme.md2
-rw-r--r--keyboards/draculad/config.h2
-rw-r--r--keyboards/draculad/keymaps/pimoroni/keymap.c2
-rw-r--r--keyboards/draculad/keymaps/pimoroni/pimoroni_trackball.h35
-rw-r--r--keyboards/draculad/keymaps/pimoroni/rules.mk2
-rw-r--r--keyboards/dztech/dz60rgb/v1/config.h2
-rw-r--r--keyboards/dztech/dz60rgb/v2/config.h2
-rw-r--r--keyboards/dztech/dz60rgb_ansi/v1/config.h2
-rw-r--r--keyboards/dztech/dz60rgb_ansi/v2/config.h2
-rw-r--r--keyboards/dztech/dz60rgb_wkl/v1/config.h2
-rw-r--r--keyboards/dztech/dz60rgb_wkl/v2/config.h2
-rw-r--r--keyboards/dztech/dz65rgb/v1/config.h4
-rw-r--r--keyboards/dztech/dz65rgb/v2/config.h2
-rw-r--r--keyboards/ergodox_ez/config.h2
-rw-r--r--keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h2
-rw-r--r--keyboards/ergodox_infinity/config.h15
-rw-r--r--keyboards/ergodox_infinity/ergodox_infinity.c302
-rw-r--r--keyboards/ergodox_infinity/matrix.c18
-rw-r--r--keyboards/ergodox_infinity/rules.mk7
-rw-r--r--keyboards/geekboards/macropad_v2/config.h4
-rw-r--r--keyboards/geekboards/tester/config.h4
-rw-r--r--keyboards/gmmk/pro/config.h17
-rw-r--r--keyboards/gmmk/pro/halconf.h7
-rw-r--r--keyboards/gmmk/pro/mcuconf.h6
-rw-r--r--keyboards/gmmk/pro/pro.c222
-rw-r--r--keyboards/gmmk/pro/rules.mk2
-rw-r--r--keyboards/handwired/colorlice/config.h2
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.h2
-rw-r--r--keyboards/handwired/dactyl_manuform/5x6_right_trackball/rules.mk2
-rw-r--r--keyboards/handwired/frankie_macropad/keymaps/default/config.h19
-rw-r--r--keyboards/handwired/freoduo/rules.mk4
-rw-r--r--keyboards/handwired/hnah40rgb/config.h2
-rw-r--r--keyboards/handwired/p65rgb/config.h2
-rw-r--r--keyboards/helix/rev2/keymaps/default/rules.mk2
-rw-r--r--keyboards/helix/rev3_4rows/config.h2
-rw-r--r--keyboards/helix/rev3_5rows/config.h2
-rw-r--r--keyboards/hs60/v1/config.h2
-rw-r--r--keyboards/kbdfans/bella/rgb/config.h2
-rw-r--r--keyboards/kbdfans/bella/rgb_iso/config.h2
-rw-r--r--keyboards/kbdfans/kbd67/mkiirgb/v1/config.h4
-rw-r--r--keyboards/kbdfans/kbd67/mkiirgb/v2/config.h4
-rw-r--r--keyboards/kbdfans/kbd67/rev1/keymaps/default/config.h2
-rw-r--r--keyboards/kbdfans/kbdmini/config.h2
-rwxr-xr-xkeyboards/kbdfans/maja/config.h4
-rw-r--r--keyboards/keebio/iris/rev2/rules.mk2
-rw-r--r--keyboards/keebio/iris/rev3/rules.mk1
-rw-r--r--keyboards/keebio/iris/rev4/rules.mk2
-rw-r--r--keyboards/keebio/quefrency/rules.mk1
-rw-r--r--keyboards/keebio/viterbi/rev2/rules.mk2
-rw-r--r--keyboards/keebio/viterbi/rules.mk8
-rw-r--r--keyboards/kinesis/kint36/config.h2
-rw-r--r--keyboards/latin17rgb/config.h32
-rw-r--r--keyboards/latin60rgb/config.h31
-rw-r--r--keyboards/le_chiffre/config.h2
-rw-r--r--keyboards/marksard/rhymestone/rev1/config.h2
-rw-r--r--keyboards/massdrop/alt/keymaps/pregame/config.h4
-rw-r--r--keyboards/massdrop/alt/keymaps/urbanvanilla/config.h2
-rw-r--r--keyboards/massdrop/ctrl/keymaps/endgame/config.h2
-rw-r--r--keyboards/massdrop/ctrl/keymaps/matthewrobo/config.h2
-rw-r--r--keyboards/mechlovin/adelais/rgb_led/rev1/config.h4
-rw-r--r--keyboards/mechlovin/adelais/rgb_led/rev2/config.h6
-rw-r--r--keyboards/mechlovin/delphine/rgb_led/config.h4
-rw-r--r--keyboards/mechlovin/hannah60rgb/rev1/config.h4
-rw-r--r--keyboards/mechlovin/hannah60rgb/rev2/config.h4
-rw-r--r--keyboards/mechlovin/infinity87/rgb_rev1/config.h2
-rw-r--r--keyboards/melgeek/mj61/config.h2
-rw-r--r--keyboards/melgeek/mj63/config.h2
-rw-r--r--keyboards/melgeek/mj64/config.h2
-rw-r--r--keyboards/melgeek/mj65/config.h2
-rw-r--r--keyboards/melgeek/mojo75/config.h2
-rw-r--r--keyboards/melgeek/z70ultra/config.h2
-rw-r--r--keyboards/miller/gm862/config.h4
-rw-r--r--keyboards/monstargear/xo87/rgb/config.h2
-rw-r--r--keyboards/moonlander/config.h2
-rw-r--r--keyboards/mt84/keymaps/default/config.h19
-rw-r--r--keyboards/naked48/keymaps/salicylic/config.h3
-rw-r--r--keyboards/oddball/optical_sensor/optical_sensor.h2
-rw-r--r--keyboards/oddball/rules.mk2
-rw-r--r--keyboards/opendeck/32/rev1/config.h2
-rw-r--r--keyboards/percent/canoe_gen2/config.h2
-rw-r--r--keyboards/phase_studio/titan65/config.h2
-rw-r--r--keyboards/planck/ez/config.h2
-rw-r--r--keyboards/planck/rev6/config.h2
-rw-r--r--keyboards/ploopyco/mouse/mouse.h2
-rw-r--r--keyboards/ploopyco/mouse/rules.mk2
-rw-r--r--keyboards/ploopyco/pmw3360.c218
-rw-r--r--keyboards/ploopyco/pmw3360.h103
-rw-r--r--keyboards/ploopyco/pmw3360_firmware.h300
-rw-r--r--keyboards/ploopyco/trackball/rules.mk2
-rw-r--r--keyboards/ploopyco/trackball/trackball.h2
-rw-r--r--keyboards/ploopyco/trackball_mini/rules.mk2
-rw-r--r--keyboards/ploopyco/trackball_mini/trackball_mini.h2
-rw-r--r--keyboards/ploopyco/trackball_nano/rules.mk2
-rw-r--r--keyboards/ploopyco/trackball_nano/trackball_nano.h2
-rw-r--r--keyboards/ramonimbao/chevron/info.json2
-rw-r--r--keyboards/sendyyeah/75pixels/info.json62
-rw-r--r--keyboards/setta21/keymaps/salicylic/config.h3
-rw-r--r--keyboards/sofle/keymaps/devdev/config.h44
-rw-r--r--keyboards/sofle/keymaps/killmaster/config.h64
-rw-r--r--keyboards/sofle/keymaps/killmaster/keymap.c403
-rw-r--r--keyboards/sofle/keymaps/killmaster/readme.md19
-rw-r--r--keyboards/sofle/keymaps/killmaster/rules.mk4
-rw-r--r--keyboards/sofle/keymaps/rgb_default/config.h44
-rw-r--r--keyboards/sofle/rev1/readme.md27
-rw-r--r--keyboards/sofle/rev1/rev1.c86
-rw-r--r--keyboards/terrazzo/config.h4
-rw-r--r--keyboards/tkc/portico/config.h2
-rw-r--r--keyboards/tokyokeyboard/tokyo60/config.h (renamed from keyboards/tokyo60/config.h)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/info.json (renamed from keyboards/tokyo60/info.json)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/keymaps/default/config.h (renamed from keyboards/tokyo60/keymaps/default/config.h)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/keymaps/default/keymap.c (renamed from keyboards/tokyo60/keymaps/default/keymap.c)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/keymaps/swappedBottomRow/config.h (renamed from keyboards/tokyo60/keymaps/swappedBottomRow/config.h)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/keymaps/swappedBottomRow/keymap.c (renamed from keyboards/tokyo60/keymaps/swappedBottomRow/keymap.c)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/keymaps/via/keymap.c (renamed from keyboards/tokyo60/keymaps/via/keymap.c)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/keymaps/via/rules.mk (renamed from keyboards/tokyo60/keymaps/via/rules.mk)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/readme.md (renamed from keyboards/tokyo60/readme.md)8
-rw-r--r--keyboards/tokyokeyboard/tokyo60/rules.mk (renamed from keyboards/tokyo60/rules.mk)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/tokyo60.c (renamed from keyboards/tokyo60/tokyo60.c)0
-rw-r--r--keyboards/tokyokeyboard/tokyo60/tokyo60.h (renamed from keyboards/tokyo60/tokyo60.h)0
-rw-r--r--keyboards/whitefox/config.h14
-rw-r--r--keyboards/whitefox/rules.mk8
-rw-r--r--keyboards/whitefox/whitefox.c76
-rw-r--r--keyboards/xbows/nature/config.h2
-rw-r--r--keyboards/xbows/woody/config.h6
-rw-r--r--keyboards/yncognito/batpad/config.h14
-rw-r--r--layouts/community/ergodox/drashna/config.h1
-rw-r--r--layouts/community/ortho_4x12/bocaj/config.h2
-rw-r--r--layouts/community/ortho_4x12/drashna/config.h2
-rw-r--r--layouts/community/split_3x6_3/drashna/config.h2
m---------lib/chibios0
m---------lib/chibios-contrib0
-rwxr-xr-xlib/python/qmk/cli/doctor/__init__.py5
-rw-r--r--lib/python/qmk/cli/doctor/check.py (renamed from lib/python/qmk/os_helpers/__init__.py)18
-rw-r--r--lib/python/qmk/cli/doctor/linux.py (renamed from lib/python/qmk/os_helpers/linux/__init__.py)26
-rw-r--r--lib/python/qmk/cli/doctor/macos.py13
-rwxr-xr-xlib/python/qmk/cli/doctor/main.py (renamed from lib/python/qmk/cli/doctor.py)43
-rw-r--r--lib/python/qmk/cli/doctor/windows.py14
-rwxr-xr-xlib/python/qmk/cli/format/json.py5
-rw-r--r--lib/python/qmk/info.py11
-rw-r--r--lib/python/qmk/json_schema.py34
-rw-r--r--platforms/chibios/IC_TEENSY_4_1/board/board.mk1
-rw-r--r--platforms/chibios/IC_TEENSY_4_1/rules.mk1
-rw-r--r--quantum/crc.c59
-rw-r--r--quantum/crc.h (renamed from quantum/rgb.h)45
-rw-r--r--quantum/debounce.h2
-rw-r--r--quantum/debounce/asym_eager_defer_pk.c171
-rw-r--r--quantum/debounce/none.c31
-rw-r--r--quantum/debounce/sym_defer_g.c26
-rw-r--r--quantum/debounce/sym_defer_pk.c67
-rw-r--r--quantum/debounce/sym_eager_pk.c72
-rw-r--r--quantum/debounce/sym_eager_pr.c76
-rw-r--r--quantum/debounce/tests/asym_eager_defer_pk_tests.cpp374
-rw-r--r--quantum/debounce/tests/debounce_test_common.cpp229
-rw-r--r--quantum/debounce/tests/debounce_test_common.h83
-rw-r--r--quantum/debounce/tests/rules.mk44
-rw-r--r--quantum/debounce/tests/sym_defer_g_tests.cpp223
-rw-r--r--quantum/debounce/tests/sym_defer_pk_tests.cpp225
-rw-r--r--quantum/debounce/tests/sym_eager_pk_tests.cpp237
-rw-r--r--quantum/debounce/tests/sym_eager_pr_tests.cpp280
-rw-r--r--quantum/debounce/tests/testlist.mk6
-rw-r--r--quantum/led_matrix/animations/alpha_mods_anim.h (renamed from quantum/led_matrix_animations/alpha_mods_anim.h)2
-rw-r--r--quantum/led_matrix/animations/band_anim.h (renamed from quantum/led_matrix_animations/band_anim.h)2
-rw-r--r--quantum/led_matrix/animations/band_pinwheel_anim.h (renamed from quantum/led_matrix_animations/band_pinwheel_anim.h)2
-rw-r--r--quantum/led_matrix/animations/band_spiral_anim.h (renamed from quantum/led_matrix_animations/band_spiral_anim.h)2
-rw-r--r--quantum/led_matrix/animations/breathing_anim.h (renamed from quantum/led_matrix_animations/breathing_anim.h)2
-rw-r--r--quantum/led_matrix/animations/cycle_left_right_anim.h (renamed from quantum/led_matrix_animations/cycle_left_right_anim.h)2
-rw-r--r--quantum/led_matrix/animations/cycle_out_in_anim.h (renamed from quantum/led_matrix_animations/cycle_out_in_anim.h)2
-rw-r--r--quantum/led_matrix/animations/cycle_up_down_anim.h (renamed from quantum/led_matrix_animations/cycle_up_down_anim.h)2
-rw-r--r--quantum/led_matrix/animations/dual_beacon_anim.h (renamed from quantum/led_matrix_animations/dual_beacon_anim.h)2
-rw-r--r--quantum/led_matrix/animations/led_matrix_effects.inc18
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_dx_dy.h (renamed from quantum/led_matrix_runners/effect_runner_dx_dy.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h (renamed from quantum/led_matrix_runners/effect_runner_dx_dy_dist.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_i.h (renamed from quantum/led_matrix_runners/effect_runner_i.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_reactive.h (renamed from quantum/led_matrix_runners/effect_runner_reactive.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h (renamed from quantum/led_matrix_runners/effect_runner_reactive_splash.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h (renamed from quantum/led_matrix_runners/effect_runner_sin_cos_i.h)0
-rw-r--r--quantum/led_matrix/animations/runners/led_matrix_runners.inc6
-rw-r--r--quantum/led_matrix/animations/solid_anim.h (renamed from quantum/led_matrix_animations/solid_anim.h)0
-rw-r--r--quantum/led_matrix/animations/solid_reactive_cross.h (renamed from quantum/led_matrix_animations/solid_reactive_cross.h)4
-rw-r--r--quantum/led_matrix/animations/solid_reactive_nexus.h (renamed from quantum/led_matrix_animations/solid_reactive_nexus.h)4
-rw-r--r--quantum/led_matrix/animations/solid_reactive_simple_anim.h (renamed from quantum/led_matrix_animations/solid_reactive_simple_anim.h)4
-rw-r--r--quantum/led_matrix/animations/solid_reactive_wide.h (renamed from quantum/led_matrix_animations/solid_reactive_wide.h)4
-rw-r--r--quantum/led_matrix/animations/solid_splash_anim.h (renamed from quantum/led_matrix_animations/solid_splash_anim.h)4
-rw-r--r--quantum/led_matrix/animations/wave_left_right_anim.h (renamed from quantum/led_matrix_animations/wave_left_right_anim.h)2
-rw-r--r--quantum/led_matrix/animations/wave_up_down_anim.h (renamed from quantum/led_matrix_animations/wave_up_down_anim.h)2
-rw-r--r--quantum/led_matrix/led_matrix.c (renamed from quantum/led_matrix.c)46
-rw-r--r--quantum/led_matrix/led_matrix.h (renamed from quantum/led_matrix.h)2
-rw-r--r--quantum/led_matrix/led_matrix_drivers.c (renamed from quantum/led_matrix_drivers.c)0
-rw-r--r--quantum/led_matrix/led_matrix_types.h (renamed from quantum/led_matrix_types.h)0
-rw-r--r--quantum/led_matrix_animations/led_matrix_effects.inc18
-rw-r--r--quantum/matrix.c79
-rw-r--r--quantum/mcu_selection.mk40
-rw-r--r--quantum/process_keycode/process_rgb.c1
-rw-r--r--quantum/quantum.h4
-rw-r--r--quantum/rgb_matrix/animations/alpha_mods_anim.h (renamed from quantum/rgb_matrix_animations/alpha_mods_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/breathing_anim.h (renamed from quantum/rgb_matrix_animations/breathing_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h (renamed from quantum/rgb_matrix_animations/colorband_pinwheel_sat_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h (renamed from quantum/rgb_matrix_animations/colorband_pinwheel_val_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_sat_anim.h (renamed from quantum/rgb_matrix_animations/colorband_sat_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h (renamed from quantum/rgb_matrix_animations/colorband_spiral_sat_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_spiral_val_anim.h (renamed from quantum/rgb_matrix_animations/colorband_spiral_val_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_val_anim.h (renamed from quantum/rgb_matrix_animations/colorband_val_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_all_anim.h (renamed from quantum/rgb_matrix_animations/cycle_all_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_left_right_anim.h (renamed from quantum/rgb_matrix_animations/cycle_left_right_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_out_in_anim.h (renamed from quantum/rgb_matrix_animations/cycle_out_in_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h (renamed from quantum/rgb_matrix_animations/cycle_out_in_dual_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_pinwheel_anim.h (renamed from quantum/rgb_matrix_animations/cycle_pinwheel_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_spiral_anim.h (renamed from quantum/rgb_matrix_animations/cycle_spiral_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_up_down_anim.h (renamed from quantum/rgb_matrix_animations/cycle_up_down_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/digital_rain_anim.h (renamed from quantum/rgb_matrix_animations/digital_rain_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/dual_beacon_anim.h (renamed from quantum/rgb_matrix_animations/dual_beacon_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/gradient_left_right_anim.h (renamed from quantum/rgb_matrix_animations/gradient_left_right_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/gradient_up_down_anim.h (renamed from quantum/rgb_matrix_animations/gradient_up_down_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/hue_breathing_anim.h (renamed from quantum/rgb_matrix_animations/hue_breathing_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/hue_pendulum_anim.h (renamed from quantum/rgb_matrix_animations/hue_pendulum_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/hue_wave_anim.h (renamed from quantum/rgb_matrix_animations/hue_wave_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/jellybean_raindrops_anim.h (renamed from quantum/rgb_matrix_animations/jellybean_raindrops_anim.h)2
-rw-r--r--quantum/rgb_matrix/animations/rainbow_beacon_anim.h (renamed from quantum/rgb_matrix_animations/rainbow_beacon_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h (renamed from quantum/rgb_matrix_animations/rainbow_moving_chevron_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h (renamed from quantum/rgb_matrix_animations/rainbow_pinwheels_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/raindrops_anim.h (renamed from quantum/rgb_matrix_animations/raindrops_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/rgb_matrix_effects.inc37
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h (renamed from quantum/rgb_matrix_runners/effect_runner_dx_dy.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h (renamed from quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_i.h (renamed from quantum/rgb_matrix_runners/effect_runner_i.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_reactive.h (renamed from quantum/rgb_matrix_runners/effect_runner_reactive.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h (renamed from quantum/rgb_matrix_runners/effect_runner_reactive_splash.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h (renamed from quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc6
-rw-r--r--quantum/rgb_matrix/animations/solid_color_anim.h (renamed from quantum/rgb_matrix_animations/solid_color_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_anim.h (renamed from quantum/rgb_matrix_animations/solid_reactive_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_cross.h (renamed from quantum/rgb_matrix_animations/solid_reactive_cross.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_nexus.h (renamed from quantum/rgb_matrix_animations/solid_reactive_nexus.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_simple_anim.h (renamed from quantum/rgb_matrix_animations/solid_reactive_simple_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_wide.h (renamed from quantum/rgb_matrix_animations/solid_reactive_wide.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_splash_anim.h (renamed from quantum/rgb_matrix_animations/solid_splash_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/splash_anim.h (renamed from quantum/rgb_matrix_animations/splash_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/typing_heatmap_anim.h (renamed from quantum/rgb_matrix_animations/typing_heatmap_anim.h)0
-rw-r--r--quantum/rgb_matrix/rgb_matrix.c (renamed from quantum/rgb_matrix.c)46
-rw-r--r--quantum/rgb_matrix/rgb_matrix.h (renamed from quantum/rgb_matrix.h)4
-rw-r--r--quantum/rgb_matrix/rgb_matrix_drivers.c (renamed from quantum/rgb_matrix_drivers.c)16
-rw-r--r--quantum/rgb_matrix/rgb_matrix_types.h (renamed from quantum/rgb_matrix_types.h)0
-rw-r--r--quantum/rgb_matrix_animations/rgb_matrix_effects.inc37
-rw-r--r--quantum/serial_link/system/serial_link.c22
-rw-r--r--quantum/split_common/matrix.c83
-rw-r--r--quantum/split_common/post_config.h9
-rw-r--r--quantum/split_common/transaction_id_define.h94
-rw-r--r--quantum/split_common/transactions.c670
-rw-r--r--quantum/split_common/transactions.h54
-rw-r--r--quantum/split_common/transport.c484
-rw-r--r--quantum/split_common/transport.h165
-rw-r--r--testlist.mk1
-rw-r--r--tmk_core/avr.mk2
-rw-r--r--tmk_core/chibios.mk6
-rw-r--r--tmk_core/common/arm_atsam/_timer.h19
-rw-r--r--tmk_core/common/avr/_timer.h19
-rw-r--r--tmk_core/common/avr/gpio.h15
-rw-r--r--tmk_core/common/chibios/_timer.h19
-rw-r--r--tmk_core/common/chibios/bootloader.c2
-rw-r--r--tmk_core/common/chibios/gpio.h16
-rw-r--r--tmk_core/common/host.c14
-rw-r--r--tmk_core/common/keyboard.c24
-rw-r--r--tmk_core/common/sync_timer.c2
-rw-r--r--tmk_core/common/sync_timer.h2
-rw-r--r--tmk_core/common/timer.h24
-rw-r--r--tmk_core/protocol/chibios/usb_main.c34
-rw-r--r--tmk_core/protocol/lufa/lufa.c34
-rw-r--r--tmk_core/protocol/usb_descriptor.c2
-rw-r--r--tmk_core/protocol/vusb/vusb.c3
-rw-r--r--tmk_core/rules.mk2
-rw-r--r--users/bcat/config.h2
-rw-r--r--users/bocaj/config.h2
-rw-r--r--users/curry/config.h2
-rw-r--r--users/drashna/config.h2
-rw-r--r--users/drashna/drashna.h2
-rw-r--r--users/drashna/pimoroni_trackball.c151
-rw-r--r--users/drashna/rules.mk2
-rw-r--r--users/spidey3/config.h4
-rw-r--r--users/tominabox1/config.h2
-rwxr-xr-xutil/update_chibios_mirror.sh55
340 files changed, 7781 insertions, 2663 deletions
diff --git a/Vagrantfile b/Vagrantfile
index adb93a3ce..8125b0589 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -6,7 +6,7 @@ Vagrant.configure(2) do |config|
6 config.vm.define "qmk_firmware" 6 config.vm.define "qmk_firmware"
7 7
8 # VMware/Virtualbox ( and also Hyperv/Parallels) 64 bit 8 # VMware/Virtualbox ( and also Hyperv/Parallels) 64 bit
9 config.vm.box = "generic/debian9" 9 config.vm.box = "generic/debian10"
10 10
11 config.vm.synced_folder '.', '/vagrant' 11 config.vm.synced_folder '.', '/vagrant'
12 12
diff --git a/build_json.mk b/build_json.mk
index 8822be6a1..28659f260 100644
--- a/build_json.mk
+++ b/build_json.mk
@@ -1,22 +1,22 @@
1# Look for a json keymap file 1# Look for a json keymap file
2ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.json)","") 2ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.json)","")
3 KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c 3 KEYMAP_C := $(KEYMAP_OUTPUT)/keymap.c
4 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_5)/keymap.json 4 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_5)/keymap.json
5 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5) 5 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_5)
6else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.json)","") 6else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_4)/keymap.json)","")
7 KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c 7 KEYMAP_C := $(KEYMAP_OUTPUT)/keymap.c
8 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_4)/keymap.json 8 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_4)/keymap.json
9 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4) 9 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_4)
10else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.json)","") 10else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_3)/keymap.json)","")
11 KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c 11 KEYMAP_C := $(KEYMAP_OUTPUT)/keymap.c
12 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_3)/keymap.json 12 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_3)/keymap.json
13 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3) 13 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_3)
14else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.json)","") 14else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_2)/keymap.json)","")
15 KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c 15 KEYMAP_C := $(KEYMAP_OUTPUT)/keymap.c
16 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_2)/keymap.json 16 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_2)/keymap.json
17 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2) 17 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_2)
18else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","") 18else ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_1)/keymap.json)","")
19 KEYMAP_C := $(KEYBOARD_OUTPUT)/src/keymap.c 19 KEYMAP_C := $(KEYMAP_OUTPUT)/keymap.c
20 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_1)/keymap.json 20 KEYMAP_JSON := $(MAIN_KEYMAP_PATH_1)/keymap.json
21 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1) 21 KEYMAP_PATH := $(MAIN_KEYMAP_PATH_1)
22endif 22endif
@@ -27,5 +27,5 @@ ifneq ("$(wildcard $(KEYMAP_PATH))", "")
27endif 27endif
28 28
29# Generate the keymap.c 29# Generate the keymap.c
30$(KEYBOARD_OUTPUT)/src/keymap.c: $(KEYMAP_JSON) 30$(KEYMAP_C): $(KEYMAP_JSON)
31 $(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON) 31 $(QMK_BIN) json2c --quiet --output $(KEYMAP_C) $(KEYMAP_JSON)
diff --git a/build_keyboard.mk b/build_keyboard.mk
index 91a6c23b7..4c4ff3b5f 100644
--- a/build_keyboard.mk
+++ b/build_keyboard.mk
@@ -103,6 +103,15 @@ MAIN_KEYMAP_PATH_5 := $(KEYBOARD_PATH_5)/keymaps/$(KEYMAP)
103INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/rules.mk) 103INFO_RULES_MK = $(shell $(QMK_BIN) generate-rules-mk --quiet --escape --keyboard $(KEYBOARD) --output $(KEYBOARD_OUTPUT)/src/rules.mk)
104include $(INFO_RULES_MK) 104include $(INFO_RULES_MK)
105 105
106ifneq ($(FORCE_LAYOUT),)
107 TARGET := $(TARGET)_$(FORCE_LAYOUT)
108endif
109
110# Object files and generated keymap directory
111# To put object files in current directory, use a dot (.), do NOT make
112# this an empty or blank macro!
113KEYMAP_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
114
106# Check for keymap.json first, so we can regenerate keymap.c 115# Check for keymap.json first, so we can regenerate keymap.c
107include build_json.mk 116include build_json.mk
108 117
@@ -145,10 +154,6 @@ ifeq ($(strip $(CONVERT_TO_PROTON_C)), yes)
145 include platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk 154 include platforms/chibios/QMK_PROTON_C/convert_to_proton_c.mk
146endif 155endif
147 156
148ifneq ($(FORCE_LAYOUT),)
149 TARGET := $(TARGET)_$(FORCE_LAYOUT)
150endif
151
152include quantum/mcu_selection.mk 157include quantum/mcu_selection.mk
153 158
154# Find all the C source files to be compiled in subfolders. 159# Find all the C source files to be compiled in subfolders.
@@ -327,11 +332,6 @@ endif
327# Disable features that a keyboard doesn't support 332# Disable features that a keyboard doesn't support
328-include disable_features.mk 333-include disable_features.mk
329 334
330# Object files directory
331# To put object files in current directory, use a dot (.), do NOT make
332# this an empty or blank macro!
333KEYMAP_OUTPUT := $(BUILD_DIR)/obj_$(TARGET)
334
335ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","") 335ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
336 CONFIG_H += $(KEYMAP_PATH)/config.h 336 CONFIG_H += $(KEYMAP_PATH)/config.h
337endif 337endif
diff --git a/build_test.mk b/build_test.mk
index 77c4265f9..5171c58c3 100644
--- a/build_test.mk
+++ b/build_test.mk
@@ -49,6 +49,7 @@ endif
49 49
50include common_features.mk 50include common_features.mk
51include $(TMK_PATH)/common.mk 51include $(TMK_PATH)/common.mk
52include $(QUANTUM_PATH)/debounce/tests/rules.mk
52include $(QUANTUM_PATH)/sequencer/tests/rules.mk 53include $(QUANTUM_PATH)/sequencer/tests/rules.mk
53include $(QUANTUM_PATH)/serial_link/tests/rules.mk 54include $(QUANTUM_PATH)/serial_link/tests/rules.mk
54ifneq ($(filter $(FULL_TESTS),$(TEST)),) 55ifneq ($(filter $(FULL_TESTS),$(TEST)),)
diff --git a/common_features.mk b/common_features.mk
index 1a9fd46b5..a790b8432 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -230,9 +230,12 @@ ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
230 # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines 230 # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
231 OPT_DEFS += -DLIB8_ATTINY 231 OPT_DEFS += -DLIB8_ATTINY
232endif 232endif
233 COMMON_VPATH += $(QUANTUM_DIR)/led_matrix
234 COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations
235 COMMON_VPATH += $(QUANTUM_DIR)/led_matrix/animations/runners
233 SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c 236 SRC += $(QUANTUM_DIR)/process_keycode/process_backlight.c
234 SRC += $(QUANTUM_DIR)/led_matrix.c 237 SRC += $(QUANTUM_DIR)/led_matrix/led_matrix.c
235 SRC += $(QUANTUM_DIR)/led_matrix_drivers.c 238 SRC += $(QUANTUM_DIR)/led_matrix/led_matrix_drivers.c
236 CIE1931_CURVE := yes 239 CIE1931_CURVE := yes
237 240
238 ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731) 241 ifeq ($(strip $(LED_MATRIX_DRIVER)), IS31FL3731)
@@ -244,7 +247,7 @@ endif
244endif 247endif
245 248
246RGB_MATRIX_ENABLE ?= no 249RGB_MATRIX_ENABLE ?= no
247VALID_RGB_MATRIX_TYPES := IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 WS2812 custom 250VALID_RGB_MATRIX_TYPES := AW20216 IS31FL3731 IS31FL3733 IS31FL3737 IS31FL3741 WS2812 custom
248 251
249ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) 252ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
250 ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),) 253 ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
@@ -255,12 +258,22 @@ ifneq (,$(filter $(MCU), atmega16u2 atmega32u2 at90usb162))
255 # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines 258 # ATmegaxxU2 does not have hardware MUL instruction - lib8tion must be told to use software multiplication routines
256 OPT_DEFS += -DLIB8_ATTINY 259 OPT_DEFS += -DLIB8_ATTINY
257endif 260endif
261 COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix
262 COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations
263 COMMON_VPATH += $(QUANTUM_DIR)/rgb_matrix/animations/runners
258 SRC += $(QUANTUM_DIR)/color.c 264 SRC += $(QUANTUM_DIR)/color.c
259 SRC += $(QUANTUM_DIR)/rgb_matrix.c 265 SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix.c
260 SRC += $(QUANTUM_DIR)/rgb_matrix_drivers.c 266 SRC += $(QUANTUM_DIR)/rgb_matrix/rgb_matrix_drivers.c
261 CIE1931_CURVE := yes 267 CIE1931_CURVE := yes
262 RGB_KEYCODES_ENABLE := yes 268 RGB_KEYCODES_ENABLE := yes
263 269
270 ifeq ($(strip $(RGB_MATRIX_DRIVER)), AW20216)
271 OPT_DEFS += -DAW20216 -DSTM32_SPI -DHAL_USE_SPI=TRUE
272 COMMON_VPATH += $(DRIVER_PATH)/awinic
273 SRC += aw20216.c
274 QUANTUM_LIB_SRC += spi_master.c
275 endif
276
264 ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731) 277 ifeq ($(strip $(RGB_MATRIX_DRIVER)), IS31FL3731)
265 OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE 278 OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
266 COMMON_VPATH += $(DRIVER_PATH)/issi 279 COMMON_VPATH += $(DRIVER_PATH)/issi
@@ -529,7 +542,11 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
529 542
530 # Determine which (if any) transport files are required 543 # Determine which (if any) transport files are required
531 ifneq ($(strip $(SPLIT_TRANSPORT)), custom) 544 ifneq ($(strip $(SPLIT_TRANSPORT)), custom)
532 QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/transport.c 545 QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c \
546 $(QUANTUM_DIR)/split_common/transactions.c
547
548 OPT_DEFS += -DSPLIT_COMMON_TRANSACTIONS
549
533 # Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called. 550 # Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called.
534 # Unused functions are pruned away, which is why we can add multiple drivers here without bloat. 551 # Unused functions are pruned away, which is why we can add multiple drivers here without bloat.
535 ifeq ($(PLATFORM),AVR) 552 ifeq ($(PLATFORM),AVR)
@@ -550,6 +567,11 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
550 COMMON_VPATH += $(QUANTUM_PATH)/split_common 567 COMMON_VPATH += $(QUANTUM_PATH)/split_common
551endif 568endif
552 569
570ifeq ($(strip $(CRC_ENABLE)), yes)
571 OPT_DEFS += -DCRC_ENABLE
572 QUANTUM_LIB_SRC += crc.c
573endif
574
553HAPTIC_ENABLE ?= no 575HAPTIC_ENABLE ?= no
554ifneq ($(strip $(HAPTIC_ENABLE)),no) 576ifneq ($(strip $(HAPTIC_ENABLE)),no)
555 COMMON_VPATH += $(DRIVER_PATH)/haptic 577 COMMON_VPATH += $(DRIVER_PATH)/haptic
@@ -580,6 +602,14 @@ ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes)
580 SRC += oled_driver.c 602 SRC += oled_driver.c
581endif 603endif
582 604
605ifeq ($(strip $(ST7565_ENABLE)), yes)
606 OPT_DEFS += -DST7565_ENABLE
607 COMMON_VPATH += $(DRIVER_PATH)/oled # For glcdfont.h
608 COMMON_VPATH += $(DRIVER_PATH)/lcd
609 QUANTUM_LIB_SRC += spi_master.c
610 SRC += st7565.c
611endif
612
583include $(DRIVER_PATH)/qwiic/qwiic.mk 613include $(DRIVER_PATH)/qwiic/qwiic.mk
584 614
585ifeq ($(strip $(UCIS_ENABLE)), yes) 615ifeq ($(strip $(UCIS_ENABLE)), yes)
diff --git a/data/schemas/api_keyboard.jsonschema b/data/schemas/api_keyboard.jsonschema
index d570ee999..d638658a1 100644
--- a/data/schemas/api_keyboard.jsonschema
+++ b/data/schemas/api_keyboard.jsonschema
@@ -1,34 +1,22 @@
1{ 1{
2 "$id": "qmk.api.keyboard.v1",
2 "allOf": [ 3 "allOf": [
3 { "$ref": "qmk.keyboard.v1" }, 4 {"$ref": "qmk.keyboard.v1"},
4 { 5 {
5 "$id": "qmk.api.keyboard.v1", 6 "properties": {
6 "keymaps": { 7 "keymaps": {
7 "type": "string" 8 "type": "object",
8 }, 9 "properties": {
9 "parse_errors": { 10 "url": {"type": "string"}
10 "type": "array", 11 }
11 "items": { 12
12 "type": "string" 13 },
13 } 14 "parse_errors": {"$ref": "qmk.definitions.v1#/string_array"},
14 }, 15 "parse_warnings": {"$ref": "qmk.definitions.v1#/string_array"},
15 "parse_warnings": { 16 "processor_type": {"type": "string"},
16 "type": "array", 17 "protocol": {"type": "string"},
17 "items": { 18 "keyboard_folder": {"type": "string"},
18 "type": "string" 19 "platform": {"type": "string"}
19 }
20 },
21 "processor_type": {
22 "type": "string"
23 },
24 "protocol": {
25 "type": "string"
26 },
27 "keyboard_folder": {
28 "type": "string"
29 },
30 "platform": {
31 "type": "string"
32 } 20 }
33 } 21 }
34 ] 22 ]
diff --git a/data/schemas/definitions.jsonschema b/data/schemas/definitions.jsonschema
new file mode 100644
index 000000000..822f23707
--- /dev/null
+++ b/data/schemas/definitions.jsonschema
@@ -0,0 +1,107 @@
1{
2 "$schema": "http://json-schema.org/draft-07/schema#",
3 "$id": "qmk.definitions.v1",
4 "title": "Common definitions used across QMK's jsonschemas.",
5 "type": "object",
6 "boolean_array": {
7 "type": "object",
8 "additionalProperties": {"type": "boolean"}
9 },
10 "filename": {
11 "type": "string",
12 "minLength": 1,
13 "pattern": "^[0-9a-z_]*$"
14 },
15 "hex_number_2d": {
16 "type": "string",
17 "pattern": "^0x[0-9A-F]{2}$"
18 },
19 "hex_number_4d": {
20 "type": "string",
21 "pattern": "^0x[0-9A-F]{4}$"
22 },
23 "text_identifier": {
24 "type": "string",
25 "minLength": 1,
26 "maxLength": 250
27 },
28 "layout_macro": {
29 "oneOf": [
30 {
31 "type": "string",
32 "enum": ["LAYOUT", "LAYOUT_planck_1x2uC"]
33 },
34 {
35 "type": "string",
36 "pattern": "^LAYOUT_[0-9a-z_]*$"
37 }
38 ]
39 },
40 "key_unit": {
41 "type": "number",
42 "min": 0.25
43 },
44 "mcu_pin_array": {
45 "type": "array",
46 "items": {"$ref": "#/mcu_pin"}
47 },
48 "mcu_pin": {
49 "oneOf": [
50 {
51 "type": "string",
52 "pattern": "^[A-K]\\d{1,2}$"
53 },
54 {
55 "type": "string",
56 "pattern": "^LINE_PIN\\d{1,2}$"
57 },
58 {
59 "type": "number",
60 "multipleOf": 1
61 },
62 {
63 "type": "null"
64 }
65 ]
66 },
67 "signed_decimal": {
68 "type": "number"
69 },
70 "signed_int": {
71 "type": "number",
72 "multipleOf": 1
73 }
74 "signed_int_8": {
75 "type": "number",
76 "min": -127,
77 "max": 127,
78 "multipleOf": 1
79 }
80 "string_array": {
81 "type": "array",
82 "items": {
83 "type": "string"
84 }
85 },
86 "string_object": {
87 "type": "object",
88 "additionalProperties": {
89 "type": "string"
90 }
91 },
92 "unsigned_decimal": {
93 "type": "number",
94 "min": 0
95 },
96 "unsigned_int": {
97 "type": "number",
98 "min": 0,
99 "multipleOf": 1
100 }
101 "unsigned_int_8": {
102 "type": "number",
103 "min": 0,
104 "max": 255,
105 "multipleOf": 1
106 }
107}
diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema
index c335f49d5..d6d33ce4e 100644
--- a/data/schemas/keyboard.jsonschema
+++ b/data/schemas/keyboard.jsonschema
@@ -1,24 +1,12 @@
1{ 1{
2 "$schema": "http://json-schema.org/schema#", 2 "$schema": "http://json-schema.org/draft-07/schema#",
3 "$id": "qmk.keyboard.v1", 3 "$id": "qmk.keyboard.v1",
4 "title": "Keyboard Information", 4 "title": "Keyboard Information",
5 "type": "object", 5 "type": "object",
6 "properties": { 6 "properties": {
7 "keyboard_name": { 7 "keyboard_name": {"$ref": "qmk.definitions.v1#/text_identifier"},
8 "type": "string", 8 "maintainer": {"$ref": "qmk.definitions.v1#/text_identifier"},
9 "minLength": 2, 9 "manufacturer": {"$ref": "qmk.definitions.v1#/text_identifier"},
10 "maxLength": 250
11 },
12 "maintainer": {
13 "type": "string",
14 "minLength": 2,
15 "maxLength": 250
16 },
17 "manufacturer": {
18 "type": "string",
19 "minLength": 2,
20 "maxLength": 250
21 },
22 "url": { 10 "url": {
23 "type": "string", 11 "type": "string",
24 "format": "uri" 12 "format": "uri"
@@ -40,62 +28,25 @@
40 "type": "string", 28 "type": "string",
41 "enum": ["COL2ROW", "ROW2COL"] 29 "enum": ["COL2ROW", "ROW2COL"]
42 }, 30 },
43 "debounce": { 31 "debounce": {"$ref": "qmk.definitions.v1#/unsigned_int"},
44 "type": "number", 32 "height": {"$ref": "qmk.definitions.v1#/key_unit"},
45 "min": 0, 33 "width": {"$ref": "qmk.definitions.v1#/key_unit"},
46 "multipleOf": 1
47 },
48 "height": {
49 "type": "number",
50 "min": 0.25
51 },
52 "width": {
53 "type": "number",
54 "min": 0.25
55 },
56 "community_layouts": { 34 "community_layouts": {
57 "type": "array", 35 "type": "array",
58 "items": { 36 "items": {"$ref": "qmk.definitions.v1#/filename"}
59 "type": "string",
60 "minLength": 2,
61 "pattern": "^[0-9a-z_]*$"
62 }
63 },
64 "features": {
65 "type": "object",
66 "additionalProperties": {"type": "boolean"}
67 }, 37 },
38 "features": {"$ref": "qmk.definitions.v1#/boolean_array"},
68 "indicators": { 39 "indicators": {
69 "type": "object", 40 "type": "object",
70 "properties": { 41 "properties": {
71 "caps_lock": { 42 "caps_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"},
72 "type": "string", 43 "num_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"},
73 "pattern": "^[A-K]\\d{1,2}$" 44 "scroll_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"}
74 },
75 "num_lock": {
76 "type": "string",
77 "pattern": "^[A-K]\\d{1,2}$"
78 },
79 "scroll_lock": {
80 "type": "string",
81 "pattern": "^[A-K]\\d{1,2}$"
82 }
83 } 45 }
84 }, 46 },
85 "layout_aliases": { 47 "layout_aliases": {
86 "type": "object", 48 "type": "object",
87 "additionalProperties": { 49 "additionalProperties": {"$ref": "qmk.definitions.v1#/layout_macro"}
88 "oneOf": [
89 {
90 "type": "string",
91 "enum": ["LAYOUT", "LAYOUT_planck_1x2uC"]
92 },
93 {
94 "type": "string",
95 "pattern": "^LAYOUT_[0-9a-z_]*$"
96 }
97 ]
98 }
99 }, 50 },
100 "layouts": { 51 "layouts": {
101 "type": "object", 52 "type": "object",
@@ -109,11 +60,7 @@
109 "c_macro": { 60 "c_macro": {
110 "type": "boolean" 61 "type": "boolean"
111 }, 62 },
112 "key_count": { 63 "key_count": {"$ref": "qmk.definitions.v1#/key_unit"},
113 "type": "number",
114 "min": 0,
115 "multipleOf": 1
116 },
117 "layout": { 64 "layout": {
118 "type": "array", 65 "type": "array",
119 "items": { 66 "items": {
@@ -131,34 +78,14 @@
131 "multipleOf": 1 78 "multipleOf": 1
132 } 79 }
133 }, 80 },
134 "h": { 81 "key_count": {"$ref": "qmk.definitions.v1#/key_unit"},
135 "type": "number", 82 "r": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
136 "min": 0.25 83 "rx": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
137 }, 84 "ry": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
138 "r": { 85 "h": {"$ref": "qmk.definitions.v1#/key_unit"},
139 "type": "number", 86 "w": {"$ref": "qmk.definitions.v1#/key_unit"},
140 "min": 0 87 "x": {"$ref": "qmk.definitions.v1#/key_unit"},
141 }, 88 "y": {"$ref": "qmk.definitions.v1#/key_unit"}
142 "rx": {
143 "type": "number",
144 "min": 0
145 },
146 "ry": {
147 "type": "number",
148 "min": 0
149 },
150 "w": {
151 "type": "number",
152 "min": 0.25
153 },
154 "x": {
155 "type": "number",
156 "min": 0
157 },
158 "y": {
159 "type": "number",
160 "min": 0
161 }
162 } 89 }
163 } 90 }
164 } 91 }
@@ -171,61 +98,10 @@
171 "properties": { 98 "properties": {
172 "direct": { 99 "direct": {
173 "type": "array", 100 "type": "array",
174 "items": { 101 "items": {$ref": "qmk.definitions.v1#/mcu_pin_array"}
175 "type": "array",
176 "items": {
177 "oneOf": [
178 {
179 "type": "string",
180 "pattern": "^[A-K]\\d{1,2}$"
181 },
182 {
183 "type": "number",
184 "multipleOf": 1
185 },
186 {
187 "type": "null"
188 }
189 ]
190 }
191 }
192 },
193 "cols": {
194 "type": "array",
195 "items": {
196 "oneOf": [
197 {
198 "type": "string",
199 "pattern": "^[A-K]\\d{1,2}$"
200 },
201 {
202 "type": "number",
203 "multipleOf": 1
204 },
205 {
206 "type": "null"
207 }
208 ]
209 }
210 }, 102 },
211 "rows": { 103 "cols": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
212 "type": "array", 104 "rows": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}
213 "items": {
214 "oneOf": [
215 {
216 "type": "string",
217 "pattern": "^[A-K]\\d{1,2}$"
218 },
219 {
220 "type": "number",
221 "multipleOf": 1
222 },
223 {
224 "type": "null"
225 }
226 ]
227 }
228 }
229 } 105 }
230 }, 106 },
231 "rgblight": { 107 "rgblight": {
@@ -238,47 +114,19 @@
238 "type": "boolean" 114 "type": "boolean"
239 } 115 }
240 }, 116 },
241 "brightness_steps": { 117 "brightness_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
242 "type": "number", 118 "hue_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
243 "min": 0, 119 "led_count": {"$ref": "qmk.definitions.v1#/unsigned_int"},
244 "multipleOf": 1 120 "max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
245 }, 121 "pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
246 "hue_steps": { 122 "saturation_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
247 "type": "number",
248 "min": 0,
249 "multipleOf": 1
250 },
251 "led_count": {
252 "type": "number",
253 "min": 0,
254 "multipleOf": 1
255 },
256 "max_brightness": {
257 "type": "number",
258 "min": 0,
259 "max": 255,
260 "multipleOf": 1
261 },
262 "pin": {
263 "type": "string",
264 "pattern": "^[A-K]\\d{1,2}$"
265 },
266 "saturation_steps": {
267 "type": "number",
268 "min": 0,
269 "multipleOf": 1
270 },
271 "sleep": {"type": "boolean"}, 123 "sleep": {"type": "boolean"},
272 "split": {"type": "boolean"}, 124 "split": {"type": "boolean"},
273 "split_count": { 125 "split_count": {
274 "type": "array", 126 "type": "array",
275 "minLength": 2, 127 "minLength": 2,
276 "maxLength": 2, 128 "maxLength": 2,
277 "items": { 129 "items": {"$ref": "qmk.definitions.v1#/unsigned_int"}
278 "type": "number",
279 "min": 0,
280 "multipleOf": 1
281 }
282 } 130 }
283 } 131 }
284 }, 132 },
@@ -286,40 +134,19 @@
286 "type": "object", 134 "type": "object",
287 "additionalProperties": false, 135 "additionalProperties": false,
288 "properties": { 136 "properties": {
289 "device_ver": { 137 "device_ver": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
290 "type": "string", 138 "pid": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
291 "pattern": "^[0-9A-F]x[0-9A-F][0-9A-F][0-9A-F][0-9A-F]" 139 "vid": {"$ref": "qmk.definitions.v1#/hex_number_4d"}
292 },
293 "pid": {
294 "type": "string",
295 "pattern": "^[0-9A-F]x[0-9A-F][0-9A-F][0-9A-F][0-9A-F]"
296 },
297 "vid": {
298 "type": "string",
299 "pattern": "^[0-9A-F]x[0-9A-F][0-9A-F][0-9A-F][0-9A-F]"
300 }
301 } 140 }
302 }, 141 },
303 "qmk_lufa_bootloader": { 142 "qmk_lufa_bootloader": {
304 "type": "object", 143 "type": "object",
305 "additionalProperties": false, 144 "additionalProperties": false,
306 "properties": { 145 "properties": {
307 "esc_output": { 146 "esc_output": {"$ref": "qmk.definitions.v1#/mcu_pin"},
308 "type": "string", 147 "esc_input": {"$ref": "qmk.definitions.v1#/mcu_pin"},
309 "pattern": "^[A-K]\\d{1,2}$" 148 "led": {"$ref": "qmk.definitions.v1#/mcu_pin"},
310 }, 149 "speaker": {"$ref": "qmk.definitions.v1#/mcu_pin"}
311 "esc_input": {
312 "type": "string",
313 "pattern": "^[A-K]\\d{1,2}$"
314 },
315 "led": {
316 "type": "string",
317 "pattern": "^[A-K]\\d{1,2}$"
318 },
319 "speaker": {
320 "type": "string",
321 "pattern": "^[A-K]\\d{1,2}$"
322 }
323 } 150 }
324 } 151 }
325 } 152 }
diff --git a/docs/_summary.md b/docs/_summary.md
index 9798ef512..4141e01e7 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -93,6 +93,7 @@
93 * Hardware Features 93 * Hardware Features
94 * Displays 94 * Displays
95 * [HD44780 LCD Controller](feature_hd44780.md) 95 * [HD44780 LCD Controller](feature_hd44780.md)
96 * [ST7565 LCD Driver](feature_st7565.md)
96 * [OLED Driver](feature_oled_driver.md) 97 * [OLED Driver](feature_oled_driver.md)
97 * Lighting 98 * Lighting
98 * [Backlight](feature_backlight.md) 99 * [Backlight](feature_backlight.md)
diff --git a/docs/breaking_changes.md b/docs/breaking_changes.md
index b0d56a81b..a1a56bd45 100644
--- a/docs/breaking_changes.md
+++ b/docs/breaking_changes.md
@@ -100,3 +100,7 @@ This happens immediately after the previous `develop` branch is merged.
100 * [ ] `git pull --ff-only` 100 * [ ] `git pull --ff-only`
101 * [ ] `git merge --no-ff develop` 101 * [ ] `git merge --no-ff develop`
102 * [ ] `git push upstream master` 102 * [ ] `git push upstream master`
103
104## Post-merge operations
105
106* (Optional) [update ChibiOS + ChibiOS-Contrib on `develop`](chibios_upgrade_instructions.md)
diff --git a/docs/chibios_upgrade_instructions.md b/docs/chibios_upgrade_instructions.md
new file mode 100644
index 000000000..40c2faafc
--- /dev/null
+++ b/docs/chibios_upgrade_instructions.md
@@ -0,0 +1,56 @@
1# ChibiOS Upgrade Procedure
2
3ChibiOS and ChibiOS-Contrib need to be updated in tandem -- the latter has a branch tied to the ChibiOS version in use and should not be mixed with different versions.
4
5## Getting ChibiOS
6
7* `svn` Initialisation:
8 * Only needed to be done once
9 * You might need to separately install `git-svn` package in your OS's package manager
10 * `git svn init --stdlayout --prefix='svn/' http://svn.osdn.net/svnroot/chibios/`
11 * `git remote add qmk git@github.com:qmk/ChibiOS.git`
12* Updating:
13 * `git svn fetch`
14 * First time around this will take several hours
15 * Subsequent updates will be incremental only
16* Tagging example (work out which version first!):
17 * `git tag -a ver20.3.3 -m ver20.3.3 svn/tags/ver20.3.3`
18 * `git push qmk ver20.3.3`
19 * `git tag -a breaking_YYYY_qN -m breaking_YYYY_qN svn/tags/ver20.3.3`
20 * `git push qmk breaking_YYYY_qN`
21
22## Getting ChibiOS-Contrib
23
24* `git` Initialisation:
25 * `git clone git@github.com:qmk/ChibiOS-Contrib`
26 * `git remote add upstream https://github.com/ChibiOS/ChibiOS-Contrib`
27 * `git checkout -b chibios-20.3.x upstream/chibios-20.3.x`
28* Updating:
29 * `git fetch --all --tags --prune`
30 * `git checkout chibios-20.3.x`
31 * `git pull --ff-only`
32 * `git push origin chibios-20.3.x`
33 * `git tag -a breaking_YYYY_qN -m breaking_YYYY_qN chibios-20.3.x`
34 * `git push origin breaking_YYYY_qN`
35
36## Updating submodules
37
38* Update the submodules
39 * `cd $QMK_FIRMWARE`
40 * `git checkout develop`
41 * `git pull --ff-only`
42 * `git checkout -b chibios-version-bump`
43 * `cd lib/chibios`
44 * `git fetch --all --tags --prune`
45 * `git checkout breaking_YYYY_qN`
46 * `cd ../chibios-contrib`
47 * `git fetch --all --tags --prune`
48 * `git checkout breaking_YYYY_qN`
49* Build everything
50 * `cd $QMK_FIRMWARE`
51 * `qmk multibuild -j4`
52 * Make sure there are no errors
53* Push to the repo
54 * `git commit -am 'Update ChibiOS to XXXXXXXXX'`
55 * `git push --set-upstream origin chibios-version-bump`
56* Make a PR to qmk_firmware with the new branch \ No newline at end of file
diff --git a/docs/config_options.md b/docs/config_options.md
index d0f0b316e..980195ac6 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -51,8 +51,10 @@ This is a C header file that is one of the first things included, and will persi
51 * the number of columns in your keyboard's matrix 51 * the number of columns in your keyboard's matrix
52* `#define MATRIX_ROW_PINS { D0, D5, B5, B6 }` 52* `#define MATRIX_ROW_PINS { D0, D5, B5, B6 }`
53 * pins of the rows, from top to bottom 53 * pins of the rows, from top to bottom
54 * may be omitted by the keyboard designer if matrix reads are handled in an alternate manner. See [low-level matrix overrides](custom_quantum_functions.md?id=low-level-matrix-overrides) for more information.
54* `#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }` 55* `#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }`
55 * pins of the columns, from left to right 56 * pins of the columns, from left to right
57 * may be omitted by the keyboard designer if matrix reads are handled in an alternate manner. See [low-level matrix overrides](custom_quantum_functions.md?id=low-level-matrix-overrides) for more information.
56* `#define MATRIX_IO_DELAY 30` 58* `#define MATRIX_IO_DELAY 30`
57 * the delay in microseconds when between changing matrix pin state and reading values 59 * the delay in microseconds when between changing matrix pin state and reading values
58* `#define UNUSED_PINS { D1, D2, D3, B1, B2, B3 }` 60* `#define UNUSED_PINS { D1, D2, D3, B1, B2, B3 }`
@@ -272,7 +274,7 @@ There are a few different ways to set handedness for split keyboards (listed in
272### Other Options 274### Other Options
273 275
274* `#define USE_I2C` 276* `#define USE_I2C`
275 * For using I2C instead of Serial (defaults to serial) 277 * For using I2C instead of Serial (default is serial; serial transport is supported on ARM -- I2C is AVR-only)
276 278
277* `#define SOFT_SERIAL_PIN D0` 279* `#define SOFT_SERIAL_PIN D0`
278 * When using serial, define this. `D0` or `D1`,`D2`,`D3`,`E6`. 280 * When using serial, define this. `D0` or `D1`,`D2`,`D3`,`E6`.
@@ -280,6 +282,7 @@ There are a few different ways to set handedness for split keyboards (listed in
280* `#define MATRIX_ROW_PINS_RIGHT { <row pins> }` 282* `#define MATRIX_ROW_PINS_RIGHT { <row pins> }`
281* `#define MATRIX_COL_PINS_RIGHT { <col pins> }` 283* `#define MATRIX_COL_PINS_RIGHT { <col pins> }`
282 * If you want to specify a different pinout for the right half than the left half, you can define `MATRIX_ROW_PINS_RIGHT`/`MATRIX_COL_PINS_RIGHT`. Currently, the size of `MATRIX_ROW_PINS` must be the same as `MATRIX_ROW_PINS_RIGHT` and likewise for the definition of columns. 284 * If you want to specify a different pinout for the right half than the left half, you can define `MATRIX_ROW_PINS_RIGHT`/`MATRIX_COL_PINS_RIGHT`. Currently, the size of `MATRIX_ROW_PINS` must be the same as `MATRIX_ROW_PINS_RIGHT` and likewise for the definition of columns.
285 * may be omitted by the keyboard designer if matrix reads are handled in an alternate manner. See [low-level matrix overrides](custom_quantum_functions.md?id=low-level-matrix-overrides) for more information.
283 286
284* `#define DIRECT_PINS_RIGHT { { F1, F0, B0, C7 }, { F4, F5, F6, F7 } }` 287* `#define DIRECT_PINS_RIGHT { { F1, F0, B0, C7 }, { F4, F5, F6, F7 } }`
285 * If you want to specify a different direct pinout for the right half than the left half, you can define `DIRECT_PINS_RIGHT`. Currently, the size of `DIRECT_PINS` must be the same as `DIRECT_PINS_RIGHT`. 288 * If you want to specify a different direct pinout for the right half than the left half, you can define `DIRECT_PINS_RIGHT`. Currently, the size of `DIRECT_PINS` must be the same as `DIRECT_PINS_RIGHT`.
@@ -300,7 +303,7 @@ There are a few different ways to set handedness for split keyboards (listed in
300* `#define SPLIT_USB_DETECT` 303* `#define SPLIT_USB_DETECT`
301 * Detect (with timeout) USB connection when delegating master/slave 304 * Detect (with timeout) USB connection when delegating master/slave
302 * Default behavior for ARM 305 * Default behavior for ARM
303 * Required for AVR Teensy 306 * Required for AVR Teensy (without hardware mods)
304 307
305* `#define SPLIT_USB_TIMEOUT 2000` 308* `#define SPLIT_USB_TIMEOUT 2000`
306 * Maximum timeout when detecting master/slave when using `SPLIT_USB_DETECT` 309 * Maximum timeout when detecting master/slave when using `SPLIT_USB_DETECT`
@@ -308,6 +311,28 @@ There are a few different ways to set handedness for split keyboards (listed in
308* `#define SPLIT_USB_TIMEOUT_POLL 10` 311* `#define SPLIT_USB_TIMEOUT_POLL 10`
309 * Poll frequency when detecting master/slave when using `SPLIT_USB_DETECT` 312 * Poll frequency when detecting master/slave when using `SPLIT_USB_DETECT`
310 313
314* `#define FORCED_SYNC_THROTTLE_MS 100`
315 * Deadline for synchronizing data from master to slave when using the QMK-provided split transport.
316
317* `#define SPLIT_TRANSPORT_MIRROR`
318 * Mirrors the master-side matrix on the slave when using the QMK-provided split transport.
319
320* `#define SPLIT_LAYER_STATE_ENABLE`
321 * Ensures the current layer state is available on the slave when using the QMK-provided split transport.
322
323* `#define SPLIT_LED_STATE_ENABLE`
324 * Ensures the current host indicator state (caps/num/scroll) is available on the slave when using the QMK-provided split transport.
325
326* `#define SPLIT_MODS_ENABLE`
327 * Ensures the current modifier state (normal, weak, and oneshot) is available on the slave when using the QMK-provided split transport.
328
329* `#define SPLIT_WPM_ENABLE`
330 * Ensures the current WPM is available on the slave when using the QMK-provided split transport.
331
332* `#define SPLIT_TRANSACTION_IDS_KB .....`
333* `#define SPLIT_TRANSACTION_IDS_USER .....`
334 * Allows for custom data sync with the slave when using the QMK-provided split transport. See [custom data sync between sides](feature_split_keyboard.md#custom-data-sync) for more information.
335
311# The `rules.mk` File 336# The `rules.mk` File
312 337
313This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features. 338This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features.
diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md
index 694b421e7..30c637bb4 100644
--- a/docs/custom_quantum_functions.md
+++ b/docs/custom_quantum_functions.md
@@ -144,6 +144,14 @@ This is useful for setting up stuff that you may need elsewhere, but isn't hardw
144* Keyboard/Revision: `void matrix_init_kb(void)` 144* Keyboard/Revision: `void matrix_init_kb(void)`
145* Keymap: `void matrix_init_user(void)` 145* Keymap: `void matrix_init_user(void)`
146 146
147### Low-level Matrix Overrides Function Documentation :id=low-level-matrix-overrides
148
149* GPIO pin initialisation: `void matrix_init_pins(void)`
150 * This needs to perform the low-level initialisation of all row and column pins. By default this will initialise the input/output state of each of the GPIO pins listed in `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`, based on whether or not the keyboard is set up for `ROW2COL`, `COL2ROW`, or `DIRECT_PINS`. Should the keyboard designer override this function, no initialisation of pin state will occur within QMK itself, instead deferring to the keyboard's override.
151* `COL2ROW`-based row reads: `void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)`
152* `ROW2COL`-based column reads: `void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)`
153* `DIRECT_PINS`-based reads: `void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)`
154 * These three functions need to perform the low-level retrieval of matrix state of relevant input pins, based on the matrix type. Only one of the functions should be implemented, if needed. By default this will iterate through `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`, configuring the inputs and outputs based on whether or not the keyboard is set up for `ROW2COL`, `COL2ROW`, or `DIRECT_PINS`. Should the keyboard designer override this function, no manipulation of matrix GPIO pin state will occur within QMK itself, instead deferring to the keyboard's override.
147 155
148## Keyboard Post Initialization code 156## Keyboard Post Initialization code
149 157
diff --git a/docs/eeprom_driver.md b/docs/eeprom_driver.md
index e2c262546..6dcf10c04 100644
--- a/docs/eeprom_driver.md
+++ b/docs/eeprom_driver.md
@@ -31,6 +31,9 @@ Currently QMK supports 24xx-series chips over I2C. As such, requires a working i
31`#define EXTERNAL_EEPROM_PAGE_SIZE` | Page size of the EEPROM in bytes, as specified in the datasheet | 32 31`#define EXTERNAL_EEPROM_PAGE_SIZE` | Page size of the EEPROM in bytes, as specified in the datasheet | 32
32`#define EXTERNAL_EEPROM_ADDRESS_SIZE` | The number of bytes to transmit for the memory location within the EEPROM | 2 32`#define EXTERNAL_EEPROM_ADDRESS_SIZE` | The number of bytes to transmit for the memory location within the EEPROM | 2
33`#define EXTERNAL_EEPROM_WRITE_TIME` | Write cycle time of the EEPROM, as specified in the datasheet | 5 33`#define EXTERNAL_EEPROM_WRITE_TIME` | Write cycle time of the EEPROM, as specified in the datasheet | 5
34`#define EXTERNAL_EEPROM_WP_PIN` | If defined the WP pin will be toggled appropriately when writing to the EEPROM. | _none_
35
36Some I2C EEPROM manufacturers explicitly recommend against hardcoding the WP pin to ground. This is in order to protect the eeprom memory content during power-up/power-down/brown-out conditions at low voltage where the eeprom is still operational, but the i2c master output might be unpredictable. If a WP pin is configured, then having an external pull-up on the WP pin is recommended.
34 37
35Default values and extended descriptions can be found in `drivers/eeprom/eeprom_i2c.h`. 38Default values and extended descriptions can be found in `drivers/eeprom/eeprom_i2c.h`.
36 39
diff --git a/docs/feature_debounce_type.md b/docs/feature_debounce_type.md
index 3ad74224c..306185fe8 100644
--- a/docs/feature_debounce_type.md
+++ b/docs/feature_debounce_type.md
@@ -121,16 +121,16 @@ DEBOUNCE_TYPE = <name of algorithm>
121Where name of algorithm is one of: 121Where name of algorithm is one of:
122* ```sym_defer_g``` - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE``` milliseconds of no changes has occurred, all input changes are pushed. 122* ```sym_defer_g``` - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE``` milliseconds of no changes has occurred, all input changes are pushed.
123 * This is the current default algorithm. This is the highest performance algorithm with lowest memory usage, and it's also noise-resistant. 123 * This is the current default algorithm. This is the highest performance algorithm with lowest memory usage, and it's also noise-resistant.
124* ```sym_eager_pr``` - debouncing per row. On any state change, response is immediate, followed by locking the row ```DEBOUNCE``` milliseconds of no further input for that row. 124* ```sym_eager_pr``` - debouncing per row. On any state change, response is immediate, followed by locking the row ```DEBOUNCE``` milliseconds of no further input for that row.
125For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be 125For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be
126appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use. 126appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use.
127* ```sym_eager_pk``` - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key 127* ```sym_eager_pk``` - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key
128* ```sym_defer_pk``` - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key status change is pushed. 128* ```sym_defer_pk``` - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key status change is pushed.
129* ```asym_eager_defer_pk``` - debouncing per key. On a key-down state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key. On a key-up state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key-up status change is pushed.
129 130
130### A couple algorithms that could be implemented in the future: 131### A couple algorithms that could be implemented in the future:
131* ```sym_defer_pr``` 132* ```sym_defer_pr```
132* ```sym_eager_g``` 133* ```sym_eager_g```
133* ```asym_eager_defer_pk```
134 134
135### Use your own debouncing code 135### Use your own debouncing code
136You have the option to implement you own debouncing algorithm. To do this: 136You have the option to implement you own debouncing algorithm. To do this:
diff --git a/docs/feature_haptic_feedback.md b/docs/feature_haptic_feedback.md
index a092e784c..469c9c798 100644
--- a/docs/feature_haptic_feedback.md
+++ b/docs/feature_haptic_feedback.md
@@ -162,4 +162,28 @@ This will set what sequence HPT_RST will set as the active mode. If not defined,
162 162
163### DRV2605L Continuous Haptic Mode 163### DRV2605L Continuous Haptic Mode
164 164
165This mode sets continuous haptic feedback with the option to increase or decrease strength. 165This mode sets continuous haptic feedback with the option to increase or decrease strength.
166
167## Haptic Key Exclusion
168The Haptic Exclusion is implemented as `__attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record)` in haptic.c. This allows a re-definition at the required level with the specific requirement / exclusion.
169
170### NO_HAPTIC_MOD
171With the entry of `#define NO_HAPTIC_MOD` in config.h, modifiers from Left Control to Right GUI will not trigger a feedback. This also includes modifiers in a Mod Tap configuration.
172
173### NO_HAPTIC_FN
174With the entry of `#define NO_HAPTIC_FN` in config.h, layer keys will not rigger a feedback.
175
176### NO_HAPTIC_ALPHA
177With the entry of `#define NO_HAPTIC_ALPHA` in config.h, none of the alpha keys (A ... Z) will trigger a feedback.
178
179### NO_HAPTIC_PUNCTUATION
180With the entry of `#define NO_HAPTIC_PUNCTUATION` in config.h, none of the following keys will trigger a feedback: Enter, ESC, Backspace, Space, Minus, Equal, Left Bracket, Right Bracket, Backslash, Non-US Hash, Semicolon, Quote, Grave, Comma, Slash, Dot, Non-US Backslash.
181
182### NO_HAPTIC_LOCKKEYS
183With the entry of `#define NO_HAPTIC_LOCKKEYS` in config.h, none of the following keys will trigger a feedback: Caps Lock, Scroll Lock, Num Lock.
184
185### NO_HAPTIC_NAV
186With the entry of `#define NO_HAPTIC_NAV` in config.h, none of the following keys will trigger a feedback: Print Screen, Pause, Insert, Delete, Page Down, Page Up, Left Arrow, Up Arrow, Right Arrow, Down Arrow, End, Home.
187
188### NO_HAPTIC_NUMERIC
189With the entry of `#define NO_HAPTIC_NUMERIC` in config.h, none of the following keys between 0 and 9 (KC_1 ... KC_0) will trigger a feedback. \ No newline at end of file
diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md
index f3b659b1b..c90aabb9c 100644
--- a/docs/feature_oled_driver.md
+++ b/docs/feature_oled_driver.md
@@ -346,6 +346,10 @@ bool oled_scroll_left(void);
346// Returns true if the screen was not scrolling or stops scrolling 346// Returns true if the screen was not scrolling or stops scrolling
347bool oled_scroll_off(void); 347bool oled_scroll_off(void);
348 348
349// Inverts the display
350// Returns true if the screen was or is inverted
351bool oled_invert(bool invert);
352
349// Returns the maximum number of characters that will fit on a line 353// Returns the maximum number of characters that will fit on a line
350uint8_t oled_max_chars(void); 354uint8_t oled_max_chars(void);
351 355
diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md
index bfb3688b6..925c9de6e 100644
--- a/docs/feature_rgb_matrix.md
+++ b/docs/feature_rgb_matrix.md
@@ -228,6 +228,75 @@ Configure the hardware via your `config.h`:
228``` 228```
229 229
230--- 230---
231### AW20216 :id=aw20216
232There is basic support for addressable RGB matrix lighting with the SPI AW20216 RGB controller. To enable it, add this to your `rules.mk`:
233
234```makefile
235RGB_MATRIX_ENABLE = yes
236RGB_MATRIX_DRIVER = AW20216
237```
238
239You can use up to 2 AW20216 IC's. Do not specify `DRIVER_<N>_xxx` defines for IC's that are not present on your keyboard. You can define the following items in `config.h`:
240
241| Variable | Description | Default |
242|----------|-------------|---------|
243| `DRIVER_1_CS` | (Required) MCU pin connected to first RGB driver chip select line | B13 |
244| `DRIVER_2_CS` | (Optional) MCU pin connected to second RGB driver chip select line | |
245| `DRIVER_1_EN` | (Required) MCU pin connected to first RGB driver hardware enable line | C13 |
246| `DRIVER_2_EN` | (Optional) MCU pin connected to second RGB driver hardware enable line | |
247| `DRIVER_1_LED_TOTAL` | (Required) How many RGB lights are connected to first RGB driver | |
248| `DRIVER_2_LED_TOTAL` | (Optional) How many RGB lights are connected to second RGB driver | |
249| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
250| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
251| `AW_SCALING_MAX` | (Optional) LED current scaling value (0-255, higher values mean LED is brighter at full PWM) | 150 |
252| `AW_GLOBAL_CURRENT_MAX` | (Optional) Driver global current limit (0-255, higher values means the driver may consume more power) | 150 |
253| `AW_SPI_DIVISOR` | (Optional) Clock divisor for SPI communication (powers of 2, smaller numbers means faster communication, should not be less than 4) | 4 |
254
255Here is an example using 2 drivers.
256
257```c
258#define DRIVER_1_CS B13
259#define DRIVER_2_CS B14
260// Hardware enable lines may be connected to the same pin
261#define DRIVER_1_EN C13
262#define DRIVER_2_EN C13
263
264#define DRIVER_COUNT 2
265#define DRIVER_1_LED_TOTAL 66
266#define DRIVER_2_LED_TOTAL 32
267#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
268```
269
270!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
271
272Define these arrays listing all the LEDs in your `<keyboard>.c`:
273
274```c
275const aw_led g_aw_leds[DRIVER_LED_TOTAL] = {
276/* Each AW20216 channel is controlled by a register at some offset between 0x00
277 * and 0xD7 inclusive.
278 * See drivers/awinic/aw20216.h for the mapping between register offsets and
279 * driver pin locations.
280 * driver
281 * | R location
282 * | | G location
283 * | | | B location
284 * | | | | */
285 { 0, CS1_SW1, CS2_SW1, CS3_SW1 },
286 { 0, CS4_SW1, CS5_SW1, CS6_SW1 },
287 { 0, CS7_SW1, CS8_SW1, CS9_SW1 },
288 { 0, CS10_SW1, CS11_SW1, CS12_SW1 },
289 { 0, CS13_SW1, CS14_SW1, CS15_SW1 },
290 ...
291 { 1, CS1_SW1, CS2_SW1, CS3_SW1 },
292 { 1, CS13_SW1, CS14_SW1, CS15_SW1 },
293 { 1, CS16_SW1, CS17_SW1, CS18_SW1 },
294 { 1, CS4_SW2, CS5_SW2, CS6_SW2 },
295 ...
296};
297```
298
299---
231 300
232## Common Configuration :id=common-configuration 301## Common Configuration :id=common-configuration
233 302
diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md
index 4ebf585f5..603c387c2 100644
--- a/docs/feature_split_keyboard.md
+++ b/docs/feature_split_keyboard.md
@@ -8,8 +8,7 @@ QMK Firmware has a generic implementation that is usable by any board, as well a
8 8
9For this, we will mostly be talking about the generic implementation used by the Let's Split and other keyboards. 9For this, we will mostly be talking about the generic implementation used by the Let's Split and other keyboards.
10 10
11!> ARM is not yet fully supported for Split Keyboards and has many limitations. Progress is being made, but we have not yet reached 100% feature parity. 11!> ARM split supports most QMK subsystems when using the 'serial' and 'serial_usart' drivers. I2C slave is currently unsupported.
12
13 12
14## Compatibility Overview 13## Compatibility Overview
15 14
@@ -169,7 +168,7 @@ Because not every split keyboard is identical, there are a number of additional
169#define USE_I2C 168#define USE_I2C
170``` 169```
171 170
172This enables I<sup>2</sup>C support for split keyboards. This isn't strictly for communication, but can be used for OLED or other I<sup>2</sup>C-based devices. 171This configures the use of I<sup>2</sup>C support for split keyboard transport (AVR only).
173 172
174```c 173```c
175#define SOFT_SERIAL_PIN D0 174#define SOFT_SERIAL_PIN D0
@@ -193,20 +192,115 @@ If you're having issues with serial communication, you can change this value, as
193* **`5`**: about 20kbps 192* **`5`**: about 20kbps
194 193
195```c 194```c
196#define SPLIT_MODS_ENABLE 195#define FORCED_SYNC_THROTTLE_MS 100
197``` 196```
198 197
199This enables transmitting modifier state (normal, weak and oneshot) to the non 198This sets the maximum number of milliseconds before forcing a synchronization of data from master to slave. Under normal circumstances this sync occurs whenever the data _changes_, for safety a data transfer occurs after this number of milliseconds if no change has been detected since the last sync.
200primary side of the split keyboard. This adds a few bytes of data to the split
201communication protocol and may impact the matrix scan speed when enabled.
202The purpose of this feature is to support cosmetic use of modifer state (e.g.
203displaying status on an OLED screen).
204 199
205```c 200```c
206#define SPLIT_TRANSPORT_MIRROR 201#define SPLIT_TRANSPORT_MIRROR
207``` 202```
208 203
209This mirrors the master side matrix to the slave side for features that react or require knowledge of master side key presses on the slave side. This adds a few bytes of data to the split communication protocol and may impact the matrix scan speed when enabled. The purpose of this feature is to support cosmetic use of key events (e.g. RGB reacting to Keypresses). 204This mirrors the master side matrix to the slave side for features that react or require knowledge of master side key presses on the slave side. The purpose of this feature is to support cosmetic use of key events (e.g. RGB reacting to keypresses). This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
205
206```c
207#define SPLIT_LAYER_STATE_ENABLE
208```
209
210This enables syncing of the layer state between both halves of the split keyboard. The main purpose of this feature is to enable support for use of things like OLED display of the currently active layer. This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
211
212```c
213#define SPLIT_LED_STATE_ENABLE
214```
215
216This enables syncing of the Host LED status (caps lock, num lock, etc) between both halves of the split keyboard. The main purpose of this feature is to enable support for use of things like OLED display of the Host LED status. This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
217
218```c
219#define SPLIT_MODS_ENABLE
220```
221
222This enables transmitting modifier state (normal, weak and oneshot) to the non primary side of the split keyboard. The purpose of this feature is to support cosmetic use of modifer state (e.g. displaying status on an OLED screen). This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
223
224```c
225#define SPLIT_WPM_ENABLE
226```
227
228This enables transmitting the current WPM to the slave side of the split keyboard. The purpose of this feature is to support cosmetic use of WPM (e.g. displaying the current value on an OLED screen). This adds overhead to the split communication protocol and may negatively impact the matrix scan speed when enabled.
229
230### Custom data sync between sides :id=custom-data-sync
231
232QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master.
233
234To leverage this, a keyboard or user/keymap can define a comma-separated list of _transaction IDs_:
235
236```c
237// for keyboard-level data sync:
238#define SPLIT_TRANSACTION_IDS_KB KEYBOARD_SYNC_A, KEYBOARD_SYNC_B
239// or, for user:
240#define SPLIT_TRANSACTION_IDS_USER USER_SYNC_A, USER_SYNC_B, USER_SYNC_C
241```
242
243These _transaction IDs_ then need a slave-side handler function to be registered with the split transport, for example:
244
245```c
246typedef struct _master_to_slave_t {
247 int m2s_data;
248} master_to_slave_t;
249
250typedef struct _slave_to_master_t {
251 int s2m_data;
252} slave_to_master_t;
253
254void user_sync_a_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) {
255 const master_to_slave_t *m2s = (const master_to_slave_t*)in_data;
256 slave_to_master_t *s2m = (slave_to_master_t*)out_data;
257 s2m->s2m_data = m2s->m2s_data + 5; // whatever comes in, add 5 so it can be sent back
258}
259
260void keyboard_post_init_user(void) {
261 transaction_register_rpc(USER_SYNC_A, user_sync_a_slave_handler);
262}
263```
264
265The master side can then invoke the slave-side handler - for normal keyboard functionality to be minimally affected, any keyboard- or user-level code attempting to sync data should be throttled:
266
267```c
268void housekeeping_task_user(void) {
269 if (is_keyboard_master()) {
270 // Interact with slave every 500ms
271 static uint32_t last_sync = 0;
272 if (timer_elapsed32(last_sync) > 500) {
273 master_to_slave_t m2s = {6};
274 slave_to_master_t s2m = {0};
275 if(transaction_rpc_exec(USER_SYNC_A, sizeof(m2s), &m2s, sizeof(s2m), &s2m)) {
276 last_sync = timer_read32();
277 dprintf("Slave value: %d\n", s2m.s2m_data); // this will now be 11, as the slave adds 5
278 } else {
279 dprint("Slave sync failed!\n");
280 }
281 }
282 }
283}
284```
285
286!> It is recommended that any data sync between halves happens during the master side's _housekeeping task_. This ensures timely retries should failures occur.
287
288If only one-way data transfer is needed, helper methods are provided:
289
290```c
291bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
292bool transaction_rpc_send(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer);
293bool transaction_rpc_recv(int8_t transaction_id, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
294```
295
296By default, the inbound and outbound data is limited to a maximum of 32 bytes each. The sizes can be altered if required:
297
298```c
299// Master to slave:
300#define RPC_M2S_BUFFER_SIZE 48
301// Slave to master:
302#define RPC_S2M_BUFFER_SIZE 48
303```
210 304
211### Hardware Configuration Options 305### Hardware Configuration Options
212 306
diff --git a/docs/feature_st7565.md b/docs/feature_st7565.md
new file mode 100644
index 000000000..de3e44d8e
--- /dev/null
+++ b/docs/feature_st7565.md
@@ -0,0 +1,274 @@
1# ST7565 LCD Driver
2
3## Supported Hardware
4
5LCD modules using ST7565 driver IC, communicating over SPI.
6
7|Module |IC |Size |Notes |
8|------------------------------|-------|------|----------------------------------------------------------|
9|Newhaven Display NHD-C12832A1Z|ST7565R|128x32|Used by Ergodox Infinity; primary consumer of this feature|
10|Zolentech ZLE12864B |ST7565P|128x64|Requires contrast adjustment |
11
12## Usage
13
14To enable the feature, there are three steps. First, when compiling your keyboard, you'll need to add the following to your `rules.mk`:
15
16```make
17ST7565_ENABLE = yes
18```
19
20Then in your `keymap.c` file, implement the ST7565 task call. This example assumes your keymap has three layers named `_QWERTY`, `_FN` and `_ADJ`:
21
22```c
23#ifdef ST7565_ENABLE
24void st7565_task_user(void) {
25 // Host Keyboard Layer Status
26 st7565_write_P(PSTR("Layer: "), false);
27
28 switch (get_highest_layer(layer_state)) {
29 case _QWERTY:
30 st7565_write_P(PSTR("Default\n"), false);
31 break;
32 case _FN:
33 st7565_write_P(PSTR("FN\n"), false);
34 break;
35 case _ADJ:
36 st7565_write_P(PSTR("ADJ\n"), false);
37 break;
38 default:
39 // Or use the write_ln shortcut over adding '\n' to the end of your string
40 st7565_write_ln_P(PSTR("Undefined"), false);
41 }
42
43 // Host Keyboard LED Status
44 led_t led_state = host_keyboard_led_state();
45 st7565_write_P(led_state.num_lock ? PSTR("NUM ") : PSTR(" "), false);
46 st7565_write_P(led_state.caps_lock ? PSTR("CAP ") : PSTR(" "), false);
47 st7565_write_P(led_state.scroll_lock ? PSTR("SCR ") : PSTR(" "), false);
48}
49#endif
50```
51
52## Logo Example
53
54In the default font, certain ranges of characters are reserved for a QMK logo. To render this logo to the screen, use the following code example:
55
56```c
57static void render_logo(void) {
58 static const char PROGMEM qmk_logo[] = {
59 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94,
60 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4,
61 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00
62 };
63
64 st7565_write_P(qmk_logo, false);
65}
66```
67
68## Buffer Read Example
69For some purposes, you may need to read the current state of the display buffer. The `st7565_read_raw` function can be used to safely read bytes from the buffer.
70
71In this example, calling `fade_display` in the `st7565_task_user` function will slowly fade away whatever is on the screen by turning random pixels off over time.
72```c
73//Setup some mask which can be or'd with bytes to turn off pixels
74const uint8_t single_bit_masks[8] = {127, 191, 223, 239, 247, 251, 253, 254};
75
76static void fade_display(void) {
77 //Define the reader structure
78 display_buffer_reader_t reader;
79 uint8_t buff_char;
80 if (random() % 30 == 0) {
81 srand(timer_read());
82 // Fetch a pointer for the buffer byte at index 0. The return structure
83 // will have the pointer and the number of bytes remaining from this
84 // index position if we want to perform a sequential read by
85 // incrementing the buffer pointer
86 reader = st7565_read_raw(0);
87 //Loop over the remaining buffer and erase pixels as we go
88 for (uint16_t i = 0; i < reader.remaining_element_count; i++) {
89 //Get the actual byte in the buffer by dereferencing the pointer
90 buff_char = *reader.current_element;
91 if (buff_char != 0) {
92 st7565_write_raw_byte(buff_char & single_bit_masks[rand() % 8], i);
93 }
94 //increment the pointer to fetch a new byte during the next loop
95 reader.current_element++;
96 }
97 }
98}
99```
100
101## Other Examples
102
103In split keyboards, it is very common to have two displays that each render different content and are oriented or flipped differently. You can do this by switching which content to render by using the return value from `is_keyboard_master()` or `is_keyboard_left()` found in `split_util.h`, e.g:
104
105```c
106#ifdef ST7565_ENABLE
107display_rotation_t st7565_init_user(display_rotation_t rotation) {
108 if (!is_keyboard_master()) {
109 return DISPLAY_ROTATION_180; // flips the display 180 degrees if offhand
110 }
111
112 return rotation;
113}
114
115void st7565_task_user(void) {
116 if (is_keyboard_master()) {
117 render_status(); // Renders the current keyboard state (layer, lock, caps, scroll, etc)
118 } else {
119 render_logo(); // Renders a static logo
120 }
121}
122#endif
123```
124
125## Basic Configuration
126
127|Define |Default |Description |
128|------------------------|--------------|-----------------------------------------------------------------------------------------------------|
129|`ST7565_A0_PIN` |*Not defined* |(Required) The GPIO connected to the display's A0 (data/command) pin |
130|`ST7565_RST_PIN` |*Not defined* |(Required) The GPIO connected to the display's reset pin |
131|`ST7565_SS_PIN` |*Not defined* |(Required) The GPIO connected to the display's slave select pin |
132|`ST7565_SPI_CLK_DIVISOR`|`4` |The SPI clock divisor to use |
133|`ST7565_FONT_H` |`"glcdfont.c"`|The font code file to use for custom fonts |
134|`ST7565_FONT_START` |`0` |The starting character index for custom fonts |
135|`ST7565_FONT_END` |`223` |The ending character index for custom fonts |
136|`ST7565_FONT_WIDTH` |`6` |The font width |
137|`ST7565_FONT_HEIGHT` |`8` |The font height (untested) |
138|`ST7565_TIMEOUT` |`60000` |Turns off the screen after 60000ms of keyboard inactivity. Helps reduce burn-in. Set to 0 to disable.|
139|`ST7565_COLUMN_OFFSET` |`0` |Shift output to the right this many pixels. |
140|`ST7565_CONTRAST` |`32` |The default contrast level of the display, from 0 to 255. |
141|`ST7565_UPDATE_INTERVAL`|`0` |Set the time interval for updating the display in ms. This will improve the matrix scan rate. |
142
143## Custom sized displays
144
145The default display size for this feature is 128x32 and all necessary defines are precalculated with that in mind.
146
147|Define |Default |Description |
148|-----------------------|----------|-----------------------------------------------------------------------------------------------------------|
149|`ST7565_DISPLAY_WIDTH` |`128` |The width of the display. |
150|`ST7565_DISPLAY_HEIGHT`|`32` |The height of the display. |
151|`ST7565_MATRIX_SIZE` |`512` |The local buffer size to allocate.<br>`(ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH)`. |
152|`ST7565_BLOCK_TYPE` |`uint16_t`|The unsigned integer type to use for dirty rendering. |
153|`ST7565_BLOCK_COUNT` |`16` |The number of blocks the display is divided into for dirty rendering.<br>`(sizeof(ST7565_BLOCK_TYPE) * 8)`.|
154|`ST7565_BLOCK_SIZE` |`32` |The size of each block for dirty rendering<br>`(ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT)`. |
155
156## API
157
158```c
159// Rotation enum values are flags
160typedef enum {
161 DISPLAY_ROTATION_0,
162 DISPLAY_ROTATION_180
163} display_rotation_t;
164
165// Initialize the display, rotating the rendered output based on the define passed in.
166// Returns true if the was initialized successfully
167bool st7565_init(display_rotation_t rotation);
168
169// Called at the start of st7565_init, weak function overridable by the user
170// rotation - the value passed into st7565_init
171// Return new display_rotation_t if you want to override default rotation
172display_rotation_t st7565_init_user(display_rotation_t rotation);
173
174// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
175void st7565_clear(void);
176
177// Renders the dirty chunks of the buffer to display
178void st7565_render(void);
179
180// Moves cursor to character position indicated by column and line, wraps if out of bounds
181// Max column denoted by 'st7565_max_chars()' and max lines by 'st7565_max_lines()' functions
182void st7565_set_cursor(uint8_t col, uint8_t line);
183
184// Advances the cursor to the next page, writing ' ' if true
185// Wraps to the begining when out of bounds
186void st7565_advance_page(bool clearPageRemainder);
187
188// Moves the cursor forward 1 character length
189// Advance page if there is not enough room for the next character
190// Wraps to the begining when out of bounds
191void st7565_advance_char(void);
192
193// Writes a single character to the buffer at current cursor position
194// Advances the cursor while writing, inverts the pixels if true
195// Main handler that writes character data to the display buffer
196void st7565_write_char(const char data, bool invert);
197
198// Writes a string to the buffer at current cursor position
199// Advances the cursor while writing, inverts the pixels if true
200void st7565_write(const char *data, bool invert);
201
202// Writes a string to the buffer at current cursor position
203// Advances the cursor while writing, inverts the pixels if true
204// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
205void st7565_write_ln(const char *data, bool invert);
206
207// Pans the buffer to the right (or left by passing true) by moving contents of the buffer
208// Useful for moving the screen in preparation for new drawing
209void st7565_pan(bool left);
210
211// Returns a pointer to the requested start index in the buffer plus remaining
212// buffer length as struct
213display_buffer_reader_t st7565_read_raw(uint16_t start_index);
214
215// Writes a string to the buffer at current cursor position
216void st7565_write_raw(const char *data, uint16_t size);
217
218// Writes a single byte into the buffer at the specified index
219void st7565_write_raw_byte(const char data, uint16_t index);
220
221// Sets a specific pixel on or off
222// Coordinates start at top-left and go right and down for positive x and y
223void st7565_write_pixel(uint8_t x, uint8_t y, bool on);
224
225// Writes a PROGMEM string to the buffer at current cursor position
226// Advances the cursor while writing, inverts the pixels if true
227// Remapped to call 'void st7565_write(const char *data, bool invert);' on ARM
228void st7565_write_P(const char *data, bool invert);
229
230// Writes a PROGMEM string to the buffer at current cursor position
231// Advances the cursor while writing, inverts the pixels if true
232// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
233// Remapped to call 'void st7565_write_ln(const char *data, bool invert);' on ARM
234void st7565_write_ln_P(const char *data, bool invert);
235
236// Writes a PROGMEM string to the buffer at current cursor position
237void st7565_write_raw_P(const char *data, uint16_t size);
238
239// Can be used to manually turn on the screen if it is off
240// Returns true if the screen was on or turns on
241bool st7565_on(void);
242
243// Called when st7565_on() turns on the screen, weak function overridable by the user
244// Not called if the screen is already on
245void st7565_on_user(void);
246
247// Can be used to manually turn off the screen if it is on
248// Returns true if the screen was off or turns off
249bool st7565_off(void);
250
251// Called when st7565_off() turns off the screen, weak function overridable by the user
252// Not called if the screen is already off
253void st7565_off_user(void);
254
255// Returns true if the screen is currently on, false if it is
256// not
257bool st7565_is_on(void);
258
259// Basically it's st7565_render, but with timeout management and st7565_task_user calling!
260void st7565_task(void);
261
262// Called at the start of st7565_task, weak function overridable by the user
263void st7565_task_user(void);
264
265// Inverts the display
266// Returns true if the screen was or is inverted
267bool st7565_invert(bool invert);
268
269// Returns the maximum number of characters that will fit on a line
270uint8_t st7565_max_chars(void);
271
272// Returns the maximum number of lines that will fit on the display
273uint8_t st7565_max_lines(void);
274```
diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c
index b1e488529..2773e0077 100644
--- a/drivers/avr/i2c_master.c
+++ b/drivers/avr/i2c_master.c
@@ -28,8 +28,14 @@
28# define F_SCL 400000UL // SCL frequency 28# define F_SCL 400000UL // SCL frequency
29#endif 29#endif
30 30
31#ifndef I2C_START_RETRY_COUNT
32# define I2C_START_RETRY_COUNT 20
33#endif // I2C_START_RETRY_COUNT
34
31#define TWBR_val (((F_CPU / F_SCL) - 16) / 2) 35#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
32 36
37#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
38
33void i2c_init(void) { 39void i2c_init(void) {
34 TWSR = 0; /* no prescaler */ 40 TWSR = 0; /* no prescaler */
35 TWBR = (uint8_t)TWBR_val; 41 TWBR = (uint8_t)TWBR_val;
@@ -47,7 +53,7 @@ void i2c_init(void) {
47#endif 53#endif
48} 54}
49 55
50i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { 56static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
51 // reset TWI control register 57 // reset TWI control register
52 TWCR = 0; 58 TWCR = 0;
53 // transmit START condition 59 // transmit START condition
@@ -86,6 +92,17 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
86 return I2C_STATUS_SUCCESS; 92 return I2C_STATUS_SUCCESS;
87} 93}
88 94
95i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
96 // Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled.
97 uint16_t timeout_timer = timer_read();
98 uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries
99 i2c_status_t status;
100 do {
101 status = i2c_start_impl(address, time_slice);
102 } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) < timeout)));
103 return status;
104}
105
89i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { 106i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
90 // load data into data register 107 // load data into data register
91 TWDR = data; 108 TWDR = data;
diff --git a/drivers/avr/i2c_slave.c b/drivers/avr/i2c_slave.c
index 62a378165..2907f164c 100644
--- a/drivers/avr/i2c_slave.c
+++ b/drivers/avr/i2c_slave.c
@@ -17,6 +17,7 @@
17 * GitHub repository: https://github.com/g4lvanix/I2C-slave-lib 17 * GitHub repository: https://github.com/g4lvanix/I2C-slave-lib
18 */ 18 */
19 19
20#include <stddef.h>
20#include <avr/io.h> 21#include <avr/io.h>
21#include <util/twi.h> 22#include <util/twi.h>
22#include <avr/interrupt.h> 23#include <avr/interrupt.h>
@@ -24,6 +25,12 @@
24 25
25#include "i2c_slave.h" 26#include "i2c_slave.h"
26 27
28#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
29# include "transactions.h"
30
31static volatile bool is_callback_executor = false;
32#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
33
27volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; 34volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
28 35
29static volatile uint8_t buffer_address; 36static volatile uint8_t buffer_address;
@@ -48,11 +55,14 @@ ISR(TWI_vect) {
48 case TW_SR_SLA_ACK: 55 case TW_SR_SLA_ACK:
49 // The device is now a slave receiver 56 // The device is now a slave receiver
50 slave_has_register_set = false; 57 slave_has_register_set = false;
58#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
59 is_callback_executor = false;
60#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
51 break; 61 break;
52 62
53 case TW_SR_DATA_ACK: 63 case TW_SR_DATA_ACK:
54 // This device is a slave receiver and has received data 64 // This device is a slave receiver and has received data
55 // First byte is the location then the bytes will be writen in buffer with auto-incriment 65 // First byte is the location then the bytes will be writen in buffer with auto-increment
56 if (!slave_has_register_set) { 66 if (!slave_has_register_set) {
57 buffer_address = TWDR; 67 buffer_address = TWDR;
58 68
@@ -60,10 +70,25 @@ ISR(TWI_vect) {
60 ack = 0; 70 ack = 0;
61 buffer_address = 0; 71 buffer_address = 0;
62 } 72 }
63 slave_has_register_set = true; // address has been receaved now fill in buffer 73 slave_has_register_set = true; // address has been received now fill in buffer
74
75#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
76 // Work out if we're attempting to execute a callback
77 is_callback_executor = buffer_address == split_transaction_table[I2C_EXECUTE_CALLBACK].initiator2target_offset;
78#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
64 } else { 79 } else {
65 i2c_slave_reg[buffer_address] = TWDR; 80 i2c_slave_reg[buffer_address] = TWDR;
66 buffer_address++; 81 buffer_address++;
82
83#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
84 // If we're intending to execute a transaction callback, do so, as we've just received the transaction ID
85 if (is_callback_executor) {
86 split_transaction_desc_t *trans = &split_transaction_table[split_shmem->transaction_id];
87 if (trans->slave_callback) {
88 trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans));
89 }
90 }
91#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
67 } 92 }
68 break; 93 break;
69 94
diff --git a/drivers/avr/i2c_slave.h b/drivers/avr/i2c_slave.h
index 1cd0625ef..a8647c9da 100644
--- a/drivers/avr/i2c_slave.h
+++ b/drivers/avr/i2c_slave.h
@@ -22,7 +22,18 @@
22 22
23#pragma once 23#pragma once
24 24
25#define I2C_SLAVE_REG_COUNT 30 25#ifndef I2C_SLAVE_REG_COUNT
26
27# if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
28# include "transport.h"
29# define I2C_SLAVE_REG_COUNT sizeof(split_shared_memory_t)
30# else // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
31# define I2C_SLAVE_REG_COUNT 30
32# endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
33
34#endif // I2C_SLAVE_REG_COUNT
35
36_Static_assert(I2C_SLAVE_REG_COUNT < 256, "I2C target registers must be single byte");
26 37
27extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; 38extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
28 39
diff --git a/drivers/avr/serial.c b/drivers/avr/serial.c
index 3647bee0d..9a7345a53 100644
--- a/drivers/avr/serial.c
+++ b/drivers/avr/serial.c
@@ -224,15 +224,8 @@
224# define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2) 224# define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2)
225 225
226# define SLAVE_INT_WIDTH_US 1 226# define SLAVE_INT_WIDTH_US 1
227# ifndef SERIAL_USE_MULTI_TRANSACTION 227# define SLAVE_INT_ACK_WIDTH_UNIT 2
228# define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY 228# define SLAVE_INT_ACK_WIDTH 4
229# else
230# define SLAVE_INT_ACK_WIDTH_UNIT 2
231# define SLAVE_INT_ACK_WIDTH 4
232# endif
233
234static SSTD_t *Transaction_table = NULL;
235static uint8_t Transaction_table_size = 0;
236 229
237inline static void serial_delay(void) ALWAYS_INLINE; 230inline static void serial_delay(void) ALWAYS_INLINE;
238inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); } 231inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); }
@@ -259,16 +252,12 @@ inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); }
259inline static void serial_high(void) ALWAYS_INLINE; 252inline static void serial_high(void) ALWAYS_INLINE;
260inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } 253inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); }
261 254
262void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) { 255void soft_serial_initiator_init(void) {
263 Transaction_table = sstd_table;
264 Transaction_table_size = (uint8_t)sstd_table_size;
265 serial_output(); 256 serial_output();
266 serial_high(); 257 serial_high();
267} 258}
268 259
269void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) { 260void soft_serial_target_init(void) {
270 Transaction_table = sstd_table;
271 Transaction_table_size = (uint8_t)sstd_table_size;
272 serial_input_with_pullup(); 261 serial_input_with_pullup();
273 262
274 // Enable INT0-INT7 263 // Enable INT0-INT7
@@ -395,19 +384,14 @@ static inline uint8_t nibble_bits_count(uint8_t bits) {
395 384
396// interrupt handle to be used by the target device 385// interrupt handle to be used by the target device
397ISR(SERIAL_PIN_INTERRUPT) { 386ISR(SERIAL_PIN_INTERRUPT) {
398# ifndef SERIAL_USE_MULTI_TRANSACTION
399 serial_low();
400 serial_output();
401 SSTD_t *trans = Transaction_table;
402# else
403 // recive transaction table index 387 // recive transaction table index
404 uint8_t tid, bits; 388 uint8_t tid, bits;
405 uint8_t pecount = 0; 389 uint8_t pecount = 0;
406 sync_recv(); 390 sync_recv();
407 bits = serial_read_chunk(&pecount, 7); 391 bits = serial_read_chunk(&pecount, 8);
408 tid = bits >> 3; 392 tid = bits >> 3;
409 bits = (bits & 7) != nibble_bits_count(tid); 393 bits = (bits & 7) != (nibble_bits_count(tid) & 7);
410 if (bits || pecount > 0 || tid > Transaction_table_size) { 394 if (bits || pecount > 0 || tid > NUM_TOTAL_TRANSACTIONS) {
411 return; 395 return;
412 } 396 }
413 serial_delay_half1(); 397 serial_delay_half1();
@@ -415,18 +399,22 @@ ISR(SERIAL_PIN_INTERRUPT) {
415 serial_high(); // response step1 low->high 399 serial_high(); // response step1 low->high
416 serial_output(); 400 serial_output();
417 _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH); 401 _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH);
418 SSTD_t *trans = &Transaction_table[tid]; 402 split_transaction_desc_t *trans = &split_transaction_table[tid];
419 serial_low(); // response step2 ack high->low 403 serial_low(); // response step2 ack high->low
420# endif 404
405 // If the transaction has a callback, we can execute it now
406 if (trans->slave_callback) {
407 trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans));
408 }
421 409
422 // target send phase 410 // target send phase
423 if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size); 411 if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size);
424 // target switch to input 412 // target switch to input
425 change_sender2reciver(); 413 change_sender2reciver();
426 414
427 // target recive phase 415 // target recive phase
428 if (trans->initiator2target_buffer_size > 0) { 416 if (trans->initiator2target_buffer_size > 0) {
429 if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size)) { 417 if (serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) {
430 *trans->status = TRANSACTION_ACCEPTED; 418 *trans->status = TRANSACTION_ACCEPTED;
431 } else { 419 } else {
432 *trans->status = TRANSACTION_DATA_ERROR; 420 *trans->status = TRANSACTION_DATA_ERROR;
@@ -448,14 +436,12 @@ ISR(SERIAL_PIN_INTERRUPT) {
448// TRANSACTION_NO_RESPONSE 436// TRANSACTION_NO_RESPONSE
449// TRANSACTION_DATA_ERROR 437// TRANSACTION_DATA_ERROR
450// this code is very time dependent, so we need to disable interrupts 438// this code is very time dependent, so we need to disable interrupts
451# ifndef SERIAL_USE_MULTI_TRANSACTION
452int soft_serial_transaction(void) {
453 SSTD_t *trans = Transaction_table;
454# else
455int soft_serial_transaction(int sstd_index) { 439int soft_serial_transaction(int sstd_index) {
456 if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR; 440 if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR;
457 SSTD_t *trans = &Transaction_table[sstd_index]; 441 split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
458# endif 442
443 if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered
444
459 cli(); 445 cli();
460 446
461 // signal to the target that we want to start a transaction 447 // signal to the target that we want to start a transaction
@@ -463,27 +449,11 @@ int soft_serial_transaction(int sstd_index) {
463 serial_low(); 449 serial_low();
464 _delay_us(SLAVE_INT_WIDTH_US); 450 _delay_us(SLAVE_INT_WIDTH_US);
465 451
466# ifndef SERIAL_USE_MULTI_TRANSACTION
467 // wait for the target response
468 serial_input_with_pullup();
469 _delay_us(SLAVE_INT_RESPONSE_TIME);
470
471 // check if the target is present
472 if (serial_read_pin()) {
473 // target failed to pull the line low, assume not present
474 serial_output();
475 serial_high();
476 *trans->status = TRANSACTION_NO_RESPONSE;
477 sei();
478 return TRANSACTION_NO_RESPONSE;
479 }
480
481# else
482 // send transaction table index 452 // send transaction table index
483 int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index)); 453 int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index));
484 sync_send(); 454 sync_send();
485 _delay_sub_us(TID_SEND_ADJUST); 455 _delay_sub_us(TID_SEND_ADJUST);
486 serial_write_chunk(tid, 7); 456 serial_write_chunk(tid, 8);
487 serial_delay_half1(); 457 serial_delay_half1();
488 458
489 // wait for the target response (step1 low->high) 459 // wait for the target response (step1 low->high)
@@ -504,12 +474,11 @@ int soft_serial_transaction(int sstd_index) {
504 } 474 }
505 _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); 475 _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);
506 } 476 }
507# endif
508 477
509 // initiator recive phase 478 // initiator recive phase
510 // if the target is present syncronize with it 479 // if the target is present syncronize with it
511 if (trans->target2initiator_buffer_size > 0) { 480 if (trans->target2initiator_buffer_size > 0) {
512 if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size)) { 481 if (!serial_recive_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) {
513 serial_output(); 482 serial_output();
514 serial_high(); 483 serial_high();
515 *trans->status = TRANSACTION_DATA_ERROR; 484 *trans->status = TRANSACTION_DATA_ERROR;
@@ -523,7 +492,7 @@ int soft_serial_transaction(int sstd_index) {
523 492
524 // initiator send phase 493 // initiator send phase
525 if (trans->initiator2target_buffer_size > 0) { 494 if (trans->initiator2target_buffer_size > 0) {
526 serial_send_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size); 495 serial_send_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size);
527 } 496 }
528 497
529 // always, release the line when not in use 498 // always, release the line when not in use
@@ -534,9 +503,8 @@ int soft_serial_transaction(int sstd_index) {
534 return TRANSACTION_END; 503 return TRANSACTION_END;
535} 504}
536 505
537# ifdef SERIAL_USE_MULTI_TRANSACTION
538int soft_serial_get_and_clean_status(int sstd_index) { 506int soft_serial_get_and_clean_status(int sstd_index) {
539 SSTD_t *trans = &Transaction_table[sstd_index]; 507 split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
540 cli(); 508 cli();
541 int retval = *trans->status; 509 int retval = *trans->status;
542 *trans->status = 0; 510 *trans->status = 0;
@@ -544,8 +512,6 @@ int soft_serial_get_and_clean_status(int sstd_index) {
544 sei(); 512 sei();
545 return retval; 513 return retval;
546} 514}
547# endif
548
549#endif 515#endif
550 516
551// Helix serial.c history 517// Helix serial.c history
diff --git a/drivers/avr/serial.h b/drivers/avr/serial.h
deleted file mode 100644
index 53e66cf90..000000000
--- a/drivers/avr/serial.h
+++ /dev/null
@@ -1,62 +0,0 @@
1#pragma once
2
3#include <stdbool.h>
4
5// /////////////////////////////////////////////////////////////////
6// Need Soft Serial defines in config.h
7// /////////////////////////////////////////////////////////////////
8// ex.
9// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
10// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
11// // 1: about 137kbps (default)
12// // 2: about 75kbps
13// // 3: about 39kbps
14// // 4: about 26kbps
15// // 5: about 20kbps
16//
17// //// USE simple API (using signle-type transaction function)
18// /* nothing */
19// //// USE flexible API (using multi-type transaction function)
20// #define SERIAL_USE_MULTI_TRANSACTION
21//
22// /////////////////////////////////////////////////////////////////
23
24// Soft Serial Transaction Descriptor
25typedef struct _SSTD_t {
26 uint8_t *status;
27 uint8_t initiator2target_buffer_size;
28 uint8_t *initiator2target_buffer;
29 uint8_t target2initiator_buffer_size;
30 uint8_t *target2initiator_buffer;
31} SSTD_t;
32#define TID_LIMIT(table) (sizeof(table) / sizeof(SSTD_t))
33
34// initiator is transaction start side
35void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
36// target is interrupt accept side
37void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size);
38
39// initiator resullt
40#define TRANSACTION_END 0
41#define TRANSACTION_NO_RESPONSE 0x1
42#define TRANSACTION_DATA_ERROR 0x2
43#define TRANSACTION_TYPE_ERROR 0x4
44#ifndef SERIAL_USE_MULTI_TRANSACTION
45int soft_serial_transaction(void);
46#else
47int soft_serial_transaction(int sstd_index);
48#endif
49
50// target status
51// *SSTD_t.status has
52// initiator:
53// TRANSACTION_END
54// or TRANSACTION_NO_RESPONSE
55// or TRANSACTION_DATA_ERROR
56// target:
57// TRANSACTION_DATA_ERROR
58// or TRANSACTION_ACCEPTED
59#define TRANSACTION_ACCEPTED 0x8
60#ifdef SERIAL_USE_MULTI_TRANSACTION
61int soft_serial_get_and_clean_status(int sstd_index);
62#endif
diff --git a/drivers/awinic/aw20216.c b/drivers/awinic/aw20216.c
new file mode 100644
index 000000000..269bb3a59
--- /dev/null
+++ b/drivers/awinic/aw20216.c
@@ -0,0 +1,170 @@
1/* Copyright 2021 Jasper Chan
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "aw20216.h"
18#include "spi_master.h"
19
20/* The AW20216 appears to be somewhat similar to the IS31FL743, although quite
21 * a few things are different, such as the command byte format and page ordering.
22 * The LED addresses start from 0x00 instead of 0x01.
23 */
24#define AWINIC_ID 0b1010 << 4
25
26#define AW_PAGE_FUNCTION 0x00 << 1 // PG0, Function registers
27#define AW_PAGE_PWM 0x01 << 1 // PG1, LED PWM control
28#define AW_PAGE_SCALING 0x02 << 1 // PG2, LED current scaling control
29#define AW_PAGE_PATCHOICE 0x03 << 1 // PG3, Pattern choice?
30#define AW_PAGE_PWMSCALING 0x04 << 1 // PG4, LED PWM + Scaling control?
31
32#define AW_WRITE 0
33#define AW_READ 1
34
35#define AW_REG_CONFIGURATION 0x00 // PG0
36#define AW_REG_GLOBALCURRENT 0x01 // PG0
37
38// Default value of AW_REG_CONFIGURATION
39// D7:D4 = 1011, SWSEL (SW1~SW12 active)
40// D3 = 0?, reserved (apparently this should be 1 but it doesn't seem to matter)
41// D2:D1 = 00, OSDE (open/short detection enable)
42// D0 = 0, CHIPEN (write 1 to enable LEDs when hardware enable pulled high)
43#define AW_CONFIG_DEFAULT 0b10110000
44#define AW_CHIPEN 1
45
46#ifndef AW_SCALING_MAX
47# define AW_SCALING_MAX 150
48#endif
49
50#ifndef AW_GLOBAL_CURRENT_MAX
51# define AW_GLOBAL_CURRENT_MAX 150
52#endif
53
54#ifndef DRIVER_1_CS
55# define DRIVER_1_CS B13
56#endif
57
58#ifndef DRIVER_1_EN
59# define DRIVER_1_EN C13
60#endif
61
62#ifndef AW_SPI_DIVISOR
63# define AW_SPI_DIVISOR 4
64#endif
65
66uint8_t g_spi_transfer_buffer[20] = {0};
67aw_led g_pwm_buffer[DRIVER_LED_TOTAL];
68bool g_pwm_buffer_update_required[DRIVER_LED_TOTAL];
69
70bool AW20216_write_register(pin_t slave_pin, uint8_t page, uint8_t reg, uint8_t data) {
71 // Do we need to call spi_stop() if this fails?
72 if (!spi_start(slave_pin, false, 0, AW_SPI_DIVISOR)) {
73 return false;
74 }
75
76 g_spi_transfer_buffer[0] = (AWINIC_ID | page | AW_WRITE);
77 g_spi_transfer_buffer[1] = reg;
78 g_spi_transfer_buffer[2] = data;
79
80 if (spi_transmit(g_spi_transfer_buffer, 3) != SPI_STATUS_SUCCESS) {
81 spi_stop();
82 return false;
83 }
84 spi_stop();
85 return true;
86}
87
88bool AW20216_init_scaling(void) {
89 // Set constant current to the max, control brightness with PWM
90 aw_led led;
91 for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
92 led = g_aw_leds[i];
93 if (led.driver == 0) {
94 AW20216_write_register(DRIVER_1_CS, AW_PAGE_SCALING, led.r, AW_SCALING_MAX);
95 AW20216_write_register(DRIVER_1_CS, AW_PAGE_SCALING, led.g, AW_SCALING_MAX);
96 AW20216_write_register(DRIVER_1_CS, AW_PAGE_SCALING, led.b, AW_SCALING_MAX);
97 }
98#ifdef DRIVER_2_CS
99 else if (led.driver == 1) {
100 AW20216_write_register(DRIVER_2_CS, AW_PAGE_SCALING, led.r, AW_SCALING_MAX);
101 AW20216_write_register(DRIVER_2_CS, AW_PAGE_SCALING, led.g, AW_SCALING_MAX);
102 AW20216_write_register(DRIVER_2_CS, AW_PAGE_SCALING, led.b, AW_SCALING_MAX);
103 }
104#endif
105 }
106 return true;
107}
108
109bool AW20216_soft_enable(void) {
110 AW20216_write_register(DRIVER_1_CS, AW_PAGE_FUNCTION, AW_REG_CONFIGURATION, AW_CONFIG_DEFAULT | AW_CHIPEN);
111#ifdef DRIVER_2_CS
112 AW20216_write_register(DRIVER_2_CS, AW_PAGE_FUNCTION, AW_REG_CONFIGURATION, AW_CONFIG_DEFAULT | AW_CHIPEN);
113#endif
114 return true;
115}
116
117void AW20216_update_pwm(int index, uint8_t red, uint8_t green, uint8_t blue) {
118 aw_led led = g_aw_leds[index];
119 if (led.driver == 0) {
120 AW20216_write_register(DRIVER_1_CS, AW_PAGE_PWM, led.r, red);
121 AW20216_write_register(DRIVER_1_CS, AW_PAGE_PWM, led.g, green);
122 AW20216_write_register(DRIVER_1_CS, AW_PAGE_PWM, led.b, blue);
123 }
124#ifdef DRIVER_2_CS
125 else if (led.driver == 1) {
126 AW20216_write_register(DRIVER_2_CS, AW_PAGE_PWM, led.r, red);
127 AW20216_write_register(DRIVER_2_CS, AW_PAGE_PWM, led.g, green);
128 AW20216_write_register(DRIVER_2_CS, AW_PAGE_PWM, led.b, blue);
129 }
130#endif
131 return;
132}
133
134void AW20216_init(void) {
135 // All LEDs should start with all scaling and PWM registers as off
136 setPinOutput(DRIVER_1_EN);
137 writePinHigh(DRIVER_1_EN);
138 AW20216_write_register(DRIVER_1_CS, AW_PAGE_FUNCTION, AW_REG_GLOBALCURRENT, AW_GLOBAL_CURRENT_MAX);
139#ifdef DRIVER_2_EN
140 setPinOutput(DRIVER_2_EN);
141 writePinHigh(DRIVER_2_EN);
142 AW20216_write_register(DRIVER_2_CS, AW_PAGE_FUNCTION, AW_REG_GLOBALCURRENT, AW_GLOBAL_CURRENT_MAX);
143#endif
144 AW20216_init_scaling();
145 AW20216_soft_enable();
146 return;
147}
148
149void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
150 g_pwm_buffer[index].r = red;
151 g_pwm_buffer[index].g = green;
152 g_pwm_buffer[index].b = blue;
153 g_pwm_buffer_update_required[index] = true;
154 return;
155}
156void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
157 for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
158 AW20216_set_color(i, red, green, blue);
159 }
160 return;
161}
162void AW20216_update_pwm_buffers(void) {
163 for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
164 if (g_pwm_buffer_update_required[i]) {
165 AW20216_update_pwm(i, g_pwm_buffer[i].r, g_pwm_buffer[i].g, g_pwm_buffer[i].b);
166 g_pwm_buffer_update_required[i] = false;
167 }
168 }
169 return;
170}
diff --git a/drivers/awinic/aw20216.h b/drivers/awinic/aw20216.h
new file mode 100644
index 000000000..9c6865cc8
--- /dev/null
+++ b/drivers/awinic/aw20216.h
@@ -0,0 +1,251 @@
1/* Copyright 2021 Jasper Chan (Gigahawk)
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include <stdint.h>
20#include <stdbool.h>
21
22typedef struct aw_led {
23 uint8_t driver : 2;
24 uint8_t r;
25 uint8_t g;
26 uint8_t b;
27} aw_led;
28
29extern const aw_led g_aw_leds[DRIVER_LED_TOTAL];
30
31void AW20216_init(void);
32void AW20216_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
33void AW20216_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
34void AW20216_update_pwm_buffers(void);
35
36#define CS1_SW1 0x00
37#define CS2_SW1 0x01
38#define CS3_SW1 0x02
39#define CS4_SW1 0x03
40#define CS5_SW1 0x04
41#define CS6_SW1 0x05
42#define CS7_SW1 0x06
43#define CS8_SW1 0x07
44#define CS9_SW1 0x08
45#define CS10_SW1 0x09
46#define CS11_SW1 0x0A
47#define CS12_SW1 0x0B
48#define CS13_SW1 0x0C
49#define CS14_SW1 0x0D
50#define CS15_SW1 0x0E
51#define CS16_SW1 0x0F
52#define CS17_SW1 0x10
53#define CS18_SW1 0x11
54#define CS1_SW2 0x12
55#define CS2_SW2 0x13
56#define CS3_SW2 0x14
57#define CS4_SW2 0x15
58#define CS5_SW2 0x16
59#define CS6_SW2 0x17
60#define CS7_SW2 0x18
61#define CS8_SW2 0x19
62#define CS9_SW2 0x1A
63#define CS10_SW2 0x1B
64#define CS11_SW2 0x1C
65#define CS12_SW2 0x1D
66#define CS13_SW2 0x1E
67#define CS14_SW2 0x1F
68#define CS15_SW2 0x20
69#define CS16_SW2 0x21
70#define CS17_SW2 0x22
71#define CS18_SW2 0x23
72#define CS1_SW3 0x24
73#define CS2_SW3 0x25
74#define CS3_SW3 0x26
75#define CS4_SW3 0x27
76#define CS5_SW3 0x28
77#define CS6_SW3 0x29
78#define CS7_SW3 0x2A
79#define CS8_SW3 0x2B
80#define CS9_SW3 0x2C
81#define CS10_SW3 0x2D
82#define CS11_SW3 0x2E
83#define CS12_SW3 0x2F
84#define CS13_SW3 0x30
85#define CS14_SW3 0x31
86#define CS15_SW3 0x32
87#define CS16_SW3 0x33
88#define CS17_SW3 0x34
89#define CS18_SW3 0x35
90#define CS1_SW4 0x36
91#define CS2_SW4 0x37
92#define CS3_SW4 0x38
93#define CS4_SW4 0x39
94#define CS5_SW4 0x3A
95#define CS6_SW4 0x3B
96#define CS7_SW4 0x3C
97#define CS8_SW4 0x3D
98#define CS9_SW4 0x3E
99#define CS10_SW4 0x3F
100#define CS11_SW4 0x40
101#define CS12_SW4 0x41
102#define CS13_SW4 0x42
103#define CS14_SW4 0x43
104#define CS15_SW4 0x44
105#define CS16_SW4 0x45
106#define CS17_SW4 0x46
107#define CS18_SW4 0x47
108#define CS1_SW5 0x48
109#define CS2_SW5 0x49
110#define CS3_SW5 0x4A
111#define CS4_SW5 0x4B
112#define CS5_SW5 0x4C
113#define CS6_SW5 0x4D
114#define CS7_SW5 0x4E
115#define CS8_SW5 0x4F
116#define CS9_SW5 0x50
117#define CS10_SW5 0x51
118#define CS11_SW5 0x52
119#define CS12_SW5 0x53
120#define CS13_SW5 0x54
121#define CS14_SW5 0x55
122#define CS15_SW5 0x56
123#define CS16_SW5 0x57
124#define CS17_SW5 0x58
125#define CS18_SW5 0x59
126#define CS1_SW6 0x5A
127#define CS2_SW6 0x5B
128#define CS3_SW6 0x5C
129#define CS4_SW6 0x5D
130#define CS5_SW6 0x5E
131#define CS6_SW6 0x5F
132#define CS7_SW6 0x60
133#define CS8_SW6 0x61
134#define CS9_SW6 0x62
135#define CS10_SW6 0x63
136#define CS11_SW6 0x64
137#define CS12_SW6 0x65
138#define CS13_SW6 0x66
139#define CS14_SW6 0x67
140#define CS15_SW6 0x68
141#define CS16_SW6 0x69
142#define CS17_SW6 0x6A
143#define CS18_SW6 0x6B
144#define CS1_SW7 0x6C
145#define CS2_SW7 0x6D
146#define CS3_SW7 0x6E
147#define CS4_SW7 0x6F
148#define CS5_SW7 0x70
149#define CS6_SW7 0x71
150#define CS7_SW7 0x72
151#define CS8_SW7 0x73
152#define CS9_SW7 0x74
153#define CS10_SW7 0x75
154#define CS11_SW7 0x76
155#define CS12_SW7 0x77
156#define CS13_SW7 0x78
157#define CS14_SW7 0x79
158#define CS15_SW7 0x7A
159#define CS16_SW7 0x7B
160#define CS17_SW7 0x7C
161#define CS18_SW7 0x7D
162#define CS1_SW8 0x7E
163#define CS2_SW8 0x7F
164#define CS3_SW8 0x80
165#define CS4_SW8 0x81
166#define CS5_SW8 0x82
167#define CS6_SW8 0x83
168#define CS7_SW8 0x84
169#define CS8_SW8 0x85
170#define CS9_SW8 0x86
171#define CS10_SW8 0x87
172#define CS11_SW8 0x88
173#define CS12_SW8 0x89
174#define CS13_SW8 0x8A
175#define CS14_SW8 0x8B
176#define CS15_SW8 0x8C
177#define CS16_SW8 0x8D
178#define CS17_SW8 0x8E
179#define CS18_SW8 0x8F
180#define CS1_SW9 0x90
181#define CS2_SW9 0x91
182#define CS3_SW9 0x92
183#define CS4_SW9 0x93
184#define CS5_SW9 0x94
185#define CS6_SW9 0x95
186#define CS7_SW9 0x96
187#define CS8_SW9 0x97
188#define CS9_SW9 0x98
189#define CS10_SW9 0x99
190#define CS11_SW9 0x9A
191#define CS12_SW9 0x9B
192#define CS13_SW9 0x9C
193#define CS14_SW9 0x9D
194#define CS15_SW9 0x9E
195#define CS16_SW9 0x9F
196#define CS17_SW9 0xA0
197#define CS18_SW9 0xA1
198#define CS1_SW10 0xA2
199#define CS2_SW10 0xA3
200#define CS3_SW10 0xA4
201#define CS4_SW10 0xA5
202#define CS5_SW10 0xA6
203#define CS6_SW10 0xA7
204#define CS7_SW10 0xA8
205#define CS8_SW10 0xA9
206#define CS9_SW10 0xAA
207#define CS10_SW10 0xAB
208#define CS11_SW10 0xAC
209#define CS12_SW10 0xAD
210#define CS13_SW10 0xAE
211#define CS14_SW10 0xAF
212#define CS15_SW10 0xB0
213#define CS16_SW10 0xB1
214#define CS17_SW10 0xB2
215#define CS18_SW10 0xB3
216#define CS1_SW11 0xB4
217#define CS2_SW11 0xB5
218#define CS3_SW11 0xB6
219#define CS4_SW11 0xB7
220#define CS5_SW11 0xB8
221#define CS6_SW11 0xB9
222#define CS7_SW11 0xBA
223#define CS8_SW11 0xBB
224#define CS9_SW11 0xBC
225#define CS10_SW11 0xBD
226#define CS11_SW11 0xBE
227#define CS12_SW11 0xBF
228#define CS13_SW11 0xC0
229#define CS14_SW11 0xC1
230#define CS15_SW11 0xC2
231#define CS16_SW11 0xC3
232#define CS17_SW11 0xC4
233#define CS18_SW11 0xC5
234#define CS1_SW12 0xC6
235#define CS2_SW12 0xC7
236#define CS3_SW12 0xC8
237#define CS4_SW12 0xC9
238#define CS5_SW12 0xCA
239#define CS6_SW12 0xCB
240#define CS7_SW12 0xCC
241#define CS8_SW12 0xCD
242#define CS9_SW12 0xCE
243#define CS10_SW12 0xCF
244#define CS11_SW12 0xD0
245#define CS12_SW12 0xD1
246#define CS13_SW12 0xD2
247#define CS14_SW12 0xD3
248#define CS15_SW12 0xD4
249#define CS16_SW12 0xD5
250#define CS17_SW12 0xD6
251#define CS18_SW12 0xD7
diff --git a/drivers/chibios/serial.c b/drivers/chibios/serial.c
index 54f7e1321..f54fbcee4 100644
--- a/drivers/chibios/serial.c
+++ b/drivers/chibios/serial.c
@@ -74,21 +74,12 @@ static THD_FUNCTION(Thread1, arg) {
74 } 74 }
75} 75}
76 76
77static SSTD_t *Transaction_table = NULL; 77void soft_serial_initiator_init(void) {
78static uint8_t Transaction_table_size = 0;
79
80void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) {
81 Transaction_table = sstd_table;
82 Transaction_table_size = (uint8_t)sstd_table_size;
83
84 serial_output(); 78 serial_output();
85 serial_high(); 79 serial_high();
86} 80}
87 81
88void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) { 82void soft_serial_target_init(void) {
89 Transaction_table = sstd_table;
90 Transaction_table_size = (uint8_t)sstd_table_size;
91
92 serial_input(); 83 serial_input();
93 84
94 palEnablePadEvent(PAL_PORT(SOFT_SERIAL_PIN), PAL_PAD(SOFT_SERIAL_PIN), PAL_EVENT_MODE_FALLING_EDGE); 85 palEnablePadEvent(PAL_PORT(SOFT_SERIAL_PIN), PAL_PAD(SOFT_SERIAL_PIN), PAL_EVENT_MODE_FALLING_EDGE);
@@ -154,16 +145,14 @@ void interrupt_handler(void *arg) {
154 uint8_t checksum_computed = 0; 145 uint8_t checksum_computed = 0;
155 int sstd_index = 0; 146 int sstd_index = 0;
156 147
157#ifdef SERIAL_USE_MULTI_TRANSACTION
158 sstd_index = serial_read_byte(); 148 sstd_index = serial_read_byte();
159 sync_send(); 149 sync_send();
160#endif
161 150
162 SSTD_t *trans = &Transaction_table[sstd_index]; 151 split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
163 for (int i = 0; i < trans->initiator2target_buffer_size; ++i) { 152 for (int i = 0; i < trans->initiator2target_buffer_size; ++i) {
164 trans->initiator2target_buffer[i] = serial_read_byte(); 153 split_trans_initiator2target_buffer(trans)[i] = serial_read_byte();
165 sync_send(); 154 sync_send();
166 checksum_computed += trans->initiator2target_buffer[i]; 155 checksum_computed += split_trans_initiator2target_buffer(trans)[i];
167 } 156 }
168 checksum_computed ^= 7; 157 checksum_computed ^= 7;
169 uint8_t checksum_received = serial_read_byte(); 158 uint8_t checksum_received = serial_read_byte();
@@ -172,12 +161,17 @@ void interrupt_handler(void *arg) {
172 // wait for the sync to finish sending 161 // wait for the sync to finish sending
173 serial_delay(); 162 serial_delay();
174 163
164 // Allow any slave processing to occur
165 if (trans->slave_callback) {
166 trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans));
167 }
168
175 uint8_t checksum = 0; 169 uint8_t checksum = 0;
176 for (int i = 0; i < trans->target2initiator_buffer_size; ++i) { 170 for (int i = 0; i < trans->target2initiator_buffer_size; ++i) {
177 serial_write_byte(trans->target2initiator_buffer[i]); 171 serial_write_byte(split_trans_target2initiator_buffer(trans)[i]);
178 sync_send(); 172 sync_send();
179 serial_delay_half(); 173 serial_delay_half();
180 checksum += trans->target2initiator_buffer[i]; 174 checksum += split_trans_target2initiator_buffer(trans)[i];
181 } 175 }
182 serial_write_byte(checksum ^ 7); 176 serial_write_byte(checksum ^ 7);
183 sync_send(); 177 sync_send();
@@ -206,15 +200,10 @@ void interrupt_handler(void *arg) {
206// TRANSACTION_NO_RESPONSE 200// TRANSACTION_NO_RESPONSE
207// TRANSACTION_DATA_ERROR 201// TRANSACTION_DATA_ERROR
208// this code is very time dependent, so we need to disable interrupts 202// this code is very time dependent, so we need to disable interrupts
209#ifndef SERIAL_USE_MULTI_TRANSACTION
210int soft_serial_transaction(void) {
211 int sstd_index = 0;
212#else
213int soft_serial_transaction(int sstd_index) { 203int soft_serial_transaction(int sstd_index) {
214#endif 204 if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR;
215 205 split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
216 if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR; 206 if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered
217 SSTD_t *trans = &Transaction_table[sstd_index];
218 207
219 // TODO: remove extra delay between transactions 208 // TODO: remove extra delay between transactions
220 serial_delay(); 209 serial_delay();
@@ -244,14 +233,13 @@ int soft_serial_transaction(int sstd_index) {
244 233
245 uint8_t checksum = 0; 234 uint8_t checksum = 0;
246 // send data to the slave 235 // send data to the slave
247#ifdef SERIAL_USE_MULTI_TRANSACTION
248 serial_write_byte(sstd_index); // first chunk is transaction id 236 serial_write_byte(sstd_index); // first chunk is transaction id
249 sync_recv(); 237 sync_recv();
250#endif 238
251 for (int i = 0; i < trans->initiator2target_buffer_size; ++i) { 239 for (int i = 0; i < trans->initiator2target_buffer_size; ++i) {
252 serial_write_byte(trans->initiator2target_buffer[i]); 240 serial_write_byte(split_trans_initiator2target_buffer(trans)[i]);
253 sync_recv(); 241 sync_recv();
254 checksum += trans->initiator2target_buffer[i]; 242 checksum += split_trans_initiator2target_buffer(trans)[i];
255 } 243 }
256 serial_write_byte(checksum ^ 7); 244 serial_write_byte(checksum ^ 7);
257 sync_recv(); 245 sync_recv();
@@ -262,9 +250,9 @@ int soft_serial_transaction(int sstd_index) {
262 // receive data from the slave 250 // receive data from the slave
263 uint8_t checksum_computed = 0; 251 uint8_t checksum_computed = 0;
264 for (int i = 0; i < trans->target2initiator_buffer_size; ++i) { 252 for (int i = 0; i < trans->target2initiator_buffer_size; ++i) {
265 trans->target2initiator_buffer[i] = serial_read_byte(); 253 split_trans_target2initiator_buffer(trans)[i] = serial_read_byte();
266 sync_recv(); 254 sync_recv();
267 checksum_computed += trans->target2initiator_buffer[i]; 255 checksum_computed += split_trans_target2initiator_buffer(trans)[i];
268 } 256 }
269 checksum_computed ^= 7; 257 checksum_computed ^= 7;
270 uint8_t checksum_received = serial_read_byte(); 258 uint8_t checksum_received = serial_read_byte();
diff --git a/drivers/chibios/serial.h b/drivers/chibios/serial.h
deleted file mode 100644
index 0c1857d52..000000000
--- a/drivers/chibios/serial.h
+++ /dev/null
@@ -1,62 +0,0 @@
1#pragma once
2
3#include <stdbool.h>
4
5// /////////////////////////////////////////////////////////////////
6// Need Soft Serial defines in config.h
7// /////////////////////////////////////////////////////////////////
8// ex.
9// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
10// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
11// // 1: about 137kbps (default)
12// // 2: about 75kbps
13// // 3: about 39kbps
14// // 4: about 26kbps
15// // 5: about 20kbps
16//
17// //// USE simple API (using signle-type transaction function)
18// /* nothing */
19// //// USE flexible API (using multi-type transaction function)
20// #define SERIAL_USE_MULTI_TRANSACTION
21//
22// /////////////////////////////////////////////////////////////////
23
24// Soft Serial Transaction Descriptor
25typedef struct _SSTD_t {
26 uint8_t *status;
27 uint8_t initiator2target_buffer_size;
28 uint8_t *initiator2target_buffer;
29 uint8_t target2initiator_buffer_size;
30 uint8_t *target2initiator_buffer;
31} SSTD_t;
32#define TID_LIMIT(table) (sizeof(table) / sizeof(SSTD_t))
33
34// initiator is transaction start side
35void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
36// target is interrupt accept side
37void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size);
38
39// initiator result
40#define TRANSACTION_END 0
41#define TRANSACTION_NO_RESPONSE 0x1
42#define TRANSACTION_DATA_ERROR 0x2
43#define TRANSACTION_TYPE_ERROR 0x4
44#ifndef SERIAL_USE_MULTI_TRANSACTION
45int soft_serial_transaction(void);
46#else
47int soft_serial_transaction(int sstd_index);
48#endif
49
50// target status
51// *SSTD_t.status has
52// initiator:
53// TRANSACTION_END
54// or TRANSACTION_NO_RESPONSE
55// or TRANSACTION_DATA_ERROR
56// target:
57// TRANSACTION_DATA_ERROR
58// or TRANSACTION_ACCEPTED
59#define TRANSACTION_ACCEPTED 0x8
60#ifdef SERIAL_USE_MULTI_TRANSACTION
61int soft_serial_get_and_clean_status(int sstd_index);
62#endif
diff --git a/drivers/chibios/serial_usart.c b/drivers/chibios/serial_usart.c
index cae29388c..9f180d2d7 100644
--- a/drivers/chibios/serial_usart.c
+++ b/drivers/chibios/serial_usart.c
@@ -113,37 +113,29 @@ void usart_slave_init(void) {
113 chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL); 113 chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL);
114} 114}
115 115
116static SSTD_t* Transaction_table = NULL; 116void soft_serial_initiator_init(void) { usart_master_init(); }
117static uint8_t Transaction_table_size = 0;
118 117
119void soft_serial_initiator_init(SSTD_t* sstd_table, int sstd_table_size) { 118void soft_serial_target_init(void) { usart_slave_init(); }
120 Transaction_table = sstd_table;
121 Transaction_table_size = (uint8_t)sstd_table_size;
122
123 usart_master_init();
124}
125
126void soft_serial_target_init(SSTD_t* sstd_table, int sstd_table_size) {
127 Transaction_table = sstd_table;
128 Transaction_table_size = (uint8_t)sstd_table_size;
129
130 usart_slave_init();
131}
132 119
133void handle_soft_serial_slave(void) { 120void handle_soft_serial_slave(void) {
134 uint8_t sstd_index = sdGet(&SERIAL_USART_DRIVER); // first chunk is always transaction id 121 uint8_t sstd_index = sdGet(&SERIAL_USART_DRIVER); // first chunk is always transaction id
135 SSTD_t* trans = &Transaction_table[sstd_index]; 122 split_transaction_desc_t* trans = &split_transaction_table[sstd_index];
136 123
137 // Always write back the sstd_index as part of a basic handshake 124 // Always write back the sstd_index as part of a basic handshake
138 sstd_index ^= HANDSHAKE_MAGIC; 125 sstd_index ^= HANDSHAKE_MAGIC;
139 sdWrite(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index)); 126 sdWrite(&SERIAL_USART_DRIVER, &sstd_index, sizeof(sstd_index));
140 127
141 if (trans->initiator2target_buffer_size) { 128 if (trans->initiator2target_buffer_size) {
142 sdRead(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size); 129 sdRead(&SERIAL_USART_DRIVER, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size);
130 }
131
132 // Allow any slave processing to occur
133 if (trans->slave_callback) {
134 trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans));
143 } 135 }
144 136
145 if (trans->target2initiator_buffer_size) { 137 if (trans->target2initiator_buffer_size) {
146 sdWrite(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size); 138 sdWrite(&SERIAL_USART_DRIVER, split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size);
147 } 139 }
148 140
149 if (trans->status) { 141 if (trans->status) {
@@ -160,17 +152,14 @@ void handle_soft_serial_slave(void) {
160// TRANSACTION_END 152// TRANSACTION_END
161// TRANSACTION_NO_RESPONSE 153// TRANSACTION_NO_RESPONSE
162// TRANSACTION_DATA_ERROR 154// TRANSACTION_DATA_ERROR
163#ifndef SERIAL_USE_MULTI_TRANSACTION
164int soft_serial_transaction(void) {
165 uint8_t sstd_index = 0;
166#else
167int soft_serial_transaction(int index) { 155int soft_serial_transaction(int index) {
168 uint8_t sstd_index = index; 156 uint8_t sstd_index = index;
169#endif
170 157
171 if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR; 158 if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR;
172 SSTD_t* trans = &Transaction_table[sstd_index]; 159 split_transaction_desc_t* trans = &split_transaction_table[sstd_index];
173 msg_t res = 0; 160 msg_t res = 0;
161
162 if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered
174 163
175 sdClear(&SERIAL_USART_DRIVER); 164 sdClear(&SERIAL_USART_DRIVER);
176 165
@@ -189,7 +178,7 @@ int soft_serial_transaction(int index) {
189 } 178 }
190 179
191 if (trans->initiator2target_buffer_size) { 180 if (trans->initiator2target_buffer_size) {
192 res = sdWriteTimeout(&SERIAL_USART_DRIVER, trans->initiator2target_buffer, trans->initiator2target_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT)); 181 res = sdWriteTimeout(&SERIAL_USART_DRIVER, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT));
193 if (res < 0) { 182 if (res < 0) {
194 dprintf("serial::usart_transmit NO_RESPONSE\n"); 183 dprintf("serial::usart_transmit NO_RESPONSE\n");
195 return TRANSACTION_NO_RESPONSE; 184 return TRANSACTION_NO_RESPONSE;
@@ -197,7 +186,7 @@ int soft_serial_transaction(int index) {
197 } 186 }
198 187
199 if (trans->target2initiator_buffer_size) { 188 if (trans->target2initiator_buffer_size) {
200 res = sdReadTimeout(&SERIAL_USART_DRIVER, trans->target2initiator_buffer, trans->target2initiator_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT)); 189 res = sdReadTimeout(&SERIAL_USART_DRIVER, split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size, TIME_MS2I(SERIAL_USART_TIMEOUT));
201 if (res < 0) { 190 if (res < 0) {
202 dprintf("serial::usart_receive NO_RESPONSE\n"); 191 dprintf("serial::usart_receive NO_RESPONSE\n");
203 return TRANSACTION_NO_RESPONSE; 192 return TRANSACTION_NO_RESPONSE;
diff --git a/drivers/chibios/spi_master.c b/drivers/chibios/spi_master.c
index 4852a6eba..28ddcbb2b 100644
--- a/drivers/chibios/spi_master.c
+++ b/drivers/chibios/spi_master.c
@@ -18,8 +18,13 @@
18 18
19#include "timer.h" 19#include "timer.h"
20 20
21static pin_t currentSlavePin = NO_PIN; 21static pin_t currentSlavePin = NO_PIN;
22static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0}; 22
23#if defined(K20x) || defined(KL2x)
24static SPIConfig spiConfig = {NULL, 0, 0, 0};
25#else
26static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0};
27#endif
23 28
24__attribute__((weak)) void spi_init(void) { 29__attribute__((weak)) void spi_init(void) {
25 static bool is_initialised = false; 30 static bool is_initialised = false;
@@ -27,15 +32,15 @@ __attribute__((weak)) void spi_init(void) {
27 is_initialised = true; 32 is_initialised = true;
28 33
29 // Try releasing special pins for a short time 34 // Try releasing special pins for a short time
30 palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_INPUT); 35 setPinInput(SPI_SCK_PIN);
31 palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_INPUT); 36 setPinInput(SPI_MOSI_PIN);
32 palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_INPUT); 37 setPinInput(SPI_MISO_PIN);
33 38
34 chThdSleepMilliseconds(10); 39 chThdSleepMilliseconds(10);
35#if defined(USE_GPIOV1) 40#if defined(USE_GPIOV1)
36 palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); 41 palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), SPI_SCK_PAL_MODE);
37 palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); 42 palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_PAL_MODE);
38 palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL); 43 palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_PAL_MODE);
39#else 44#else
40 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); 45 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);
41 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); 46 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);
@@ -58,6 +63,54 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
58 return false; 63 return false;
59 } 64 }
60 65
66#if defined(K20x) || defined(KL2x)
67 spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1);
68
69 if (lsbFirst) {
70 spiConfig.tar0 |= SPIx_CTARn_LSBFE;
71 }
72
73 switch (mode) {
74 case 0:
75 break;
76 case 1:
77 spiConfig.tar0 |= SPIx_CTARn_CPHA;
78 break;
79 case 2:
80 spiConfig.tar0 |= SPIx_CTARn_CPOL;
81 break;
82 case 3:
83 spiConfig.tar0 |= SPIx_CTARn_CPHA | SPIx_CTARn_CPOL;
84 break;
85 }
86
87 switch (roundedDivisor) {
88 case 2:
89 spiConfig.tar0 |= SPIx_CTARn_BR(0);
90 break;
91 case 4:
92 spiConfig.tar0 |= SPIx_CTARn_BR(1);
93 break;
94 case 8:
95 spiConfig.tar0 |= SPIx_CTARn_BR(3);
96 break;
97 case 16:
98 spiConfig.tar0 |= SPIx_CTARn_BR(4);
99 break;
100 case 32:
101 spiConfig.tar0 |= SPIx_CTARn_BR(5);
102 break;
103 case 64:
104 spiConfig.tar0 |= SPIx_CTARn_BR(6);
105 break;
106 case 128:
107 spiConfig.tar0 |= SPIx_CTARn_BR(7);
108 break;
109 case 256:
110 spiConfig.tar0 |= SPIx_CTARn_BR(8);
111 break;
112 }
113#else
61 spiConfig.cr1 = 0; 114 spiConfig.cr1 = 0;
62 115
63 if (lsbFirst) { 116 if (lsbFirst) {
@@ -103,6 +156,7 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
103 spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0; 156 spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0;
104 break; 157 break;
105 } 158 }
159#endif
106 160
107 currentSlavePin = slavePin; 161 currentSlavePin = slavePin;
108 spiConfig.ssport = PAL_PORT(slavePin); 162 spiConfig.ssport = PAL_PORT(slavePin);
diff --git a/drivers/chibios/spi_master.h b/drivers/chibios/spi_master.h
index e93580e31..b5a6ef143 100644
--- a/drivers/chibios/spi_master.h
+++ b/drivers/chibios/spi_master.h
@@ -21,6 +21,7 @@
21#include <stdbool.h> 21#include <stdbool.h>
22 22
23#include "gpio.h" 23#include "gpio.h"
24#include "chibios_config.h"
24 25
25#ifndef SPI_DRIVER 26#ifndef SPI_DRIVER
26# define SPI_DRIVER SPID2 27# define SPI_DRIVER SPID2
@@ -31,7 +32,11 @@
31#endif 32#endif
32 33
33#ifndef SPI_SCK_PAL_MODE 34#ifndef SPI_SCK_PAL_MODE
34# define SPI_SCK_PAL_MODE 5 35# if defined(USE_GPIOV1)
36# define SPI_SCK_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
37# else
38# define SPI_SCK_PAL_MODE 5
39# endif
35#endif 40#endif
36 41
37#ifndef SPI_MOSI_PIN 42#ifndef SPI_MOSI_PIN
@@ -39,7 +44,11 @@
39#endif 44#endif
40 45
41#ifndef SPI_MOSI_PAL_MODE 46#ifndef SPI_MOSI_PAL_MODE
42# define SPI_MOSI_PAL_MODE 5 47# if defined(USE_GPIOV1)
48# define SPI_MOSI_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
49# else
50# define SPI_MOSI_PAL_MODE 5
51# endif
43#endif 52#endif
44 53
45#ifndef SPI_MISO_PIN 54#ifndef SPI_MISO_PIN
@@ -47,7 +56,11 @@
47#endif 56#endif
48 57
49#ifndef SPI_MISO_PAL_MODE 58#ifndef SPI_MISO_PAL_MODE
50# define SPI_MISO_PAL_MODE 5 59# if defined(USE_GPIOV1)
60# define SPI_MISO_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
61# else
62# define SPI_MISO_PAL_MODE 5
63# endif
51#endif 64#endif
52 65
53typedef int16_t spi_status_t; 66typedef int16_t spi_status_t;
diff --git a/drivers/eeprom/eeprom_i2c.c b/drivers/eeprom/eeprom_i2c.c
index 4210f06f9..8e80ff544 100644
--- a/drivers/eeprom/eeprom_i2c.c
+++ b/drivers/eeprom/eeprom_i2c.c
@@ -16,6 +16,9 @@
16 16
17#include <stdint.h> 17#include <stdint.h>
18#include <string.h> 18#include <string.h>
19#if defined(EXTERNAL_EEPROM_WP_PIN)
20# include "gpio.h"
21#endif
19 22
20/* 23/*
21 Note that the implementations of eeprom_XXXX_YYYY on AVR are normally 24 Note that the implementations of eeprom_XXXX_YYYY on AVR are normally
@@ -50,7 +53,14 @@ static inline void fill_target_address(uint8_t *buffer, const void *addr) {
50 } 53 }
51} 54}
52 55
53void eeprom_driver_init(void) { i2c_init(); } 56void eeprom_driver_init(void) {
57 i2c_init();
58#if defined(EXTERNAL_EEPROM_WP_PIN)
59 /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
60 writePin(EXTERNAL_EEPROM_WP_PIN, 1);
61 setPinInputHigh(EXTERNAL_EEPROM_WP_PIN);
62#endif
63}
54 64
55void eeprom_driver_erase(void) { 65void eeprom_driver_erase(void) {
56#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) 66#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)
@@ -89,6 +99,11 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
89 uint8_t * read_buf = (uint8_t *)buf; 99 uint8_t * read_buf = (uint8_t *)buf;
90 uintptr_t target_addr = (uintptr_t)addr; 100 uintptr_t target_addr = (uintptr_t)addr;
91 101
102#if defined(EXTERNAL_EEPROM_WP_PIN)
103 setPinOutput(EXTERNAL_EEPROM_WP_PIN);
104 writePin(EXTERNAL_EEPROM_WP_PIN, 0);
105#endif
106
92 while (len > 0) { 107 while (len > 0) {
93 uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE; 108 uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE;
94 int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset; 109 int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset;
@@ -116,4 +131,10 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
116 target_addr += write_length; 131 target_addr += write_length;
117 len -= write_length; 132 len -= write_length;
118 } 133 }
134
135#if defined(EXTERNAL_EEPROM_WP_PIN)
136 /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
137 writePin(EXTERNAL_EEPROM_WP_PIN, 1);
138 setPinInputHigh(EXTERNAL_EEPROM_WP_PIN);
139#endif
119} 140}
diff --git a/drivers/haptic/haptic.c b/drivers/haptic/haptic.c
index de3f40052..3fab1be1a 100644
--- a/drivers/haptic/haptic.c
+++ b/drivers/haptic/haptic.c
@@ -291,6 +291,73 @@ void haptic_play(void) {
291#endif 291#endif
292} 292}
293 293
294__attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record) {
295 switch(keycode) {
296# ifdef NO_HAPTIC_MOD
297 case QK_MOD_TAP ... QK_MOD_TAP_MAX:
298 if (record->tap.count == 0) return false;
299 break;
300 case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
301 if (record->tap.count != TAPPING_TOGGLE) return false;
302 break;
303 case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
304 if (record->tap.count == 0) return false;
305 break;
306 case KC_LCTRL ... KC_RGUI:
307 case QK_MOMENTARY ... QK_MOMENTARY_MAX:
308# endif
309# ifdef NO_HAPTIC_FN
310 case KC_FN0 ... KC_FN31:
311# endif
312# ifdef NO_HAPTIC_ALPHA
313 case KC_A ... KC_Z:
314# endif
315# ifdef NO_HAPTIC_PUNCTUATION
316 case KC_ENTER:
317 case KC_ESCAPE:
318 case KC_BSPACE:
319 case KC_SPACE:
320 case KC_MINUS:
321 case KC_EQUAL:
322 case KC_LBRACKET:
323 case KC_RBRACKET:
324 case KC_BSLASH:
325 case KC_NONUS_HASH:
326 case KC_SCOLON:
327 case KC_QUOTE:
328 case KC_GRAVE:
329 case KC_COMMA:
330 case KC_SLASH:
331 case KC_DOT:
332 case KC_NONUS_BSLASH:
333# endif
334# ifdef NO_HAPTIC_LOCKKEYS
335 case KC_CAPSLOCK:
336 case KC_SCROLLLOCK:
337 case KC_NUMLOCK:
338# endif
339# ifdef NO_HAPTIC_NAV
340 case KC_PSCREEN:
341 case KC_PAUSE:
342 case KC_INSERT:
343 case KC_DELETE:
344 case KC_PGDOWN:
345 case KC_PGUP:
346 case KC_LEFT:
347 case KC_UP:
348 case KC_RIGHT:
349 case KC_DOWN:
350 case KC_END:
351 case KC_HOME:
352# endif
353# ifdef NO_HAPTIC_NUMERIC
354 case KC_1 ... KC_0:
355# endif
356 return false;
357 }
358 return true;
359}
360
294bool process_haptic(uint16_t keycode, keyrecord_t *record) { 361bool process_haptic(uint16_t keycode, keyrecord_t *record) {
295 if (keycode == HPT_ON && record->event.pressed) { 362 if (keycode == HPT_ON && record->event.pressed) {
296 haptic_enable(); 363 haptic_enable();
@@ -335,12 +402,12 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) {
335 if (haptic_config.enable) { 402 if (haptic_config.enable) {
336 if (record->event.pressed) { 403 if (record->event.pressed) {
337 // keypress 404 // keypress
338 if (haptic_config.feedback < 2) { 405 if (haptic_config.feedback < 2 && get_haptic_enabled_key(keycode, record)) {
339 haptic_play(); 406 haptic_play();
340 } 407 }
341 } else { 408 } else {
342 // keyrelease 409 // keyrelease
343 if (haptic_config.feedback > 0) { 410 if (haptic_config.feedback > 0 && get_haptic_enabled_key(keycode, record)) {
344 haptic_play(); 411 haptic_play();
345 } 412 }
346 } 413 }
diff --git a/drivers/lcd/st7565.c b/drivers/lcd/st7565.c
new file mode 100644
index 000000000..49b13c00f
--- /dev/null
+++ b/drivers/lcd/st7565.c
@@ -0,0 +1,496 @@
1/*
2Copyright 2021
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "st7565.h"
19
20#include <string.h>
21
22#include "keyboard.h"
23#include "progmem.h"
24#include "timer.h"
25#include "wait.h"
26
27#include ST7565_FONT_H
28
29// Fundamental Commands
30#define CONTRAST 0x81
31#define DISPLAY_ALL_ON 0xA5
32#define DISPLAY_ALL_ON_RESUME 0xA4
33#define NORMAL_DISPLAY 0xA6
34#define INVERT_DISPLAY 0xA7
35#define DISPLAY_ON 0xAF
36#define DISPLAY_OFF 0xAE
37#define NOP 0xE3
38
39// Addressing Setting Commands
40#define PAM_SETCOLUMN_LSB 0x00
41#define PAM_SETCOLUMN_MSB 0x10
42#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7
43
44// Hardware Configuration Commands
45#define DISPLAY_START_LINE 0x40
46#define SEGMENT_REMAP 0xA0
47#define SEGMENT_REMAP_INV 0xA1
48#define COM_SCAN_INC 0xC0
49#define COM_SCAN_DEC 0xC8
50#define LCD_BIAS_7 0xA3
51#define LCD_BIAS_9 0xA2
52#define RESISTOR_RATIO 0x20
53#define POWER_CONTROL 0x28
54
55// Misc defines
56#ifndef ST7565_BLOCK_COUNT
57# define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8)
58#endif
59#ifndef ST7565_BLOCK_SIZE
60# define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT)
61#endif
62
63#define ST7565_ALL_BLOCKS_MASK (((((ST7565_BLOCK_TYPE)1 << (ST7565_BLOCK_COUNT - 1)) - 1) << 1) | 1)
64
65#define HAS_FLAGS(bits, flags) ((bits & flags) == flags)
66
67// Display buffer's is the same as the display memory layout
68// this is so we don't end up with rounding errors with
69// parts of the display unusable or don't get cleared correctly
70// and also allows for drawing & inverting
71uint8_t st7565_buffer[ST7565_MATRIX_SIZE];
72uint8_t * st7565_cursor;
73ST7565_BLOCK_TYPE st7565_dirty = 0;
74bool st7565_initialized = false;
75bool st7565_active = false;
76bool st7565_inverted = false;
77display_rotation_t st7565_rotation = DISPLAY_ROTATION_0;
78#if ST7565_TIMEOUT > 0
79uint32_t st7565_timeout;
80#endif
81#if ST7565_UPDATE_INTERVAL > 0
82uint16_t st7565_update_timeout;
83#endif
84
85// Flips the rendering bits for a character at the current cursor position
86static void InvertCharacter(uint8_t *cursor) {
87 const uint8_t *end = cursor + ST7565_FONT_WIDTH;
88 while (cursor < end) {
89 *cursor = ~(*cursor);
90 cursor++;
91 }
92}
93
94bool st7565_init(display_rotation_t rotation) {
95 setPinOutput(ST7565_A0_PIN);
96 writePinHigh(ST7565_A0_PIN);
97 setPinOutput(ST7565_RST_PIN);
98 writePinHigh(ST7565_RST_PIN);
99
100 st7565_rotation = st7565_init_user(rotation);
101
102 spi_init();
103 spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
104
105 st7565_reset();
106
107 st7565_send_cmd(LCD_BIAS_7);
108 if (!HAS_FLAGS(st7565_rotation, DISPLAY_ROTATION_180)) {
109 st7565_send_cmd(SEGMENT_REMAP);
110 st7565_send_cmd(COM_SCAN_DEC);
111 } else {
112 st7565_send_cmd(SEGMENT_REMAP_INV);
113 st7565_send_cmd(COM_SCAN_INC);
114 }
115 st7565_send_cmd(DISPLAY_START_LINE | 0x00);
116 st7565_send_cmd(CONTRAST);
117 st7565_send_cmd(ST7565_CONTRAST);
118 st7565_send_cmd(RESISTOR_RATIO | 0x01);
119 st7565_send_cmd(POWER_CONTROL | 0x04);
120 wait_ms(50);
121 st7565_send_cmd(POWER_CONTROL | 0x06);
122 wait_ms(50);
123 st7565_send_cmd(POWER_CONTROL | 0x07);
124 wait_ms(10);
125 st7565_send_cmd(DISPLAY_ON);
126 st7565_send_cmd(DISPLAY_ALL_ON_RESUME);
127 st7565_send_cmd(NORMAL_DISPLAY);
128
129 spi_stop();
130
131#if ST7565_TIMEOUT > 0
132 st7565_timeout = timer_read32() + ST7565_TIMEOUT;
133#endif
134
135 st7565_clear();
136 st7565_initialized = true;
137 st7565_active = true;
138 return true;
139}
140
141__attribute__((weak)) display_rotation_t st7565_init_user(display_rotation_t rotation) { return rotation; }
142
143void st7565_clear(void) {
144 memset(st7565_buffer, 0, sizeof(st7565_buffer));
145 st7565_cursor = &st7565_buffer[0];
146 st7565_dirty = ST7565_ALL_BLOCKS_MASK;
147}
148
149uint8_t crot(uint8_t a, int8_t n) {
150 const uint8_t mask = 0x7;
151 n &= mask;
152 return a << n | a >> (-n & mask);
153}
154
155void st7565_render(void) {
156 if (!st7565_initialized) {
157 return;
158 }
159
160 // Do we have work to do?
161 st7565_dirty &= ST7565_ALL_BLOCKS_MASK;
162 if (!st7565_dirty) {
163 return;
164 }
165
166 // Find first dirty block
167 uint8_t update_start = 0;
168 while (!(st7565_dirty & ((ST7565_BLOCK_TYPE)1 << update_start))) {
169 ++update_start;
170 }
171
172 // Calculate commands to set memory addressing bounds.
173 uint8_t start_page = ST7565_BLOCK_SIZE * update_start / ST7565_DISPLAY_WIDTH;
174 uint8_t start_column = ST7565_BLOCK_SIZE * update_start % ST7565_DISPLAY_WIDTH;
175 // IC has 132 segment drivers, for panels with less width we need to offset the starting column
176 if (HAS_FLAGS(st7565_rotation, DISPLAY_ROTATION_180)) {
177 start_column += (132 - ST7565_DISPLAY_WIDTH);
178 }
179
180 spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
181
182 st7565_send_cmd(PAM_PAGE_ADDR | start_page);
183 st7565_send_cmd(PAM_SETCOLUMN_LSB | ((ST7565_COLUMN_OFFSET + start_column) & 0x0f));
184 st7565_send_cmd(PAM_SETCOLUMN_MSB | ((ST7565_COLUMN_OFFSET + start_column) >> 4 & 0x0f));
185
186 st7565_send_data(&st7565_buffer[ST7565_BLOCK_SIZE * update_start], ST7565_BLOCK_SIZE);
187
188 // Turn on display if it is off
189 st7565_on();
190
191 // Clear dirty flag
192 st7565_dirty &= ~((ST7565_BLOCK_TYPE)1 << update_start);
193}
194
195void st7565_set_cursor(uint8_t col, uint8_t line) {
196 uint16_t index = line * ST7565_DISPLAY_WIDTH + col * ST7565_FONT_WIDTH;
197
198 // Out of bounds?
199 if (index >= ST7565_MATRIX_SIZE) {
200 index = 0;
201 }
202
203 st7565_cursor = &st7565_buffer[index];
204}
205
206void st7565_advance_page(bool clearPageRemainder) {
207 uint16_t index = st7565_cursor - &st7565_buffer[0];
208 uint8_t remaining = ST7565_DISPLAY_WIDTH - (index % ST7565_DISPLAY_WIDTH);
209
210 if (clearPageRemainder) {
211 // Remaining Char count
212 remaining = remaining / ST7565_FONT_WIDTH;
213
214 // Write empty character until next line
215 while (remaining--) st7565_write_char(' ', false);
216 } else {
217 // Next page index out of bounds?
218 if (index + remaining >= ST7565_MATRIX_SIZE) {
219 index = 0;
220 remaining = 0;
221 }
222
223 st7565_cursor = &st7565_buffer[index + remaining];
224 }
225}
226
227void st7565_advance_char(void) {
228 uint16_t nextIndex = st7565_cursor - &st7565_buffer[0] + ST7565_FONT_WIDTH;
229 uint8_t remainingSpace = ST7565_DISPLAY_WIDTH - (nextIndex % ST7565_DISPLAY_WIDTH);
230
231 // Do we have enough space on the current line for the next character
232 if (remainingSpace < ST7565_FONT_WIDTH) {
233 nextIndex += remainingSpace;
234 }
235
236 // Did we go out of bounds
237 if (nextIndex >= ST7565_MATRIX_SIZE) {
238 nextIndex = 0;
239 }
240
241 // Update cursor position
242 st7565_cursor = &st7565_buffer[nextIndex];
243}
244
245// Main handler that writes character data to the display buffer
246void st7565_write_char(const char data, bool invert) {
247 // Advance to the next line if newline
248 if (data == '\n') {
249 // Old source wrote ' ' until end of line...
250 st7565_advance_page(true);
251 return;
252 }
253
254 if (data == '\r') {
255 st7565_advance_page(false);
256 return;
257 }
258
259 // copy the current render buffer to check for dirty after
260 static uint8_t st7565_temp_buffer[ST7565_FONT_WIDTH];
261 memcpy(&st7565_temp_buffer, st7565_cursor, ST7565_FONT_WIDTH);
262
263 _Static_assert(sizeof(font) >= ((ST7565_FONT_END + 1 - ST7565_FONT_START) * ST7565_FONT_WIDTH), "ST7565_FONT_END references outside array");
264
265 // set the reder buffer data
266 uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index
267 if (cast_data < ST7565_FONT_START || cast_data > ST7565_FONT_END) {
268 memset(st7565_cursor, 0x00, ST7565_FONT_WIDTH);
269 } else {
270 const uint8_t *glyph = &font[(cast_data - ST7565_FONT_START) * ST7565_FONT_WIDTH];
271 memcpy_P(st7565_cursor, glyph, ST7565_FONT_WIDTH);
272 }
273
274 // Invert if needed
275 if (invert) {
276 InvertCharacter(st7565_cursor);
277 }
278
279 // Dirty check
280 if (memcmp(&st7565_temp_buffer, st7565_cursor, ST7565_FONT_WIDTH)) {
281 uint16_t index = st7565_cursor - &st7565_buffer[0];
282 st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE));
283 // Edgecase check if the written data spans the 2 chunks
284 st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << ((index + ST7565_FONT_WIDTH - 1) / ST7565_BLOCK_SIZE));
285 }
286
287 // Finally move to the next char
288 st7565_advance_char();
289}
290
291void st7565_write(const char *data, bool invert) {
292 const char *end = data + strlen(data);
293 while (data < end) {
294 st7565_write_char(*data, invert);
295 data++;
296 }
297}
298
299void st7565_write_ln(const char *data, bool invert) {
300 st7565_write(data, invert);
301 st7565_advance_page(true);
302}
303
304void st7565_pan(bool left) {
305 uint16_t i = 0;
306 for (uint16_t y = 0; y < ST7565_DISPLAY_HEIGHT / 8; y++) {
307 if (left) {
308 for (uint16_t x = 0; x < ST7565_DISPLAY_WIDTH - 1; x++) {
309 i = y * ST7565_DISPLAY_WIDTH + x;
310 st7565_buffer[i] = st7565_buffer[i + 1];
311 }
312 } else {
313 for (uint16_t x = ST7565_DISPLAY_WIDTH - 1; x > 0; x--) {
314 i = y * ST7565_DISPLAY_WIDTH + x;
315 st7565_buffer[i] = st7565_buffer[i - 1];
316 }
317 }
318 }
319 st7565_dirty = ST7565_ALL_BLOCKS_MASK;
320}
321
322display_buffer_reader_t st7565_read_raw(uint16_t start_index) {
323 if (start_index > ST7565_MATRIX_SIZE) start_index = ST7565_MATRIX_SIZE;
324 display_buffer_reader_t ret_reader;
325 ret_reader.current_element = &st7565_buffer[start_index];
326 ret_reader.remaining_element_count = ST7565_MATRIX_SIZE - start_index;
327 return ret_reader;
328}
329
330void st7565_write_raw_byte(const char data, uint16_t index) {
331 if (index > ST7565_MATRIX_SIZE) index = ST7565_MATRIX_SIZE;
332 if (st7565_buffer[index] == data) return;
333 st7565_buffer[index] = data;
334 st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE));
335}
336
337void st7565_write_raw(const char *data, uint16_t size) {
338 uint16_t cursor_start_index = st7565_cursor - &st7565_buffer[0];
339 if ((size + cursor_start_index) > ST7565_MATRIX_SIZE) size = ST7565_MATRIX_SIZE - cursor_start_index;
340 for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
341 uint8_t c = *data++;
342 if (st7565_buffer[i] == c) continue;
343 st7565_buffer[i] = c;
344 st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE));
345 }
346}
347
348void st7565_write_pixel(uint8_t x, uint8_t y, bool on) {
349 if (x >= ST7565_DISPLAY_WIDTH) {
350 return;
351 }
352 uint16_t index = x + (y / 8) * ST7565_DISPLAY_WIDTH;
353 if (index >= ST7565_MATRIX_SIZE) {
354 return;
355 }
356 uint8_t data = st7565_buffer[index];
357 if (on) {
358 data |= (1 << (y % 8));
359 } else {
360 data &= ~(1 << (y % 8));
361 }
362 if (st7565_buffer[index] != data) {
363 st7565_buffer[index] = data;
364 st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (index / ST7565_BLOCK_SIZE));
365 }
366}
367
368#if defined(__AVR__)
369void st7565_write_P(const char *data, bool invert) {
370 uint8_t c = pgm_read_byte(data);
371 while (c != 0) {
372 st7565_write_char(c, invert);
373 c = pgm_read_byte(++data);
374 }
375}
376
377void st7565_write_ln_P(const char *data, bool invert) {
378 st7565_write_P(data, invert);
379 st7565_advance_page(true);
380}
381
382void st7565_write_raw_P(const char *data, uint16_t size) {
383 uint16_t cursor_start_index = st7565_cursor - &st7565_buffer[0];
384 if ((size + cursor_start_index) > ST7565_MATRIX_SIZE) size = ST7565_MATRIX_SIZE - cursor_start_index;
385 for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
386 uint8_t c = pgm_read_byte(data++);
387 if (st7565_buffer[i] == c) continue;
388 st7565_buffer[i] = c;
389 st7565_dirty |= ((ST7565_BLOCK_TYPE)1 << (i / ST7565_BLOCK_SIZE));
390 }
391}
392#endif // defined(__AVR__)
393
394bool st7565_on(void) {
395 if (!st7565_initialized) {
396 return st7565_active;
397 }
398
399#if ST7565_TIMEOUT > 0
400 st7565_timeout = timer_read32() + ST7565_TIMEOUT;
401#endif
402
403 if (!st7565_active) {
404 spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
405 st7565_send_cmd(DISPLAY_ON);
406 spi_stop();
407 st7565_active = true;
408 st7565_on_user();
409 }
410 return st7565_active;
411}
412
413__attribute__((weak)) void st7565_on_user(void) {}
414
415bool st7565_off(void) {
416 if (!st7565_initialized) {
417 return !st7565_active;
418 }
419
420 if (st7565_active) {
421 spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
422 st7565_send_cmd(DISPLAY_OFF);
423 spi_stop();
424 st7565_active = false;
425 st7565_off_user();
426 }
427 return !st7565_active;
428}
429
430__attribute__((weak)) void st7565_off_user(void) {}
431
432bool st7565_is_on(void) { return st7565_active; }
433
434bool st7565_invert(bool invert) {
435 if (!st7565_initialized) {
436 return st7565_inverted;
437 }
438
439 if (invert != st7565_inverted) {
440 spi_start(ST7565_SS_PIN, false, 0, ST7565_SPI_CLK_DIVISOR);
441 st7565_send_cmd(invert ? INVERT_DISPLAY : NORMAL_DISPLAY);
442 spi_stop();
443 st7565_inverted = invert;
444 }
445 return st7565_inverted;
446}
447
448uint8_t st7565_max_chars(void) { return ST7565_DISPLAY_WIDTH / ST7565_FONT_WIDTH; }
449
450uint8_t st7565_max_lines(void) { return ST7565_DISPLAY_HEIGHT / ST7565_FONT_HEIGHT; }
451
452void st7565_task(void) {
453 if (!st7565_initialized) {
454 return;
455 }
456
457#if ST7565_UPDATE_INTERVAL > 0
458 if (timer_elapsed(st7565_update_timeout) >= ST7565_UPDATE_INTERVAL) {
459 st7565_update_timeout = timer_read();
460 st7565_set_cursor(0, 0);
461 st7565_task_user();
462 }
463#else
464 st7565_set_cursor(0, 0);
465 st7565_task_user();
466#endif
467
468 // Smart render system, no need to check for dirty
469 st7565_render();
470
471 // Display timeout check
472#if ST7565_TIMEOUT > 0
473 if (st7565_active && timer_expired32(timer_read32(), st7565_timeout)) {
474 st7565_off();
475 }
476#endif
477}
478
479__attribute__((weak)) void st7565_task_user(void) {}
480
481void st7565_reset(void) {
482 writePinLow(ST7565_RST_PIN);
483 wait_ms(20);
484 writePinHigh(ST7565_RST_PIN);
485 wait_ms(20);
486}
487
488spi_status_t st7565_send_cmd(uint8_t cmd) {
489 writePinLow(ST7565_A0_PIN);
490 return spi_write(cmd);
491}
492
493spi_status_t st7565_send_data(uint8_t *data, uint16_t length) {
494 writePinHigh(ST7565_A0_PIN);
495 return spi_transmit(data, length);
496}
diff --git a/drivers/lcd/st7565.h b/drivers/lcd/st7565.h
new file mode 100644
index 000000000..d453dbe6d
--- /dev/null
+++ b/drivers/lcd/st7565.h
@@ -0,0 +1,219 @@
1/*
2Copyright 2021
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#pragma once
19
20#include <stdint.h>
21#include <stdbool.h>
22
23#include "spi_master.h"
24
25#ifndef ST7565_DISPLAY_WIDTH
26# define ST7565_DISPLAY_WIDTH 128
27#endif
28#ifndef ST7565_DISPLAY_HEIGHT
29# define ST7565_DISPLAY_HEIGHT 32
30#endif
31#ifndef ST7565_MATRIX_SIZE
32# define ST7565_MATRIX_SIZE (ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH) // 1024 (compile time mathed)
33#endif
34#ifndef ST7565_BLOCK_TYPE
35# define ST7565_BLOCK_TYPE uint16_t
36#endif
37#ifndef ST7565_BLOCK_COUNT
38# define ST7565_BLOCK_COUNT (sizeof(ST7565_BLOCK_TYPE) * 8) // 32 (compile time mathed)
39#endif
40#ifndef ST7565_BLOCK_SIZE
41# define ST7565_BLOCK_SIZE (ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT) // 32 (compile time mathed)
42#endif
43
44// the column address corresponding to the first column in the display hardware
45#if !defined(ST7565_COLUMN_OFFSET)
46# define ST7565_COLUMN_OFFSET 0
47#endif
48
49// spi clock divisor
50#if !defined(ST7565_SPI_CLK_DIVISOR)
51# define ST7565_SPI_CLK_DIVISOR 4
52#endif
53
54// Custom font file to use
55#if !defined(ST7565_FONT_H)
56# define ST7565_FONT_H "glcdfont.c"
57#endif
58// unsigned char value of the first character in the font file
59#if !defined(ST7565_FONT_START)
60# define ST7565_FONT_START 0
61#endif
62// unsigned char value of the last character in the font file
63#if !defined(ST7565_FONT_END)
64# define ST7565_FONT_END 223
65#endif
66// Font render width
67#if !defined(ST7565_FONT_WIDTH)
68# define ST7565_FONT_WIDTH 6
69#endif
70// Font render height
71#if !defined(ST7565_FONT_HEIGHT)
72# define ST7565_FONT_HEIGHT 8
73#endif
74// Default contrast level
75#if !defined(ST7565_CONTRAST)
76# define ST7565_CONTRAST 32
77#endif
78
79#if !defined(ST7565_TIMEOUT)
80# if defined(ST7565_DISABLE_TIMEOUT)
81# define ST7565_TIMEOUT 0
82# else
83# define ST7565_TIMEOUT 60000
84# endif
85#endif
86
87#if !defined(ST7565_UPDATE_INTERVAL) && defined(SPLIT_KEYBOARD)
88# define ST7565_UPDATE_INTERVAL 50
89#endif
90
91typedef struct __attribute__((__packed__)) {
92 uint8_t *current_element;
93 uint16_t remaining_element_count;
94} display_buffer_reader_t;
95
96// Rotation enum values are flags
97typedef enum { DISPLAY_ROTATION_0, DISPLAY_ROTATION_180 } display_rotation_t;
98
99// Initialize the display, rotating the rendered output based on the define passed in.
100// Returns true if the display was initialized successfully
101bool st7565_init(display_rotation_t rotation);
102
103// Called at the start of st7565_init, weak function overridable by the user
104// rotation - the value passed into st7565_init
105// Return new display_rotation_t if you want to override default rotation
106display_rotation_t st7565_init_user(display_rotation_t rotation);
107
108// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
109void st7565_clear(void);
110
111// Renders the dirty chunks of the buffer to display
112void st7565_render(void);
113
114// Moves cursor to character position indicated by column and line, wraps if out of bounds
115// Max column denoted by 'st7565_max_chars()' and max lines by 'st7565_max_lines()' functions
116void st7565_set_cursor(uint8_t col, uint8_t line);
117
118// Advances the cursor to the next page, writing ' ' if true
119// Wraps to the begining when out of bounds
120void st7565_advance_page(bool clearPageRemainder);
121
122// Moves the cursor forward 1 character length
123// Advance page if there is not enough room for the next character
124// Wraps to the begining when out of bounds
125void st7565_advance_char(void);
126
127// Writes a single character to the buffer at current cursor position
128// Advances the cursor while writing, inverts the pixels if true
129// Main handler that writes character data to the display buffer
130void st7565_write_char(const char data, bool invert);
131
132// Writes a string to the buffer at current cursor position
133// Advances the cursor while writing, inverts the pixels if true
134void st7565_write(const char *data, bool invert);
135
136// Writes a string to the buffer at current cursor position
137// Advances the cursor while writing, inverts the pixels if true
138// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
139void st7565_write_ln(const char *data, bool invert);
140
141// Pans the buffer to the right (or left by passing true) by moving contents of the buffer
142// Useful for moving the screen in preparation for new drawing
143void st7565_pan(bool left);
144
145// Returns a pointer to the requested start index in the buffer plus remaining
146// buffer length as struct
147display_buffer_reader_t st7565_read_raw(uint16_t start_index);
148
149// Writes a string to the buffer at current cursor position
150void st7565_write_raw(const char *data, uint16_t size);
151
152// Writes a single byte into the buffer at the specified index
153void st7565_write_raw_byte(const char data, uint16_t index);
154
155// Sets a specific pixel on or off
156// Coordinates start at top-left and go right and down for positive x and y
157void st7565_write_pixel(uint8_t x, uint8_t y, bool on);
158
159#if defined(__AVR__)
160// Writes a PROGMEM string to the buffer at current cursor position
161// Advances the cursor while writing, inverts the pixels if true
162// Remapped to call 'void st7565_write(const char *data, bool invert);' on ARM
163void st7565_write_P(const char *data, bool invert);
164
165// Writes a PROGMEM string to the buffer at current cursor position
166// Advances the cursor while writing, inverts the pixels if true
167// Advances the cursor to the next page, wiring ' ' to the remainder of the current page
168// Remapped to call 'void st7565_write_ln(const char *data, bool invert);' on ARM
169void st7565_write_ln_P(const char *data, bool invert);
170
171// Writes a PROGMEM string to the buffer at current cursor position
172void st7565_write_raw_P(const char *data, uint16_t size);
173#else
174# define st7565_write_P(data, invert) st7565_write(data, invert)
175# define st7565_write_ln_P(data, invert) st7565_write_ln(data, invert)
176# define st7565_write_raw_P(data, size) st7565_write_raw(data, size)
177#endif // defined(__AVR__)
178
179// Can be used to manually turn on the screen if it is off
180// Returns true if the screen was on or turns on
181bool st7565_on(void);
182
183// Called when st7565_on() turns on the screen, weak function overridable by the user
184// Not called if the screen is already on
185void st7565_on_user(void);
186
187// Can be used to manually turn off the screen if it is on
188// Returns true if the screen was off or turns off
189bool st7565_off(void);
190
191// Called when st7565_off() turns off the screen, weak function overridable by the user
192// Not called if the screen is already off
193void st7565_off_user(void);
194
195// Returns true if the screen is currently on, false if it is
196// not
197bool st7565_is_on(void);
198
199// Basically it's st7565_render, but with timeout management and st7565_task_user calling!
200void st7565_task(void);
201
202// Called at the start of st7565_task, weak function overridable by the user
203void st7565_task_user(void);
204
205// Inverts the display
206// Returns true if the screen was or is inverted
207bool st7565_invert(bool invert);
208
209// Returns the maximum number of characters that will fit on a line
210uint8_t st7565_max_chars(void);
211
212// Returns the maximum number of lines that will fit on the display
213uint8_t st7565_max_lines(void);
214
215void st7565_reset(void);
216
217spi_status_t st7565_send_cmd(uint8_t cmd);
218
219spi_status_t st7565_send_data(uint8_t *data, uint16_t length);
diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c
index 8e5ed5f07..7d4197890 100644
--- a/drivers/oled/oled_driver.c
+++ b/drivers/oled/oled_driver.c
@@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
34#define DISPLAY_ALL_ON 0xA5 34#define DISPLAY_ALL_ON 0xA5
35#define DISPLAY_ALL_ON_RESUME 0xA4 35#define DISPLAY_ALL_ON_RESUME 0xA4
36#define NORMAL_DISPLAY 0xA6 36#define NORMAL_DISPLAY 0xA6
37#define INVERT_DISPLAY 0xA7
37#define DISPLAY_ON 0xAF 38#define DISPLAY_ON 0xAF
38#define DISPLAY_OFF 0xAE 39#define DISPLAY_OFF 0xAE
39#define NOP 0xE3 40#define NOP 0xE3
@@ -114,6 +115,7 @@ OLED_BLOCK_TYPE oled_dirty = 0;
114bool oled_initialized = false; 115bool oled_initialized = false;
115bool oled_active = false; 116bool oled_active = false;
116bool oled_scrolling = false; 117bool oled_scrolling = false;
118bool oled_inverted = false;
117uint8_t oled_brightness = OLED_BRIGHTNESS; 119uint8_t oled_brightness = OLED_BRIGHTNESS;
118oled_rotation_t oled_rotation = 0; 120oled_rotation_t oled_rotation = 0;
119uint8_t oled_rotation_width = 0; 121uint8_t oled_rotation_width = 0;
@@ -690,6 +692,30 @@ bool oled_scroll_off(void) {
690 return !oled_scrolling; 692 return !oled_scrolling;
691} 693}
692 694
695bool oled_invert(bool invert) {
696 if (!oled_initialized) {
697 return oled_inverted;
698 }
699
700 if (invert && !oled_inverted) {
701 static const uint8_t PROGMEM display_inverted[] = {I2C_CMD, INVERT_DISPLAY};
702 if (I2C_TRANSMIT_P(display_inverted) != I2C_STATUS_SUCCESS) {
703 print("oled_invert cmd failed\n");
704 return oled_inverted;
705 }
706 oled_inverted = true;
707 } else if (!invert && oled_inverted) {
708 static const uint8_t PROGMEM display_normal[] = {I2C_CMD, NORMAL_DISPLAY};
709 if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) {
710 print("oled_invert cmd failed\n");
711 return oled_inverted;
712 }
713 oled_inverted = false;
714 }
715
716 return oled_inverted;
717}
718
693uint8_t oled_max_chars(void) { 719uint8_t oled_max_chars(void) {
694 if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { 720 if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
695 return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH; 721 return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH;
diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h
index a6b85f37e..fc68f0ec9 100644
--- a/drivers/oled/oled_driver.h
+++ b/drivers/oled/oled_driver.h
@@ -313,6 +313,10 @@ bool oled_scroll_left(void);
313// Returns true if the screen was not scrolling or stops scrolling 313// Returns true if the screen was not scrolling or stops scrolling
314bool oled_scroll_off(void); 314bool oled_scroll_off(void);
315 315
316// Inverts the display
317// Returns true if the screen was or is inverted
318bool oled_invert(bool invert);
319
316// Returns the maximum number of characters that will fit on a line 320// Returns the maximum number of characters that will fit on a line
317uint8_t oled_max_chars(void); 321uint8_t oled_max_chars(void);
318 322
diff --git a/keyboards/ploopyco/adns5050.c b/drivers/sensors/adns5050.c
index e12e56f20..e7273977d 100644
--- a/keyboards/ploopyco/adns5050.c
+++ b/drivers/sensors/adns5050.c
@@ -19,20 +19,16 @@
19 19
20 20
21#include "adns5050.h" 21#include "adns5050.h"
22#include "quantum.h"
23#include "wait.h" 22#include "wait.h"
24 23#include "debug.h"
25#ifdef CONSOLE_ENABLE 24#include "print.h"
26# include "print.h" 25#include "gpio.h"
27#endif
28 26
29#ifndef OPTIC_ROTATED 27#ifndef OPTIC_ROTATED
30# define OPTIC_ROTATED false 28# define OPTIC_ROTATED false
31#endif 29#endif
32 30
33// Definitions for the ADNS serial line. 31// Definitions for the ADNS serial line.
34// These really ought to be defined in your config.h, but defaults are
35// here if you're really lazy.
36#ifndef ADNS_SCLK_PIN 32#ifndef ADNS_SCLK_PIN
37# define ADNS_SCLK_PIN B7 33# define ADNS_SCLK_PIN B7
38#endif 34#endif
diff --git a/keyboards/ploopyco/adns5050.h b/drivers/sensors/adns5050.h
index ff8e8f78e..ff8e8f78e 100644
--- a/keyboards/ploopyco/adns5050.h
+++ b/drivers/sensors/adns5050.h
diff --git a/keyboards/oddball/adns/adns.c b/drivers/sensors/adns9800.c
index 9338808ff..36213179f 100644
--- a/keyboards/oddball/adns/adns.c
+++ b/drivers/sensors/adns9800.c
@@ -17,7 +17,7 @@
17#include "spi_master.h" 17#include "spi_master.h"
18#include "quantum.h" 18#include "quantum.h"
19#include "adns9800_srom_A6.h" 19#include "adns9800_srom_A6.h"
20#include "adns.h" 20#include "adns9800.h"
21 21
22// registers 22// registers
23#define REG_Product_ID 0x00 23#define REG_Product_ID 0x00
diff --git a/keyboards/oddball/adns/adns.h b/drivers/sensors/adns9800.h
index 2f50b8f1b..2f50b8f1b 100644
--- a/keyboards/oddball/adns/adns.h
+++ b/drivers/sensors/adns9800.h
diff --git a/keyboards/oddball/adns/adns9800_srom_A6.h b/drivers/sensors/adns9800_srom_A6.h
index f5b3abeb6..f5b3abeb6 100644
--- a/keyboards/oddball/adns/adns9800_srom_A6.h
+++ b/drivers/sensors/adns9800_srom_A6.h
diff --git a/keyboards/draculad/keymaps/pimoroni/pimoroni_trackball.c b/drivers/sensors/pimoroni_trackball.c
index c4f4a0441..c0ac644f7 100644
--- a/keyboards/draculad/keymaps/pimoroni/pimoroni_trackball.c
+++ b/drivers/sensors/pimoroni_trackball.c
@@ -26,8 +26,8 @@ static float precisionSpeed = 1;
26 26
27static uint16_t i2c_timeout_timer; 27static uint16_t i2c_timeout_timer;
28 28
29#ifndef I2C_TIMEOUT 29#ifndef PIMORONI_I2C_TIMEOUT
30# define I2C_TIMEOUT 100 30# define PIMORONI_I2C_TIMEOUT 100
31#endif 31#endif
32#ifndef I2C_WAITCHECK 32#ifndef I2C_WAITCHECK
33# define I2C_WAITCHECK 1000 33# define I2C_WAITCHECK 1000
@@ -38,7 +38,7 @@ static uint16_t i2c_timeout_timer;
38 38
39void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) { 39void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) {
40 uint8_t data[] = {0x00, red, green, blue, white}; 40 uint8_t data[] = {0x00, red, green, blue, white};
41 i2c_transmit(TRACKBALL_WRITE, data, sizeof(data), I2C_TIMEOUT); 41 i2c_transmit(TRACKBALL_WRITE, data, sizeof(data), PIMORONI_I2C_TIMEOUT);
42} 42}
43 43
44int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) { 44int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) {
@@ -68,59 +68,19 @@ __attribute__((weak)) void trackball_check_click(bool pressed, report_mouse_t* m
68 } 68 }
69} 69}
70 70
71bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
72 if (true) {
73 xprintf("KL: kc: %u, col: %u, row: %u, pressed: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed);
74 }
75
76
77 if (!process_record_user(keycode, record)) { return false; }
78
79/* If Mousekeys is disabled, then use handle the mouse button
80 * keycodes. This makes things simpler, and allows usage of
81 * the keycodes in a consistent manner. But only do this if
82 * Mousekeys is not enable, so it's not handled twice.
83 */
84#ifndef MOUSEKEY_ENABLE
85 if (IS_MOUSEKEY_BUTTON(keycode)) {
86 report_mouse_t currentReport = pointing_device_get_report();
87 if (record->event.pressed) {
88 currentReport.buttons |= 1 << (keycode - KC_MS_BTN1);
89 } else {
90 currentReport.buttons &= ~(1 << (keycode - KC_MS_BTN1));
91 }
92 pointing_device_set_report(currentReport);
93 pointing_device_send();
94 }
95#endif
96
97 return true;
98}
99
100void trackball_register_button(bool pressed, enum mouse_buttons button) {
101 report_mouse_t currentReport = pointing_device_get_report();
102 if (pressed) {
103 currentReport.buttons |= button;
104 } else {
105 currentReport.buttons &= ~button;
106 }
107 pointing_device_set_report(currentReport);
108}
109
110float trackball_get_precision(void) { return precisionSpeed; } 71float trackball_get_precision(void) { return precisionSpeed; }
111void trackball_set_precision(float precision) { precisionSpeed = precision; } 72void trackball_set_precision(float precision) { precisionSpeed = precision; }
112bool trackball_is_scrolling(void) { return scrolling; } 73bool trackball_is_scrolling(void) { return scrolling; }
113void trackball_set_scrolling(bool scroll) { scrolling = scroll; } 74void trackball_set_scrolling(bool scroll) { scrolling = scroll; }
114 75
115 76__attribute__((weak)) void pointing_device_init(void) { i2c_init(); trackball_set_rgbw(0x00, 0x00, 0x00, 0x00); }
116__attribute__((weak)) void pointing_device_init(void) { trackball_set_rgbw(0x80, 0x00, 0x00, 0x00); }
117 77
118void pointing_device_task(void) { 78void pointing_device_task(void) {
119 static bool debounce; 79 static bool debounce;
120 static uint16_t debounce_timer; 80 static uint16_t debounce_timer;
121 uint8_t state[5] = {}; 81 uint8_t state[5] = {};
122 if (timer_elapsed(i2c_timeout_timer) > I2C_WAITCHECK) { 82 if (timer_elapsed(i2c_timeout_timer) > I2C_WAITCHECK) {
123 if (i2c_readReg(TRACKBALL_WRITE, 0x04, state, 5, I2C_TIMEOUT) == I2C_STATUS_SUCCESS) { 83 if (i2c_readReg(TRACKBALL_READ, 0x04, state, 5, PIMORONI_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) {
124 if (!state[4] && !debounce) { 84 if (!state[4] && !debounce) {
125 if (scrolling) { 85 if (scrolling) {
126#ifdef PIMORONI_TRACKBALL_INVERT_X 86#ifdef PIMORONI_TRACKBALL_INVERT_X
@@ -159,7 +119,10 @@ void pointing_device_task(void) {
159 if (timer_elapsed(debounce_timer) > MOUSE_DEBOUNCE) debounce = false; 119 if (timer_elapsed(debounce_timer) > MOUSE_DEBOUNCE) debounce = false;
160 120
161 report_mouse_t mouse = pointing_device_get_report(); 121 report_mouse_t mouse = pointing_device_get_report();
162 // trackball_check_click(state[4] & (1 << 7), &mouse); 122
123#ifdef PIMORONI_TRACKBALL_CLICK
124 trackball_check_click(state[4] & (1 << 7), &mouse);
125#endif
163 126
164#ifndef PIMORONI_TRACKBALL_ROTATE 127#ifndef PIMORONI_TRACKBALL_ROTATE
165 update_member(&mouse.x, &x_offset); 128 update_member(&mouse.x, &x_offset);
diff --git a/users/drashna/pimoroni_trackball.h b/drivers/sensors/pimoroni_trackball.h
index a30fb0bb8..a30fb0bb8 100644
--- a/users/drashna/pimoroni_trackball.h
+++ b/drivers/sensors/pimoroni_trackball.h
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.c b/drivers/sensors/pmw3360.c
index 59e349512..91ee87b95 100644
--- a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.c
+++ b/drivers/sensors/pmw3360.c
@@ -16,8 +16,6 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 17 */
18 18
19#ifdef POINTING_DEVICE_ENABLE
20
21#include "wait.h" 19#include "wait.h"
22#include "debug.h" 20#include "debug.h"
23#include "print.h" 21#include "print.h"
@@ -29,17 +27,26 @@ bool _inBurst = false;
29#ifndef PMW_CPI 27#ifndef PMW_CPI
30# define PMW_CPI 1600 28# define PMW_CPI 1600
31#endif 29#endif
30#ifndef PMW_CLOCK_SPEED
31# define PMW_CLOCK_SPEED 70000000
32#endif
33#ifndef SPI_MODE
34# define SPI_MODE 3
35#endif
32#ifndef SPI_DIVISOR 36#ifndef SPI_DIVISOR
33# define SPI_DIVISOR 2 37# define SPI_DIVISOR (F_CPU / PMW_CLOCK_SPEED)
34#endif 38#endif
35#ifndef ROTATIONAL_TRANSFORM_ANGLE 39#ifndef ROTATIONAL_TRANSFORM_ANGLE
36# define ROTATIONAL_TRANSFORM_ANGLE 0x00 40# define ROTATIONAL_TRANSFORM_ANGLE 0x00
37#endif 41#endif
42#ifndef PMW_CS_PIN
43# define PMW_CS_PIN SPI_SS_PIN
44#endif
38 45
39void 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')); } 46void 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')); }
40 47
41bool spi_start_adv(void) { 48bool spi_start_adv(void) {
42 bool status = spi_start(SPI_SS_PIN, false, 3, SPI_DIVISOR); 49 bool status = spi_start(PMW_CS_PIN, false, SPI_MODE, SPI_DIVISOR);
43 wait_us(1); 50 wait_us(1);
44 return status; 51 return status;
45} 52}
@@ -57,7 +64,7 @@ spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data) {
57 spi_start_adv(); 64 spi_start_adv();
58 // send address of the register, with MSBit = 1 to indicate it's a write 65 // send address of the register, with MSBit = 1 to indicate it's a write
59 spi_status_t status = spi_write(reg_addr | 0x80); 66 spi_status_t status = spi_write(reg_addr | 0x80);
60 status = spi_write(data); 67 status = spi_write(data);
61 68
62 // tSCLK-NCS for write operation 69 // tSCLK-NCS for write operation
63 wait_us(20); 70 wait_us(20);
@@ -86,14 +93,21 @@ uint8_t spi_read_adv(uint8_t reg_addr) {
86} 93}
87 94
88void pmw_set_cpi(uint16_t cpi) { 95void pmw_set_cpi(uint16_t cpi) {
89 int cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119 96 uint8_t cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119
90 97
91 spi_start_adv(); 98 spi_start_adv();
92 spi_write_adv(REG_Config1, cpival); 99 spi_write_adv(REG_Config1, cpival);
93 spi_stop(); 100 spi_stop();
94} 101}
95 102
103uint16_t pmw_get_cpi(void) {
104 uint8_t cpival = spi_read_adv(REG_Config1);
105 return (uint16_t)(cpival & 0xFF) * 100;
106}
107
96bool pmw_spi_init(void) { 108bool pmw_spi_init(void) {
109 setPinOutput(PMW_CS_PIN);
110
97 spi_init(); 111 spi_init();
98 _inBurst = false; 112 _inBurst = false;
99 113
@@ -101,7 +115,7 @@ bool pmw_spi_init(void) {
101 spi_start_adv(); 115 spi_start_adv();
102 spi_stop(); 116 spi_stop();
103 117
104 spi_write_adv(REG_Shutdown, 0xb6); // Shutdown first 118 spi_write_adv(REG_Shutdown, 0xb6); // Shutdown first
105 wait_ms(300); 119 wait_ms(300);
106 120
107 spi_start_adv(); 121 spi_start_adv();
@@ -127,14 +141,18 @@ bool pmw_spi_init(void) {
127 141
128 wait_ms(1); 142 wait_ms(1);
129 143
130 return pmw_check_signature();
131}
132
133void pmw_upload_firmware(void) {
134 spi_write_adv(REG_Config2, 0x00); 144 spi_write_adv(REG_Config2, 0x00);
135 145
136 spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30)); 146 spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30));
137 147
148 bool init_success = pmw_check_signature();
149
150 writePinLow(PMW_CS_PIN);
151
152 return init_success;
153}
154
155void pmw_upload_firmware(void) {
138 spi_write_adv(REG_SROM_Enable, 0x1d); 156 spi_write_adv(REG_SROM_Enable, 0x1d);
139 157
140 wait_ms(10); 158 wait_ms(10);
@@ -217,5 +235,3 @@ report_pmw_t pmw_read_burst(void) {
217 235
218 return data; 236 return data;
219} 237}
220
221#endif
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.h b/drivers/sensors/pmw3360.h
index c1d5e3bad..d5b174179 100644
--- a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360.h
+++ b/drivers/sensors/pmw3360.h
@@ -93,6 +93,7 @@ spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data);
93uint8_t spi_read_adv(uint8_t reg_addr); 93uint8_t spi_read_adv(uint8_t reg_addr);
94bool pmw_spi_init(void); 94bool pmw_spi_init(void);
95void pmw_set_cpi(uint16_t cpi); 95void pmw_set_cpi(uint16_t cpi);
96uint16_t pmw_get_cpi(void);
96void pmw_upload_firmware(void); 97void pmw_upload_firmware(void);
97bool pmw_check_signature(void); 98bool pmw_check_signature(void);
98report_pmw_t pmw_read_burst(void); 99report_pmw_t pmw_read_burst(void);
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360_firmware.h b/drivers/sensors/pmw3360_firmware.h
index cca5a6a4d..cca5a6a4d 100644
--- a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/pmw3360_firmware.h
+++ b/drivers/sensors/pmw3360_firmware.h
diff --git a/drivers/serial.h b/drivers/serial.h
new file mode 100644
index 000000000..d9c2a69e9
--- /dev/null
+++ b/drivers/serial.h
@@ -0,0 +1,46 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include <stdint.h>
20#include <stdbool.h>
21
22#include <transactions.h>
23
24// initiator is transaction start side
25void soft_serial_initiator_init(void);
26// target is interrupt accept side
27void soft_serial_target_init(void);
28
29// initiator result
30#define TRANSACTION_END 0
31#define TRANSACTION_NO_RESPONSE 0x1
32#define TRANSACTION_DATA_ERROR 0x2
33#define TRANSACTION_TYPE_ERROR 0x4
34int soft_serial_transaction(int sstd_index);
35
36// target status
37// *SSTD_t.status has
38// initiator:
39// TRANSACTION_END
40// or TRANSACTION_NO_RESPONSE
41// or TRANSACTION_DATA_ERROR
42// target:
43// TRANSACTION_DATA_ERROR
44// or TRANSACTION_ACCEPTED
45#define TRANSACTION_ACCEPTED 0x8
46int soft_serial_get_and_clean_status(int sstd_index);
diff --git a/keyboards/anavi/macropad8/keymaps/default/config.h b/keyboards/anavi/macropad8/keymaps/default/config.h
new file mode 100644
index 000000000..dd687cad5
--- /dev/null
+++ b/keyboards/anavi/macropad8/keymaps/default/config.h
@@ -0,0 +1,19 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#define LAYER_STATE_8BIT
diff --git a/keyboards/basekeys/trifecta/config.h b/keyboards/basekeys/trifecta/config.h
index 8a9529126..28c9c18fb 100644
--- a/keyboards/basekeys/trifecta/config.h
+++ b/keyboards/basekeys/trifecta/config.h
@@ -80,11 +80,11 @@
80# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 80# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
81// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 81// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
82// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 82// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
83//# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 83//# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
84# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 84# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
85# define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 85# define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
86# define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 86# define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
87# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash. 87# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
88# define RGB_MATRIX_HUE_STEP 8 88# define RGB_MATRIX_HUE_STEP 8
89# define RGB_MATRIX_SAT_STEP 8 89# define RGB_MATRIX_SAT_STEP 8
90# define RGB_MATRIX_VAL_STEP 8 90# define RGB_MATRIX_VAL_STEP 8
diff --git a/keyboards/bm40hsrgb/config.h b/keyboards/bm40hsrgb/config.h
index 167a5667a..8ef9a78c7 100755
--- a/keyboards/bm40hsrgb/config.h
+++ b/keyboards/bm40hsrgb/config.h
@@ -50,6 +50,6 @@
50#ifdef RGB_DI_PIN 50#ifdef RGB_DI_PIN
51 #define RGB_MATRIX_KEYPRESSES // reacts to keypresses 51 #define RGB_MATRIX_KEYPRESSES // reacts to keypresses
52#endif 52#endif
53#ifndef RGB_DISABLE_WHEN_USB_SUSPENDED 53#ifdef RGB_MATRIX_ENABLE
54# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 54# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
55#endif 55#endif
diff --git a/keyboards/bm68rgb/keymaps/peepeetee/config.h b/keyboards/bm68rgb/keymaps/peepeetee/config.h
index 53eebce7f..aada255cd 100644
--- a/keyboards/bm68rgb/keymaps/peepeetee/config.h
+++ b/keyboards/bm68rgb/keymaps/peepeetee/config.h
@@ -64,7 +64,7 @@
64// #define RGBLIGHT_SAT_STEP 25 // Units to step when in/decreasing saturation 64// #define RGBLIGHT_SAT_STEP 25 // Units to step when in/decreasing saturation
65// #define RGBLIGHT_VAL_STEP 12 // Units to step when in/decreasing value (brightness) 65// #define RGBLIGHT_VAL_STEP 12 // Units to step when in/decreasing value (brightness)
66// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 66// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
67// #define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 67// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
68// #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 68// #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
69// #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 69// #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
70// #define RGBLIGHT_ANIMATIONS // Run RGB animations 70// #define RGBLIGHT_ANIMATIONS // Run RGB animations
diff --git a/keyboards/boardsource/the_mark/config.h b/keyboards/boardsource/the_mark/config.h
index 5888452ce..9ca598b40 100644
--- a/keyboards/boardsource/the_mark/config.h
+++ b/keyboards/boardsource/the_mark/config.h
@@ -59,7 +59,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
59#define DRIVER_LED_TOTAL 24 // Number of LEDs 59#define DRIVER_LED_TOTAL 24 // Number of LEDs
60#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 60#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200
61# ifndef RGB_DISABLE_WHEN_USB_SUSPENDED 61# ifndef RGB_DISABLE_WHEN_USB_SUSPENDED
62# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 62# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
63# endif 63# endif
64#endif 64#endif
65 65
diff --git a/keyboards/checkerboards/nop60/info.json b/keyboards/checkerboards/nop60/info.json
index 82ff7229f..66e770634 100644
--- a/keyboards/checkerboards/nop60/info.json
+++ b/keyboards/checkerboards/nop60/info.json
@@ -1,15 +1,143 @@
1{ 1{
2 "keyboard_name": "nop60", 2 "keyboard_name": "nop60",
3 "url": "",
4 "maintainer": "nasp", 3 "maintainer": "nasp",
5 "width": 15,
6 "height": 5, 4 "height": 5,
5 "width": 15,
6 "url": "",
7 "layouts": { 7 "layouts": {
8 "LAYOUT": { 8 "LAYOUT": {
9 "2x3u": [{"label":"Esc", "x":0, "y":0}, {"label":"!", "x":1, "y":0}, {"label":"@", "x":2, "y":0}, {"label":"#", "x":3, "y":0}, {"label":"$", "x":4, "y":0}, {"label":"%", "x":5, "y":0}, {"label":"^", "x":6, "y":0}, {"label":"&", "x":7, "y":0}, {"label":"*", "x":8, "y":0}, {"label":"(", "x":9, "y":0}, {"label":")", "x":10, "y":0}, {"label":"_", "x":11, "y":0}, {"label":"+", "x":12, "y":0}, {"label":"~", "x":13, "y":0}, {"label":"Bksp", "x":14, "y":0}, {"label":"Tab", "x":0, "y":1, "w":1.5}, {"label":"Q", "x":1.5, "y":1}, {"label":"W", "x":2.5, "y":1}, {"label":"E", "x":3.5, "y":1}, {"label":"R", "x":4.5, "y":1}, {"label":"T", "x":5.5, "y":1}, {"label":"Y", "x":6.5, "y":1}, {"label":"U", "x":7.5, "y":1}, {"label":"I", "x":8.5, "y":1}, {"label":"O", "x":9.5, "y":1}, {"label":"P", "x":10.5, "y":1}, {"label":"{", "x":11.5, "y":1}, {"label":"}", "x":12.5, "y":1}, {"label":"|", "x":13.5, "y":1, "w":1.5}, {"label":"Caps Lock", "x":0, "y":2, "w":1.75}, {"label":"A", "x":1.75, "y":2}, {"label":"S", "x":2.75, "y":2}, {"label":"D", "x":3.75, "y":2}, {"label":"F", "x":4.75, "y":2}, {"label":"G", "x":5.75, "y":2}, {"label":"H", "x":6.75, "y":2}, {"label":"J", "x":7.75, "y":2}, {"label":"K", "x":8.75, "y":2}, {"label":"L", "x":9.75, "y":2}, {"label":":", "x":10.75, "y":2}, {"label":"\"", "x":11.75, "y":2}, {"label":"Enter", "x":12.75, "y":2, "w":2.25}, {"label":"Shift", "x":0, "y":3, "w":2.25}, {"label":"Z", "x":2.25, "y":3}, {"label":"X", "x":3.25, "y":3}, {"label":"C", "x":4.25, "y":3}, {"label":"V", "x":5.25, "y":3}, {"label":"B", "x":6.25, "y":3}, {"label":"N", "x":7.25, "y":3}, {"label":"M", "x":8.25, "y":3}, {"label":"<", "x":9.25, "y":3}, {"label":">", "x":10.25, "y":3}, {"label":"?", "x":11.25, "y":3}, {"label":"Shift", "x":12.25, "y":3, "w":1.75}, {"label":"Fn", "x":14, "y":3}, {"label":"Ctrl", "x":0, "y":4, "w":1.5}, {"label":"Win", "x":1.5, "y":4}, {"label":"Alt", "x":2.5, "y":4, "w":1.5}, {"x":4, "y":4, "w":3}, {"x":7, "y":4}, {"x":8, "y":4, "w":3}, {"label":"Alt", "x":11, "y":4, "w":1.5}, {"label":"Win", "x":12.5, "y":4}, {"label":"Ctrl", "x":13.5, "y":4, "w":1.5}] 9 "layout": [
10 { "label": "Esc", "x": 0, "y": 0 },
11 { "label": "!", "x": 1, "y": 0 },
12 { "label": "@", "x": 2, "y": 0 },
13 { "label": "#", "x": 3, "y": 0 },
14 { "label": "$", "x": 4, "y": 0 },
15 { "label": "%", "x": 5, "y": 0 },
16 { "label": "^", "x": 6, "y": 0 },
17 { "label": "&", "x": 7, "y": 0 },
18 { "label": "*", "x": 8, "y": 0 },
19 { "label": "(", "x": 9, "y": 0 },
20 { "label": ")", "x": 10, "y": 0 },
21 { "label": "_", "x": 11, "y": 0 },
22 { "label": "+", "x": 12, "y": 0 },
23 { "label": "~", "x": 13, "y": 0 },
24 { "label": "Bksp", "x": 14, "y": 0 },
25 { "label": "Tab", "w": 1.5, "x": 0, "y": 1 },
26 { "label": "Q", "x": 1.5, "y": 1 },
27 { "label": "W", "x": 2.5, "y": 1 },
28 { "label": "E", "x": 3.5, "y": 1 },
29 { "label": "R", "x": 4.5, "y": 1 },
30 { "label": "T", "x": 5.5, "y": 1 },
31 { "label": "Y", "x": 6.5, "y": 1 },
32 { "label": "U", "x": 7.5, "y": 1 },
33 { "label": "I", "x": 8.5, "y": 1 },
34 { "label": "O", "x": 9.5, "y": 1 },
35 { "label": "P", "x": 10.5, "y": 1 },
36 { "label": "{", "x": 11.5, "y": 1 },
37 { "label": "}", "x": 12.5, "y": 1 },
38 { "label": "|", "w": 1.5, "x": 13.5, "y": 1 },
39 { "label": "Caps Lock", "w": 1.75, "x": 0, "y": 2 },
40 { "label": "A", "x": 1.75, "y": 2 },
41 { "label": "S", "x": 2.75, "y": 2 },
42 { "label": "D", "x": 3.75, "y": 2 },
43 { "label": "F", "x": 4.75, "y": 2 },
44 { "label": "G", "x": 5.75, "y": 2 },
45 { "label": "H", "x": 6.75, "y": 2 },
46 { "label": "J", "x": 7.75, "y": 2 },
47 { "label": "K", "x": 8.75, "y": 2 },
48 { "label": "L", "x": 9.75, "y": 2 },
49 { "label": ":", "x": 10.75, "y": 2 },
50 { "label": "\"", "x": 11.75, "y": 2 },
51 { "label": "Enter", "w": 2.25, "x": 12.75, "y": 2 },
52 { "label": "Shift", "w": 2.25, "x": 0, "y": 3 },
53 { "label": "Z", "x": 2.25, "y": 3 },
54 { "label": "X", "x": 3.25, "y": 3 },
55 { "label": "C", "x": 4.25, "y": 3 },
56 { "label": "V", "x": 5.25, "y": 3 },
57 { "label": "B", "x": 6.25, "y": 3 },
58 { "label": "N", "x": 7.25, "y": 3 },
59 { "label": "M", "x": 8.25, "y": 3 },
60 { "label": "<", "x": 9.25, "y": 3 },
61 { "label": ">", "x": 10.25, "y": 3 },
62 { "label": "?", "x": 11.25, "y": 3 },
63 { "label": "Shift", "w": 1.75, "x": 12.25, "y": 3 },
64 { "label": "Fn", "x": 14, "y": 3 },
65 { "label": "Ctrl", "w": 1.5, "x": 0, "y": 4 },
66 { "label": "Win", "x": 1.5, "y": 4 },
67 { "label": "Alt", "w": 1.5, "x": 2.5, "y": 4 },
68 { "w": 7, "x": 4, "y": 4 },
69 { "label": "Alt", "w": 1.5, "x": 11, "y": 4 },
70 { "label": "Win", "x": 12.5, "y": 4 },
71 { "label": "Ctrl", "w": 1.5, "x": 13.5, "y": 4 }
72 ]
10 }, 73 },
11 "LAYOUT": { 74 "LAYOUT_2x3u": {
12 "7u": [{"label":"Esc", "x":0, "y":0}, {"label":"!", "x":1, "y":0}, {"label":"@", "x":2, "y":0}, {"label":"#", "x":3, "y":0}, {"label":"$", "x":4, "y":0}, {"label":"%", "x":5, "y":0}, {"label":"^", "x":6, "y":0}, {"label":"&", "x":7, "y":0}, {"label":"*", "x":8, "y":0}, {"label":"(", "x":9, "y":0}, {"label":")", "x":10, "y":0}, {"label":"_", "x":11, "y":0}, {"label":"+", "x":12, "y":0}, {"label":"~", "x":13, "y":0}, {"label":"Bksp", "x":14, "y":0}, {"label":"Tab", "x":0, "y":1, "w":1.5}, {"label":"Q", "x":1.5, "y":1}, {"label":"W", "x":2.5, "y":1}, {"label":"E", "x":3.5, "y":1}, {"label":"R", "x":4.5, "y":1}, {"label":"T", "x":5.5, "y":1}, {"label":"Y", "x":6.5, "y":1}, {"label":"U", "x":7.5, "y":1}, {"label":"I", "x":8.5, "y":1}, {"label":"O", "x":9.5, "y":1}, {"label":"P", "x":10.5, "y":1}, {"label":"{", "x":11.5, "y":1}, {"label":"}", "x":12.5, "y":1}, {"label":"|", "x":13.5, "y":1, "w":1.5}, {"label":"Caps Lock", "x":0, "y":2, "w":1.75}, {"label":"A", "x":1.75, "y":2}, {"label":"S", "x":2.75, "y":2}, {"label":"D", "x":3.75, "y":2}, {"label":"F", "x":4.75, "y":2}, {"label":"G", "x":5.75, "y":2}, {"label":"H", "x":6.75, "y":2}, {"label":"J", "x":7.75, "y":2}, {"label":"K", "x":8.75, "y":2}, {"label":"L", "x":9.75, "y":2}, {"label":":", "x":10.75, "y":2}, {"label":"\"", "x":11.75, "y":2}, {"label":"Enter", "x":12.75, "y":2, "w":2.25}, {"label":"Shift", "x":0, "y":3, "w":2.25}, {"label":"Z", "x":2.25, "y":3}, {"label":"X", "x":3.25, "y":3}, {"label":"C", "x":4.25, "y":3}, {"label":"V", "x":5.25, "y":3}, {"label":"B", "x":6.25, "y":3}, {"label":"N", "x":7.25, "y":3}, {"label":"M", "x":8.25, "y":3}, {"label":"<", "x":9.25, "y":3}, {"label":">", "x":10.25, "y":3}, {"label":"?", "x":11.25, "y":3}, {"label":"Shift", "x":12.25, "y":3, "w":1.75}, {"label":"Fn", "x":14, "y":3}, {"label":"Ctrl", "x":0, "y":4, "w":1.5}, {"label":"Win", "x":1.5, "y":4}, {"label":"Alt", "x":2.5, "y":4, "w":1.5}, {"x":4, "y":4, "w":7}, {"label":"Alt", "x":11, "y":4, "w":1.5}, {"label":"Win", "x":12.5, "y":4}, {"label":"Ctrl", "x":13.5, "y":4, "w":1.5}] 75 "layout": [
76 { "label": "Esc", "x": 0, "y": 0 },
77 { "label": "!", "x": 1, "y": 0 },
78 { "label": "@", "x": 2, "y": 0 },
79 { "label": "#", "x": 3, "y": 0 },
80 { "label": "$", "x": 4, "y": 0 },
81 { "label": "%", "x": 5, "y": 0 },
82 { "label": "^", "x": 6, "y": 0 },
83 { "label": "&", "x": 7, "y": 0 },
84 { "label": "*", "x": 8, "y": 0 },
85 { "label": "(", "x": 9, "y": 0 },
86 { "label": ")", "x": 10, "y": 0 },
87 { "label": "_", "x": 11, "y": 0 },
88 { "label": "+", "x": 12, "y": 0 },
89 { "label": "~", "x": 13, "y": 0 },
90 { "label": "Bksp", "x": 14, "y": 0 },
91 { "label": "Tab", "w": 1.5, "x": 0, "y": 1 },
92 { "label": "Q", "x": 1.5, "y": 1 },
93 { "label": "W", "x": 2.5, "y": 1 },
94 { "label": "E", "x": 3.5, "y": 1 },
95 { "label": "R", "x": 4.5, "y": 1 },
96 { "label": "T", "x": 5.5, "y": 1 },
97 { "label": "Y", "x": 6.5, "y": 1 },
98 { "label": "U", "x": 7.5, "y": 1 },
99 { "label": "I", "x": 8.5, "y": 1 },
100 { "label": "O", "x": 9.5, "y": 1 },
101 { "label": "P", "x": 10.5, "y": 1 },
102 { "label": "{", "x": 11.5, "y": 1 },
103 { "label": "}", "x": 12.5, "y": 1 },
104 { "label": "|", "w": 1.5, "x": 13.5, "y": 1 },
105 { "label": "Caps Lock", "w": 1.75, "x": 0, "y": 2 },
106 { "label": "A", "x": 1.75, "y": 2 },
107 { "label": "S", "x": 2.75, "y": 2 },
108 { "label": "D", "x": 3.75, "y": 2 },
109 { "label": "F", "x": 4.75, "y": 2 },
110 { "label": "G", "x": 5.75, "y": 2 },
111 { "label": "H", "x": 6.75, "y": 2 },
112 { "label": "J", "x": 7.75, "y": 2 },
113 { "label": "K", "x": 8.75, "y": 2 },
114 { "label": "L", "x": 9.75, "y": 2 },
115 { "label": ":", "x": 10.75, "y": 2 },
116 { "label": "\"", "x": 11.75, "y": 2 },
117 { "label": "Enter", "w": 2.25, "x": 12.75, "y": 2 },
118 { "label": "Shift", "w": 2.25, "x": 0, "y": 3 },
119 { "label": "Z", "x": 2.25, "y": 3 },
120 { "label": "X", "x": 3.25, "y": 3 },
121 { "label": "C", "x": 4.25, "y": 3 },
122 { "label": "V", "x": 5.25, "y": 3 },
123 { "label": "B", "x": 6.25, "y": 3 },
124 { "label": "N", "x": 7.25, "y": 3 },
125 { "label": "M", "x": 8.25, "y": 3 },
126 { "label": "<", "x": 9.25, "y": 3 },
127 { "label": ">", "x": 10.25, "y": 3 },
128 { "label": "?", "x": 11.25, "y": 3 },
129 { "label": "Shift", "w": 1.75, "x": 12.25, "y": 3 },
130 { "label": "Fn", "x": 14, "y": 3 },
131 { "label": "Ctrl", "w": 1.5, "x": 0, "y": 4 },
132 { "label": "Win", "x": 1.5, "y": 4 },
133 { "label": "Alt", "w": 1.5, "x": 2.5, "y": 4 },
134 { "w": 3, "x": 4, "y": 4 },
135 { "x": 7, "y": 4 },
136 { "w": 3, "x": 8, "y": 4 },
137 { "label": "Alt", "w": 1.5, "x": 11, "y": 4 },
138 { "label": "Win", "x": 12.5, "y": 4 },
139 { "label": "Ctrl", "w": 1.5, "x": 13.5, "y": 4 }
140 ]
13 } 141 }
14 } 142 }
15} 143}
diff --git a/keyboards/crkbd/keymaps/devdev/config.h b/keyboards/crkbd/keymaps/devdev/config.h
index 793c7b020..c858f8f2d 100644
--- a/keyboards/crkbd/keymaps/devdev/config.h
+++ b/keyboards/crkbd/keymaps/devdev/config.h
@@ -32,7 +32,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
32 32
33#define CUSTOM_FONT 33#define CUSTOM_FONT
34 34
35#define CUSTOM_LAYER_READ //if you remove this it causes issues - needs better guarding 35#define CUSTOM_LAYER_READ //if you remove this it causes issues - needs better guarding
36 36
37#define TAPPING_FORCE_HOLD 37#define TAPPING_FORCE_HOLD
38#define TAPPING_TERM 200 38#define TAPPING_TERM 200
@@ -43,7 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
43 43
44#ifdef RGBLIGHT_ENABLE 44#ifdef RGBLIGHT_ENABLE
45 #undef RGBLED_NUM 45 #undef RGBLED_NUM
46 46
47 //#define RGBLIGHT_ANIMATIONS 47 //#define RGBLIGHT_ANIMATIONS
48 #define RGBLIGHT_EFFECT_BREATHING 48 #define RGBLIGHT_EFFECT_BREATHING
49 #define RGBLIGHT_EFFECT_RAINBOW_MOOD 49 #define RGBLIGHT_EFFECT_RAINBOW_MOOD
@@ -55,11 +55,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
55 //#define RGBLIGHT_EFFECT_RGB_TEST 55 //#define RGBLIGHT_EFFECT_RGB_TEST
56 //#define RGBLIGHT_EFFECT_ALTERNATING 56 //#define RGBLIGHT_EFFECT_ALTERNATING
57 //#define RGBLIGHT_EFFECT_TWINKLE 57 //#define RGBLIGHT_EFFECT_TWINKLE
58 58
59 //#define RGBLED_NUM 54 59 //#define RGBLED_NUM 54
60 //#define RGBLED_SPLIT 27 60 //#define RGBLED_SPLIT 27
61 //#define RGBLED_SPLIT { 27, 27 } // haven't figured out how to use this yet 61 //#define RGBLED_SPLIT { 27, 27 } // haven't figured out how to use this yet
62 62
63 #define RGBLED_NUM 27 63 #define RGBLED_NUM 27
64 #define RGBLIGHT_LIMIT_VAL 120 64 #define RGBLIGHT_LIMIT_VAL 120
65 #define RGBLIGHT_HUE_STEP 10 65 #define RGBLIGHT_HUE_STEP 10
@@ -71,11 +71,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
71# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 71# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
72// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 72// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
73// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 73// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
74# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 74# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
75# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 75# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
76// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 76// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
77// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 77// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
78# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash. 78# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
79 79
80#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_GRADIENT_LEFT_RIGHT 80#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_GRADIENT_LEFT_RIGHT
81 81
diff --git a/keyboards/crkbd/keymaps/gotham/config.h b/keyboards/crkbd/keymaps/gotham/config.h
index dd58a0fe0..05b04e0aa 100644
--- a/keyboards/crkbd/keymaps/gotham/config.h
+++ b/keyboards/crkbd/keymaps/gotham/config.h
@@ -39,7 +39,7 @@
39 39
40#ifdef RGB_MATRIX_ENABLE 40#ifdef RGB_MATRIX_ENABLE
41# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 41# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
42# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 42# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
43# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash. 43# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
44# define RGB_MATRIX_HUE_STEP 32 44# define RGB_MATRIX_HUE_STEP 32
45# define RGB_MATRIX_SAT_STEP 64 45# define RGB_MATRIX_SAT_STEP 64
diff --git a/keyboards/crkbd/keymaps/kidbrazil/config.h b/keyboards/crkbd/keymaps/kidbrazil/config.h
index be1777e57..752ea862e 100644
--- a/keyboards/crkbd/keymaps/kidbrazil/config.h
+++ b/keyboards/crkbd/keymaps/kidbrazil/config.h
@@ -56,7 +56,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
56 //# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 56 //# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
57 // # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 57 // # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
58 // # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 58 // # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
59 #define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 59 #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
60 #define RGB_MATRIX_FRAMEBUFFER_EFFECTS 60 #define RGB_MATRIX_FRAMEBUFFER_EFFECTS
61 // # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 61 // # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
62 // # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 62 // # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
diff --git a/keyboards/crkbd/keymaps/rpbaptist/config.h b/keyboards/crkbd/keymaps/rpbaptist/config.h
index 6bd16725f..9e5f75c36 100644
--- a/keyboards/crkbd/keymaps/rpbaptist/config.h
+++ b/keyboards/crkbd/keymaps/rpbaptist/config.h
@@ -42,7 +42,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
42#define NO_ACTION_ONESHOT 42#define NO_ACTION_ONESHOT
43 43
44#ifdef RGB_MATRIX_ENABLE 44#ifdef RGB_MATRIX_ENABLE
45# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 45# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
46# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 46# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150
47 47
48# define RGB_MATRIX_HUE_STEP 8 48# define RGB_MATRIX_HUE_STEP 8
diff --git a/keyboards/crkbd/keymaps/soundmonster/config.h b/keyboards/crkbd/keymaps/soundmonster/config.h
index 1e58af3ab..8235b4869 100644
--- a/keyboards/crkbd/keymaps/soundmonster/config.h
+++ b/keyboards/crkbd/keymaps/soundmonster/config.h
@@ -59,11 +59,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
59# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 59# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
60// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 60// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
61// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 61// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
62# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 62# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
63# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 63# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
64# define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 64# define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
65# define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 65# define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
66# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash. 66# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
67# define RGB_MATRIX_HUE_STEP 8 67# define RGB_MATRIX_HUE_STEP 8
68# define RGB_MATRIX_SAT_STEP 8 68# define RGB_MATRIX_SAT_STEP 8
69# define RGB_MATRIX_VAL_STEP 8 69# define RGB_MATRIX_VAL_STEP 8
diff --git a/keyboards/crkbd/readme.md b/keyboards/crkbd/readme.md
index 1e5bfb39a..f0b5672cf 100644
--- a/keyboards/crkbd/readme.md
+++ b/keyboards/crkbd/readme.md
@@ -38,7 +38,7 @@ And in your `config.h` file, add the following:
38# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 38# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
39// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 39// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
40// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 40// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
41# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 41# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
42# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 42# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
43// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 43// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
44// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 44// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
diff --git a/keyboards/draculad/config.h b/keyboards/draculad/config.h
index 8a27fdea4..d8a9fbd37 100644
--- a/keyboards/draculad/config.h
+++ b/keyboards/draculad/config.h
@@ -65,3 +65,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
65#define UNUSED_PINS 65#define UNUSED_PINS
66 66
67#define EE_HANDS 67#define EE_HANDS
68
69#define LAYER_STATE_8BIT \ No newline at end of file
diff --git a/keyboards/draculad/keymaps/pimoroni/keymap.c b/keyboards/draculad/keymaps/pimoroni/keymap.c
index 87cbe3cd3..762ae26c7 100644
--- a/keyboards/draculad/keymaps/pimoroni/keymap.c
+++ b/keyboards/draculad/keymaps/pimoroni/keymap.c
@@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17 17
18#include QMK_KEYBOARD_H 18#include QMK_KEYBOARD_H
19#include "pimoroni_trackball.h" 19#include "drivers/sensors/pimoroni_trackball.h"
20#include "pointing_device.h" 20#include "pointing_device.h"
21 21
22 22
diff --git a/keyboards/draculad/keymaps/pimoroni/pimoroni_trackball.h b/keyboards/draculad/keymaps/pimoroni/pimoroni_trackball.h
deleted file mode 100644
index cfcd5a47a..000000000
--- a/keyboards/draculad/keymaps/pimoroni/pimoroni_trackball.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include "quantum.h"
20#include "pointing_device.h"
21
22#ifndef TRACKBALL_ADDRESS
23# define TRACKBALL_ADDRESS 0x0A
24#endif
25#define TRACKBALL_WRITE ((TRACKBALL_ADDRESS << 1) | I2C_WRITE)
26#define TRACKBALL_READ ((TRACKBALL_ADDRESS << 1) | I2C_READ)
27
28void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
29void trackball_check_click(bool pressed, report_mouse_t *mouse);
30void trackball_register_button(bool pressed, enum mouse_buttons button);
31
32float trackball_get_precision(void);
33void trackball_set_precision(float precision);
34bool trackball_is_scrolling(void);
35void trackball_set_scrolling(bool scroll); \ No newline at end of file
diff --git a/keyboards/draculad/keymaps/pimoroni/rules.mk b/keyboards/draculad/keymaps/pimoroni/rules.mk
index 547a02f26..d8dc92fbf 100644
--- a/keyboards/draculad/keymaps/pimoroni/rules.mk
+++ b/keyboards/draculad/keymaps/pimoroni/rules.mk
@@ -1,6 +1,6 @@
1# only uncomment on the side you have your trackball on 1# only uncomment on the side you have your trackball on
2POINTING_DEVICE_ENABLE = yes 2POINTING_DEVICE_ENABLE = yes
3SRC += pimoroni_trackball.c 3SRC += drivers/sensors/pimoroni_trackball.c
4QUANTUM_LIB_SRC += i2c_master.c 4QUANTUM_LIB_SRC += i2c_master.c
5OLED_DRIVER_ENABLE = yes 5OLED_DRIVER_ENABLE = yes
6MOUSEKEY_ENABLE = no 6MOUSEKEY_ENABLE = no
diff --git a/keyboards/dztech/dz60rgb/v1/config.h b/keyboards/dztech/dz60rgb/v1/config.h
index 6e5b3da6f..f6ee7c4e2 100644
--- a/keyboards/dztech/dz60rgb/v1/config.h
+++ b/keyboards/dztech/dz60rgb/v1/config.h
@@ -37,7 +37,7 @@
37 37
38#ifdef RGB_MATRIX_ENABLE 38#ifdef RGB_MATRIX_ENABLE
39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41# define RGB_MATRIX_KEYPRESSES 41# define RGB_MATRIX_KEYPRESSES
42# define RGB_MATRIX_LED_PROCESS_LIMIT 4 42# define RGB_MATRIX_LED_PROCESS_LIMIT 4
43# define RGB_MATRIX_LED_FLUSH_LIMIT 26 43# define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/dztech/dz60rgb/v2/config.h b/keyboards/dztech/dz60rgb/v2/config.h
index df84fff59..6108e9903 100644
--- a/keyboards/dztech/dz60rgb/v2/config.h
+++ b/keyboards/dztech/dz60rgb/v2/config.h
@@ -37,7 +37,7 @@
37 37
38#ifdef RGB_MATRIX_ENABLE 38#ifdef RGB_MATRIX_ENABLE
39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41# define RGB_MATRIX_KEYPRESSES 41# define RGB_MATRIX_KEYPRESSES
42# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 42# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
43# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 43# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
diff --git a/keyboards/dztech/dz60rgb_ansi/v1/config.h b/keyboards/dztech/dz60rgb_ansi/v1/config.h
index 8710f8d07..dc2a6f4bc 100644
--- a/keyboards/dztech/dz60rgb_ansi/v1/config.h
+++ b/keyboards/dztech/dz60rgb_ansi/v1/config.h
@@ -37,7 +37,7 @@
37 37
38#ifdef RGB_MATRIX_ENABLE 38#ifdef RGB_MATRIX_ENABLE
39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41# define RGB_MATRIX_KEYPRESSES 41# define RGB_MATRIX_KEYPRESSES
42# define RGB_MATRIX_LED_PROCESS_LIMIT 4 42# define RGB_MATRIX_LED_PROCESS_LIMIT 4
43# define RGB_MATRIX_LED_FLUSH_LIMIT 26 43# define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/dztech/dz60rgb_ansi/v2/config.h b/keyboards/dztech/dz60rgb_ansi/v2/config.h
index f3c9b73fb..6c1e00682 100644
--- a/keyboards/dztech/dz60rgb_ansi/v2/config.h
+++ b/keyboards/dztech/dz60rgb_ansi/v2/config.h
@@ -37,7 +37,7 @@
37 37
38#ifdef RGB_MATRIX_ENABLE 38#ifdef RGB_MATRIX_ENABLE
39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41# define RGB_MATRIX_KEYPRESSES 41# define RGB_MATRIX_KEYPRESSES
42# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 42# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
43# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 43# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
diff --git a/keyboards/dztech/dz60rgb_wkl/v1/config.h b/keyboards/dztech/dz60rgb_wkl/v1/config.h
index 9c630c75b..12317c2d3 100644
--- a/keyboards/dztech/dz60rgb_wkl/v1/config.h
+++ b/keyboards/dztech/dz60rgb_wkl/v1/config.h
@@ -37,7 +37,7 @@
37 37
38#ifdef RGB_MATRIX_ENABLE 38#ifdef RGB_MATRIX_ENABLE
39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41# define RGB_MATRIX_KEYPRESSES 41# define RGB_MATRIX_KEYPRESSES
42# define RGB_MATRIX_LED_PROCESS_LIMIT 4 42# define RGB_MATRIX_LED_PROCESS_LIMIT 4
43# define RGB_MATRIX_LED_FLUSH_LIMIT 26 43# define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/dztech/dz60rgb_wkl/v2/config.h b/keyboards/dztech/dz60rgb_wkl/v2/config.h
index a6145c274..945b591ce 100644
--- a/keyboards/dztech/dz60rgb_wkl/v2/config.h
+++ b/keyboards/dztech/dz60rgb_wkl/v2/config.h
@@ -37,7 +37,7 @@
37 37
38#ifdef RGB_MATRIX_ENABLE 38#ifdef RGB_MATRIX_ENABLE
39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41# define RGB_MATRIX_KEYPRESSES 41# define RGB_MATRIX_KEYPRESSES
42# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 42# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
43# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 43# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
diff --git a/keyboards/dztech/dz65rgb/v1/config.h b/keyboards/dztech/dz65rgb/v1/config.h
index adfa934b0..1ecd9002c 100644
--- a/keyboards/dztech/dz65rgb/v1/config.h
+++ b/keyboards/dztech/dz65rgb/v1/config.h
@@ -51,9 +51,9 @@
51# define RGB_MATRIX_LED_FLUSH_LIMIT 26 51# define RGB_MATRIX_LED_FLUSH_LIMIT 26
52# define DEBOUNCE 3 52# define DEBOUNCE 3
53# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 53# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
54# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 54# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
55# define RGB_MATRIX_KEYPRESSES 55# define RGB_MATRIX_KEYPRESSES
56# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 56# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
57# define DISABLE_RGB_MATRIX_BAND_SAT 57# define DISABLE_RGB_MATRIX_BAND_SAT
58# define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT 58# define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
59# define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT 59# define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
diff --git a/keyboards/dztech/dz65rgb/v2/config.h b/keyboards/dztech/dz65rgb/v2/config.h
index f86d65cd0..1e1e21f5e 100644
--- a/keyboards/dztech/dz65rgb/v2/config.h
+++ b/keyboards/dztech/dz65rgb/v2/config.h
@@ -51,7 +51,7 @@
51# define RGB_MATRIX_LED_FLUSH_LIMIT 26 51# define RGB_MATRIX_LED_FLUSH_LIMIT 26
52# define DEBOUNCE 3 52# define DEBOUNCE 3
53# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 53# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
54# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 54# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
55# define RGB_MATRIX_KEYPRESSES 55# define RGB_MATRIX_KEYPRESSES
56# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 56# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
57# define DISABLE_RGB_MATRIX_BAND_SAT 57# define DISABLE_RGB_MATRIX_BAND_SAT
diff --git a/keyboards/ergodox_ez/config.h b/keyboards/ergodox_ez/config.h
index bc63f6108..9dcfc341e 100644
--- a/keyboards/ergodox_ez/config.h
+++ b/keyboards/ergodox_ez/config.h
@@ -129,7 +129,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
129#define RGB_MATRIX_LED_PROCESS_LIMIT 5 129#define RGB_MATRIX_LED_PROCESS_LIMIT 5
130#define RGB_MATRIX_LED_FLUSH_LIMIT 26 130#define RGB_MATRIX_LED_FLUSH_LIMIT 26
131 131
132#define RGB_DISABLE_WHEN_USB_SUSPENDED true 132#define RGB_DISABLE_WHEN_USB_SUSPENDED
133 133
134// #define RGBLIGHT_COLOR_LAYER_0 0x00, 0x00, 0xFF 134// #define RGBLIGHT_COLOR_LAYER_0 0x00, 0x00, 0xFF
135/* #define RGBLIGHT_COLOR_LAYER_1 0x00, 0x00, 0xFF */ 135/* #define RGBLIGHT_COLOR_LAYER_1 0x00, 0x00, 0xFF */
diff --git a/keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h b/keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h
index a0ba655ed..da2082078 100644
--- a/keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h
+++ b/keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h
@@ -14,7 +14,7 @@
14#undef IGNORE_MOD_TAP_INTERRUPT 14#undef IGNORE_MOD_TAP_INTERRUPT
15#define IGNORE_MOD_TAP_INTERRUPT 15#define IGNORE_MOD_TAP_INTERRUPT
16 16
17#define RGB_DISABLE_WHEN_USB_SUSPENDED true 17#define RGB_DISABLE_WHEN_USB_SUSPENDED
18 18
19#undef FORCE_NKRO 19#undef FORCE_NKRO
20#define FORCE_NKRO 20#define FORCE_NKRO
diff --git a/keyboards/ergodox_infinity/config.h b/keyboards/ergodox_infinity/config.h
index a64f3f4a1..a00c593ee 100644
--- a/keyboards/ergodox_infinity/config.h
+++ b/keyboards/ergodox_infinity/config.h
@@ -62,6 +62,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
62#define LED_BRIGHTNESS_LO 100 62#define LED_BRIGHTNESS_LO 100
63#define LED_BRIGHTNESS_HI 255 63#define LED_BRIGHTNESS_HI 255
64 64
65/* LED matrix driver */
66#define LED_DRIVER_ADDR_1 0x74
67#define LED_DRIVER_COUNT 1
68#define DRIVER_LED_TOTAL 76
69#define LED_MATRIX_SPLIT { 38, 38 }
70#define LED_DISABLE_WHEN_USB_SUSPENDED
71
72/* i2c (for LED matrix) */
73#define I2C1_CLOCK_SPEED 400000
74#define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATIVE_2
75#define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATIVE_2
76#define I2C1_BANK GPIOB
77#define I2C1_SCL 0
78#define I2C1_SDA 1
79
65/* define if matrix has ghost */ 80/* define if matrix has ghost */
66//#define MATRIX_HAS_GHOST 81//#define MATRIX_HAS_GHOST
67 82
diff --git a/keyboards/ergodox_infinity/ergodox_infinity.c b/keyboards/ergodox_infinity/ergodox_infinity.c
index 97b628470..da8ea311a 100644
--- a/keyboards/ergodox_infinity/ergodox_infinity.c
+++ b/keyboards/ergodox_infinity/ergodox_infinity.c
@@ -1,20 +1,45 @@
1#include QMK_KEYBOARD_H 1#include QMK_KEYBOARD_H
2#include <ch.h> 2#include <ch.h>
3#include <hal.h> 3#include <hal.h>
4#include <string.h>
5#include "eeconfig.h"
4#include "serial_link/system/serial_link.h" 6#include "serial_link/system/serial_link.h"
5#ifdef VISUALIZER_ENABLE 7#ifdef VISUALIZER_ENABLE
6#include "lcd_backlight.h" 8# include "lcd_backlight.h"
7#endif 9#endif
8 10
9#ifdef WPM_ENABLE 11#if (defined(LED_MATRIX_ENABLE) || defined(WPM_ENABLE))
10# include "serial_link/protocol/transport.h" 12# include "serial_link/protocol/transport.h"
11# include "wpm.h" 13
14# ifdef LED_MATRIX_ENABLE
15MASTER_TO_ALL_SLAVES_OBJECT(led_matrix, led_eeconfig_t);
16MASTER_TO_ALL_SLAVES_OBJECT(led_suspend_state, bool);
17static led_eeconfig_t last_sent_led_matrix;
18static uint16_t led_matrix_sent_timer = 0;
19
20void send_led_suspend_state(void) {
21 if (is_serial_link_master()) {
22 *begin_write_led_suspend_state() = led_matrix_get_suspend_state();
23 end_write_led_suspend_state();
24 }
25}
26# endif
12 27
28# ifdef WPM_ENABLE
29# include "wpm.h"
13MASTER_TO_ALL_SLAVES_OBJECT(current_wpm, uint8_t); 30MASTER_TO_ALL_SLAVES_OBJECT(current_wpm, uint8_t);
14static remote_object_t* remote_objects[] = { 31static uint8_t last_sent_wpm = 0;
32# endif
33
34static remote_object_t *remote_objects[] = {
35# ifdef LED_MATRIX_ENABLE
36 REMOTE_OBJECT(led_matrix),
37 REMOTE_OBJECT(led_suspend_state),
38# endif
39# ifdef WPM_ENABLE
15 REMOTE_OBJECT(current_wpm), 40 REMOTE_OBJECT(current_wpm),
41# endif
16}; 42};
17static uint8_t last_sent_wpm = 0;
18#endif 43#endif
19 44
20void init_serial_link_hal(void) { 45void init_serial_link_hal(void) {
@@ -52,7 +77,7 @@ void init_serial_link_hal(void) {
52void lcd_backlight_hal_init(void) { 77void lcd_backlight_hal_init(void) {
53 // Setup Backlight 78 // Setup Backlight
54 SIM->SCGC6 |= SIM_SCGC6_FTM0; 79 SIM->SCGC6 |= SIM_SCGC6_FTM0;
55 FTM0->CNT = 0; // Reset counter 80 FTM0->CNT = 0; // Reset counter
56 81
57 // PWM Period 82 // PWM Period
58 // 16-bit maximum 83 // 16-bit maximum
@@ -60,25 +85,25 @@ void lcd_backlight_hal_init(void) {
60 85
61 // Set FTM to PWM output - Edge Aligned, Low-true pulses 86 // Set FTM to PWM output - Edge Aligned, Low-true pulses
62#define CNSC_MODE FTM_SC_CPWMS | FTM_SC_PS(4) | FTM_SC_CLKS(0) 87#define CNSC_MODE FTM_SC_CPWMS | FTM_SC_PS(4) | FTM_SC_CLKS(0)
63 CHANNEL_RED.CnSC = CNSC_MODE; 88 CHANNEL_RED.CnSC = CNSC_MODE;
64 CHANNEL_GREEN.CnSC = CNSC_MODE; 89 CHANNEL_GREEN.CnSC = CNSC_MODE;
65 CHANNEL_BLUE.CnSC = CNSC_MODE; 90 CHANNEL_BLUE.CnSC = CNSC_MODE;
66 91
67 // System clock, /w prescalar setting 92 // System clock, /w prescalar setting
68 FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_PS(PRESCALAR_DEFINE); 93 FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_PS(PRESCALAR_DEFINE);
69 94
70 CHANNEL_RED.CnV = 0; 95 CHANNEL_RED.CnV = 0;
71 CHANNEL_GREEN.CnV = 0; 96 CHANNEL_GREEN.CnV = 0;
72 CHANNEL_BLUE.CnV = 0; 97 CHANNEL_BLUE.CnV = 0;
73 98
74 RGB_PORT_GPIO->PDDR |= (1 << RED_PIN); 99 RGB_PORT_GPIO->PDDR |= (1 << RED_PIN);
75 RGB_PORT_GPIO->PDDR |= (1 << GREEN_PIN); 100 RGB_PORT_GPIO->PDDR |= (1 << GREEN_PIN);
76 RGB_PORT_GPIO->PDDR |= (1 << BLUE_PIN); 101 RGB_PORT_GPIO->PDDR |= (1 << BLUE_PIN);
77 102
78#define RGB_MODE PORTx_PCRn_SRE | PORTx_PCRn_DSE | PORTx_PCRn_MUX(4) 103#define RGB_MODE PORTx_PCRn_SRE | PORTx_PCRn_DSE | PORTx_PCRn_MUX(4)
79 RGB_PORT->PCR[RED_PIN] = RGB_MODE; 104 RGB_PORT->PCR[RED_PIN] = RGB_MODE;
80 RGB_PORT->PCR[GREEN_PIN] = RGB_MODE; 105 RGB_PORT->PCR[GREEN_PIN] = RGB_MODE;
81 RGB_PORT->PCR[BLUE_PIN] = RGB_MODE; 106 RGB_PORT->PCR[BLUE_PIN] = RGB_MODE;
82} 107}
83 108
84static uint16_t cie_lightness(uint16_t v) { 109static uint16_t cie_lightness(uint16_t v) {
@@ -89,12 +114,11 @@ static uint16_t cie_lightness(uint16_t v) {
89 // Y = (L* / 902.3) if L* <= 8 114 // Y = (L* / 902.3) if L* <= 8
90 // Y = ((L* + 16) / 116)^3 if L* > 8 115 // Y = ((L* + 16) / 116)^3 if L* > 8
91 116
92 float l = 100.0f * (v / 65535.0f); 117 float l = 100.0f * (v / 65535.0f);
93 float y = 0.0f; 118 float y = 0.0f;
94 if (l <= 8.0f) { 119 if (l <= 8.0f) {
95 y = l / 902.3; 120 y = l / 902.3;
96 } 121 } else {
97 else {
98 y = ((l + 16.0f) / 116.0f); 122 y = ((l + 16.0f) / 116.0f);
99 y = y * y * y; 123 y = y * y * y;
100 if (y > 1.0f) { 124 if (y > 1.0f) {
@@ -105,31 +129,48 @@ static uint16_t cie_lightness(uint16_t v) {
105} 129}
106 130
107void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) { 131void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) {
108 CHANNEL_RED.CnV = cie_lightness(r); 132 CHANNEL_RED.CnV = cie_lightness(r);
109 CHANNEL_GREEN.CnV = cie_lightness(g); 133 CHANNEL_GREEN.CnV = cie_lightness(g);
110 CHANNEL_BLUE.CnV = cie_lightness(b); 134 CHANNEL_BLUE.CnV = cie_lightness(b);
111} 135}
112 136
113__attribute__ ((weak)) 137__attribute__ ((weak)) void matrix_init_user(void) {}
114void matrix_init_user(void) { 138
115} 139__attribute__ ((weak)) void matrix_scan_user(void) {}
116 140
117__attribute__ ((weak))
118void matrix_scan_user(void) {
119}
120 141
142void keyboard_pre_init_kb() {
143#ifdef LED_MATRIX_ENABLE
144 // Turn on LED controller
145 setPinOutput(B16);
146 writePinHigh(B16);
147#endif
148 keyboard_pre_init_user();
149}
121 150
122void matrix_init_kb(void) { 151void matrix_init_kb(void) {
123 // put your keyboard start-up code here 152 // put your keyboard start-up code here
124 // runs once when the firmware starts up 153 // runs once when the firmware starts up
125 154
155#ifdef LED_MATRIX_ENABLE
156 /*
157 * Since K20x is stuck with a 32 byte EEPROM (see tmk_core/common/chibios/eeprom_teensy.c),
158 * and neither led_matrix_eeconfig.speed or .flags fit in this boundary, just force their values to default on boot.
159 */
160# if !defined(LED_MATRIX_STARTUP_SPD)
161# define LED_MATRIX_STARTUP_SPD UINT8_MAX / 2
162# endif
163 led_matrix_set_speed(LED_MATRIX_STARTUP_SPD);
164 led_matrix_set_flags(LED_FLAG_ALL);
165#endif
166
126 matrix_init_user(); 167 matrix_init_user();
127 // The backlight always has to be initialized, otherwise it will stay lit 168 // The backlight always has to be initialized, otherwise it will stay lit
128#ifndef VISUALIZER_ENABLE 169#ifndef VISUALIZER_ENABLE
129 lcd_backlight_hal_init(); 170 lcd_backlight_hal_init();
130#endif 171#endif
131#ifdef WPM_ENABLE 172#if (defined(LED_MATRIX_ENABLE) || defined(WPM_ENABLE))
132 add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*)); 173 add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t *));
133#endif 174#endif
134} 175}
135 176
@@ -137,6 +178,30 @@ void matrix_scan_kb(void) {
137 // put your looping keyboard code here 178 // put your looping keyboard code here
138 // runs every cycle (a lot) 179 // runs every cycle (a lot)
139 180
181#ifdef LED_MATRIX_ENABLE
182 if (is_serial_link_master()) {
183 if (!led_matrix_get_suspend_state()) {
184 if (timer_elapsed(led_matrix_sent_timer) >= 5000 || memcmp((void *)&last_sent_led_matrix, (void *)&led_matrix_eeconfig, sizeof(last_sent_led_matrix))) {
185 led_matrix_sent_timer = timer_read();
186 memcpy((void *)&last_sent_led_matrix, (void *)&led_matrix_eeconfig, sizeof(last_sent_led_matrix));
187 *begin_write_led_matrix() = last_sent_led_matrix;
188 end_write_led_matrix();
189 }
190 }
191 } else if (is_serial_link_connected()) {
192 bool *new_led_suspend_state = read_led_suspend_state();
193 if (new_led_suspend_state) {
194 led_matrix_set_suspend_state(*new_led_suspend_state);
195 }
196 if (!led_matrix_get_suspend_state()) {
197 led_eeconfig_t *new_led_matrix = read_led_matrix();
198 if (new_led_matrix) {
199 memcpy((void *)&led_matrix_eeconfig, (void *)new_led_matrix, sizeof(last_sent_led_matrix));
200 }
201 }
202 }
203#endif
204
140#ifdef WPM_ENABLE 205#ifdef WPM_ENABLE
141 if (is_serial_link_master()) { 206 if (is_serial_link_master()) {
142 uint8_t current_wpm = get_current_wpm(); 207 uint8_t current_wpm = get_current_wpm();
@@ -146,67 +211,68 @@ void matrix_scan_kb(void) {
146 last_sent_wpm = current_wpm; 211 last_sent_wpm = current_wpm;
147 } 212 }
148 } else if (is_serial_link_connected()) { 213 } else if (is_serial_link_connected()) {
149 uint8_t* new_wpm = read_current_wpm(); 214 uint8_t *new_wpm = read_current_wpm();
150 if (new_wpm) { 215 if (new_wpm) {
151 set_current_wpm(*new_wpm); 216 set_current_wpm(*new_wpm);
152 } 217 }
153 } 218 }
154#endif 219#endif
220
155 matrix_scan_user(); 221 matrix_scan_user();
156} 222}
157 223
158bool is_keyboard_master(void) { 224bool is_keyboard_master(void) { return is_serial_link_master(); }
159 return is_serial_link_master();
160}
161 225
162__attribute__ ((weak)) 226bool is_keyboard_left(void) {
163void ergodox_board_led_on(void){ 227#if defined(EE_HANDS)
228 return eeconfig_read_handedness();
229#elif defined(MASTER_IS_ON_RIGHT)
230 return !is_keyboard_master();
231#else
232 return is_keyboard_master();
233#endif
164} 234}
165 235
166__attribute__ ((weak)) 236__attribute__ ((weak)) void ergodox_board_led_on(void) {}
167void ergodox_right_led_1_on(void){
168}
169 237
170__attribute__ ((weak)) 238__attribute__ ((weak)) void ergodox_right_led_1_on(void) {}
171void ergodox_right_led_2_on(void){
172}
173 239
174__attribute__ ((weak)) 240__attribute__ ((weak)) void ergodox_right_led_2_on(void) {}
175void ergodox_right_led_3_on(void){
176}
177 241
178__attribute__ ((weak)) 242__attribute__ ((weak)) void ergodox_right_led_3_on(void) {}
179void ergodox_board_led_off(void){
180}
181 243
182__attribute__ ((weak)) 244__attribute__ ((weak)) void ergodox_board_led_off(void) {}
183void ergodox_right_led_1_off(void){
184}
185 245
186__attribute__ ((weak)) 246__attribute__ ((weak)) void ergodox_right_led_1_off(void) {}
187void ergodox_right_led_2_off(void){
188}
189 247
190__attribute__ ((weak)) 248__attribute__ ((weak)) void ergodox_right_led_2_off(void) {}
191void ergodox_right_led_3_off(void){
192}
193 249
194__attribute__ ((weak)) 250__attribute__ ((weak)) void ergodox_right_led_3_off(void) {}
195void ergodox_right_led_1_set(uint8_t n) {
196}
197 251
198__attribute__ ((weak)) 252__attribute__ ((weak)) void ergodox_right_led_1_set(uint8_t n) {}
199void ergodox_right_led_2_set(uint8_t n) { 253
254__attribute__ ((weak)) void ergodox_right_led_2_set(uint8_t n) {}
255
256__attribute__ ((weak)) void ergodox_right_led_3_set(uint8_t n) {}
257
258void suspend_power_down_kb(void) {
259#ifdef LED_MATRIX_ENABLE
260 send_led_suspend_state();
261#endif
262 suspend_power_down_user();
200} 263}
201 264
202__attribute__ ((weak)) 265void suspend_wakeup_init_kb(void) {
203void ergodox_right_led_3_set(uint8_t n) { 266#ifdef LED_MATRIX_ENABLE
267 send_led_suspend_state();
268#endif
269 suspend_wakeup_init_user();
204} 270}
205 271
206#ifdef SWAP_HANDS_ENABLE 272#ifdef SWAP_HANDS_ENABLE
207__attribute__ ((weak)) 273__attribute__ ((weak))
208const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { 274const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
209 {{0, 9}, {1, 9}, {2, 9}, {3, 9}, {4, 9}}, 275 {{0, 9}, {1, 9}, {2, 9}, {3, 9}, {4, 9}},
210 {{0, 10}, {1, 10}, {2, 10}, {3, 10}, {4, 10}}, 276 {{0, 10}, {1, 10}, {2, 10}, {3, 10}, {4, 10}},
211 {{0, 11}, {1, 11}, {2, 11}, {3, 11}, {4, 11}}, 277 {{0, 11}, {1, 11}, {2, 11}, {3, 11}, {4, 11}},
212 {{0, 12}, {1, 12}, {2, 12}, {3, 12}, {4, 12}}, 278 {{0, 12}, {1, 12}, {2, 12}, {3, 12}, {4, 12}},
@@ -226,3 +292,115 @@ const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
226 {{0, 8}, {1, 8}, {2, 8}, {3, 8}, {4, 8}}, 292 {{0, 8}, {1, 8}, {2, 8}, {3, 8}, {4, 8}},
227}; 293};
228#endif 294#endif
295
296#ifdef LED_MATRIX_ENABLE
297const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
298// The numbers in the comments are the led numbers DXX on the PCB
299/* Refer to IS31 manual for these locations
300 * driver
301 * | LED address
302 * | | */
303// Left half
304// 45 44 43 42 41 40 39
305 { 0, C2_2 }, { 0, C1_2 }, { 0, C5_1 }, { 0, C4_1 }, { 0, C3_1 }, { 0, C2_1 }, { 0, C1_1 },
306// 52 51 50 49 48 47 46
307 { 0, C4_3 }, { 0, C3_3 }, { 0, C2_3 }, { 0, C1_3 }, { 0, C5_2 }, { 0, C4_2 }, { 0, C3_2 },
308// 58 57 56 55 54 53
309 { 0, C5_4 }, { 0, C4_4 }, { 0, C3_4 }, { 0, C2_4 }, { 0, C1_4 }, { 0, C5_3 },
310// 67 66 65 64 63 62 61
311 { 0, C4_6 }, { 0, C3_6 }, { 0, C2_6 }, { 0, C1_6 }, { 0, C5_5 }, { 0, C4_5 }, { 0, C3_5 },
312// 76 75 74 73 72
313 { 0, C4_8 }, { 0, C3_8 }, { 0, C2_8 }, { 0, C1_8 }, { 0, C4_7 },
314// 60 59
315 { 0, C2_5 }, { 0, C1_5 },
316// 68
317 { 0, C5_6 },
318// 71 70 69
319 { 0, C3_7 }, { 0, C2_7 }, { 0, C1_7 },
320// Right half (mirrored)
321// Due to how LED_MATRIX_SPLIT is implemented, only the first half of g_is31_leds is actually used.
322// Luckily, the right half has the same LED pinouts, just mirrored.
323// 45 44 43 42 41 40 39
324 { 0, C2_2 }, { 0, C1_2 }, { 0, C5_1 }, { 0, C4_1 }, { 0, C3_1 }, { 0, C2_1 }, { 0, C1_1 },
325// 52 51 50 49 48 47 46
326 { 0, C4_3 }, { 0, C3_3 }, { 0, C2_3 }, { 0, C1_3 }, { 0, C5_2 }, { 0, C4_2 }, { 0, C3_2 },
327// 58 57 56 55 54 53
328 { 0, C5_4 }, { 0, C4_4 }, { 0, C3_4 }, { 0, C2_4 }, { 0, C1_4 }, { 0, C5_3 },
329// 67 66 65 64 63 62 61
330 { 0, C4_6 }, { 0, C3_6 }, { 0, C2_6 }, { 0, C1_6 }, { 0, C5_5 }, { 0, C4_5 }, { 0, C3_5 },
331// 76 75 74 73 72
332 { 0, C4_8 }, { 0, C3_8 }, { 0, C2_8 }, { 0, C1_8 }, { 0, C4_7 },
333// 60 59
334 { 0, C2_5 }, { 0, C1_5 },
335// 68
336 { 0, C5_6 },
337// 71 70 69
338 { 0, C3_7 }, { 0, C2_7 }, { 0, C1_7 },
339};
340
341led_config_t g_led_config = {
342 {
343 // Key Matrix to LED Index
344 // Left half
345 { NO_LED, NO_LED, NO_LED, 33, 34 },
346 { NO_LED, NO_LED, NO_LED, 32, 37 },
347 { 6, 13, NO_LED, 26, 36 },
348 { 5, 12, 19, 25, 35 },
349 { 4, 11, 18, 24, 31 },
350 { 3, 10, 17, 23, 30 },
351 { 2, 9, 16, 22, 29 },
352 { 1, 8, 15, 21, 28 },
353 { 0, 7, 14, 20, 27 },
354 // Right half
355 { NO_LED, NO_LED, NO_LED, 71, 72 },
356 { NO_LED, NO_LED, NO_LED, 70, 75 },
357 { 44, 51, NO_LED, 64, 74 },
358 { 43, 50, 57, 63, 73 },
359 { 42, 49, 56, 62, 69 },
360 { 41, 48, 55, 61, 68 },
361 { 40, 47, 54, 60, 67 },
362 { 39, 46, 53, 59, 66 },
363 { 38, 45, 52, 58, 65 },
364 }, {
365 // LED Index to Physical Position (assumes a reasonable gap between halves)
366 // Left half
367 { 0, 3 }, { 15, 3 }, { 27, 1 }, { 39, 0 }, { 51, 1 }, { 63, 2 }, { 75, 2 },
368 { 0, 13 }, { 15, 13 }, { 27, 11 }, { 39, 10 }, { 51, 11 }, { 63, 12 }, { 78, 17 },
369 { 0, 23 }, { 15, 23 }, { 27, 21 }, { 39, 20 }, { 51, 21 }, { 63, 22 },
370 { 0, 33 }, { 15, 33 }, { 27, 31 }, { 39, 30 }, { 51, 31 }, { 63, 32 }, { 78, 32 },
371 { 4, 43 }, { 15, 43 }, { 27, 41 }, { 39, 40 }, { 51, 41 },
372 { 89, 41 }, { 100, 46 },
373 { 95, 55 },
374 { 72, 54 }, { 83, 59 }, { 90, 64 },
375 // Right half (mirrored)
376 { 224, 3 }, { 209, 3 }, { 197, 1 }, { 185, 0 }, { 173, 1 }, { 161, 2 }, { 149, 2 },
377 { 224, 13 }, { 209, 13 }, { 197, 11 }, { 185, 10 }, { 173, 11 }, { 161, 12 }, { 146, 17 },
378 { 224, 23 }, { 209, 23 }, { 197, 21 }, { 185, 20 }, { 173, 21 }, { 161, 22 },
379 { 224, 33 }, { 209, 33 }, { 197, 31 }, { 185, 30 }, { 173, 31 }, { 161, 32 }, { 146, 32 },
380 { 220, 43 }, { 209, 43 }, { 197, 41 }, { 185, 40 }, { 173, 41 },
381 { 135, 41 }, { 124, 46 },
382 { 129, 55 },
383 { 152, 54 }, { 141, 59 }, { 134, 64 },
384 }, {
385 // LED Index to Flag
386 // Left half
387 1, 4, 4, 4, 4, 4, 1,
388 1, 4, 4, 4, 4, 4, 1,
389 1, 4, 4, 4, 4, 4,
390 1, 4, 4, 4, 4, 4, 1,
391 1, 1, 1, 1, 1,
392 1, 1,
393 1,
394 1, 1, 1,
395 // Right half (mirrored)
396 1, 4, 4, 4, 4, 4, 1,
397 1, 4, 4, 4, 4, 4, 1,
398 1, 4, 4, 4, 4, 4,
399 1, 4, 4, 4, 4, 4, 1,
400 1, 1, 1, 1, 1,
401 1, 1,
402 1,
403 1, 1, 1,
404 }
405};
406#endif
diff --git a/keyboards/ergodox_infinity/matrix.c b/keyboards/ergodox_infinity/matrix.c
index 7baacd24d..0fca56a97 100644
--- a/keyboards/ergodox_infinity/matrix.c
+++ b/keyboards/ergodox_infinity/matrix.c
@@ -24,7 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
24#include "print.h" 24#include "print.h"
25#include "debug.h" 25#include "debug.h"
26#include "matrix.h" 26#include "matrix.h"
27#include "eeconfig.h" 27#include "keyboard.h"
28#include "serial_link/system/serial_link.h" 28#include "serial_link/system/serial_link.h"
29 29
30 30
@@ -119,15 +119,9 @@ uint8_t matrix_scan(void)
119 } 119 }
120 120
121 uint8_t offset = 0; 121 uint8_t offset = 0;
122#if (defined(EE_HANDS) || defined(MASTER_IS_ON_RIGHT)) 122 if (is_serial_link_master() && !is_keyboard_left()) {
123#ifdef EE_HANDS
124 if (is_serial_link_master() && !eeconfig_read_handedness()) {
125#else
126 if (is_serial_link_master()) {
127#endif
128 offset = MATRIX_ROWS - LOCAL_MATRIX_ROWS; 123 offset = MATRIX_ROWS - LOCAL_MATRIX_ROWS;
129 } 124 }
130#endif
131 125
132 if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { 126 if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
133 for (int row = 0; row < LOCAL_MATRIX_ROWS; row++) { 127 for (int row = 0; row < LOCAL_MATRIX_ROWS; row++) {
@@ -167,17 +161,11 @@ void matrix_print(void)
167 161
168void matrix_set_remote(matrix_row_t* rows, uint8_t index) { 162void matrix_set_remote(matrix_row_t* rows, uint8_t index) {
169 uint8_t offset = 0; 163 uint8_t offset = 0;
170#ifdef EE_HANDS 164 if (is_keyboard_left()) {
171 if (eeconfig_read_handedness()) {
172 offset = LOCAL_MATRIX_ROWS * (index + 1); 165 offset = LOCAL_MATRIX_ROWS * (index + 1);
173 } else { 166 } else {
174 offset = MATRIX_ROWS - LOCAL_MATRIX_ROWS * (index + 2); 167 offset = MATRIX_ROWS - LOCAL_MATRIX_ROWS * (index + 2);
175 } 168 }
176#elif defined(MASTER_IS_ON_RIGHT)
177 offset = MATRIX_ROWS - LOCAL_MATRIX_ROWS * (index + 2);
178#else
179 offset = LOCAL_MATRIX_ROWS * (index + 1);
180#endif
181 for (int row = 0; row < LOCAL_MATRIX_ROWS; row++) { 169 for (int row = 0; row < LOCAL_MATRIX_ROWS; row++) {
182 matrix[offset + row] = rows[row]; 170 matrix[offset + row] = rows[row];
183 } 171 }
diff --git a/keyboards/ergodox_infinity/rules.mk b/keyboards/ergodox_infinity/rules.mk
index b9ead9e87..70bcabe80 100644
--- a/keyboards/ergodox_infinity/rules.mk
+++ b/keyboards/ergodox_infinity/rules.mk
@@ -22,8 +22,6 @@ CUSTOM_MATRIX = yes # Custom matrix file
22SERIAL_LINK_ENABLE = yes 22SERIAL_LINK_ENABLE = yes
23VISUALIZER_ENABLE = yes 23VISUALIZER_ENABLE = yes
24LCD_ENABLE = yes 24LCD_ENABLE = yes
25BACKLIGHT_ENABLE = yes
26BACKLIGHT_DRIVER = custom
27LCD_BACKLIGHT_ENABLE = yes 25LCD_BACKLIGHT_ENABLE = yes
28MIDI_ENABLE = no 26MIDI_ENABLE = no
29RGBLIGHT_ENABLE = no 27RGBLIGHT_ENABLE = no
@@ -32,9 +30,8 @@ LCD_DRIVER = st7565
32LCD_WIDTH = 128 30LCD_WIDTH = 128
33LCD_HEIGHT = 32 31LCD_HEIGHT = 32
34 32
35LED_DRIVER = is31fl3731c 33LED_MATRIX_ENABLE = yes
36LED_WIDTH = 7 34LED_MATRIX_DRIVER = IS31FL3731
37LED_HEIGHT = 7
38 35
39# project specific files 36# project specific files
40SRC = matrix.c \ 37SRC = matrix.c \
diff --git a/keyboards/geekboards/macropad_v2/config.h b/keyboards/geekboards/macropad_v2/config.h
index 5f11cdddb..d0e208f9b 100644
--- a/keyboards/geekboards/macropad_v2/config.h
+++ b/keyboards/geekboards/macropad_v2/config.h
@@ -41,7 +41,7 @@
41#define WS2812_DMA_CHANNEL 3 41#define WS2812_DMA_CHANNEL 3
42 42
43#ifdef RGB_MATRIX_ENABLE 43#ifdef RGB_MATRIX_ENABLE
44#define RGB_MATRIX_KEYPRESSES 44#define RGB_MATRIX_KEYPRESSES
45#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 45#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
46#define DISABLE_RGB_MATRIX_ALPHAS_MODS 46#define DISABLE_RGB_MATRIX_ALPHAS_MODS
47#define DISABLE_RGB_MATRIX_BAND_SAT 47#define DISABLE_RGB_MATRIX_BAND_SAT
@@ -67,7 +67,7 @@
67#define RGB_MATRIX_STARTUP_SPD 30 67#define RGB_MATRIX_STARTUP_SPD 30
68#endif //RGB_MATRIX_ENABLE 68#endif //RGB_MATRIX_ENABLE
69 69
70#define RGB_DISABLE_WHEN_USB_SUSPENDED true 70#define RGB_DISABLE_WHEN_USB_SUSPENDED
71#define WAIT_FOR_USB 71#define WAIT_FOR_USB
72 72
73/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ 73/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
diff --git a/keyboards/geekboards/tester/config.h b/keyboards/geekboards/tester/config.h
index 4f072c0ee..3e3daccd5 100644
--- a/keyboards/geekboards/tester/config.h
+++ b/keyboards/geekboards/tester/config.h
@@ -24,7 +24,7 @@
24#define DEBOUNCE 3 24#define DEBOUNCE 3
25#ifdef RGB_MATRIX_ENABLE 25#ifdef RGB_MATRIX_ENABLE
26#define RGB_DISABLE_AFTER_TIMEOUT 0 26#define RGB_DISABLE_AFTER_TIMEOUT 0
27#define RGB_DISABLE_WHEN_USB_SUSPENDED true 27#define RGB_DISABLE_WHEN_USB_SUSPENDED
28#define RGB_MATRIX_KEYPRESSES 28#define RGB_MATRIX_KEYPRESSES
29#define DISABLE_RGB_MATRIX_SPLASH 29#define DISABLE_RGB_MATRIX_SPLASH
30#define DISABLE_RGB_MATRIX_MULTISPLASH 30#define DISABLE_RGB_MATRIX_MULTISPLASH
@@ -36,4 +36,4 @@
36#define DRIVER_1_LED_TOTAL 8 36#define DRIVER_1_LED_TOTAL 8
37#define DRIVER_2_LED_TOTAL 0 37#define DRIVER_2_LED_TOTAL 0
38#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL) 38#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
39#endif \ No newline at end of file 39#endif
diff --git a/keyboards/gmmk/pro/config.h b/keyboards/gmmk/pro/config.h
index ab3c7a7a2..64062bece 100644
--- a/keyboards/gmmk/pro/config.h
+++ b/keyboards/gmmk/pro/config.h
@@ -46,3 +46,20 @@
46#define LOCKING_SUPPORT_ENABLE 46#define LOCKING_SUPPORT_ENABLE
47/* Locking resynchronize hack */ 47/* Locking resynchronize hack */
48#define LOCKING_RESYNC_ENABLE 48#define LOCKING_RESYNC_ENABLE
49
50/* SPI Config for LED Driver */
51#define SPI_DRIVER SPID1
52#define SPI_SCK_PIN A5
53#define SPI_MOSI_PIN A6
54#define SPI_MISO_PIN A7
55
56#define DRIVER_1_CS B13
57#define DRIVER_2_CS B14
58#define DRIVER_1_EN C13
59#define DRIVER_2_EN C13
60
61#define DRIVER_COUNT 2
62#define DRIVER_1_LED_TOTAL 66
63#define DRIVER_2_LED_TOTAL 32
64#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
65
diff --git a/keyboards/gmmk/pro/halconf.h b/keyboards/gmmk/pro/halconf.h
new file mode 100644
index 000000000..23ecb202a
--- /dev/null
+++ b/keyboards/gmmk/pro/halconf.h
@@ -0,0 +1,7 @@
1#pragma once
2
3#define HAL_USE_SPI TRUE
4#define SPI_USE_WAIT TRUE
5#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
6
7#include_next <halconf.h>
diff --git a/keyboards/gmmk/pro/mcuconf.h b/keyboards/gmmk/pro/mcuconf.h
new file mode 100644
index 000000000..bb1c0acde
--- /dev/null
+++ b/keyboards/gmmk/pro/mcuconf.h
@@ -0,0 +1,6 @@
1#pragma once
2
3#include_next <mcuconf.h>
4
5#undef STM32_SPI_USE_SPI1
6#define STM32_SPI_USE_SPI1 TRUE
diff --git a/keyboards/gmmk/pro/pro.c b/keyboards/gmmk/pro/pro.c
index 816d089a5..9ed7ac886 100644
--- a/keyboards/gmmk/pro/pro.c
+++ b/keyboards/gmmk/pro/pro.c
@@ -14,3 +14,225 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 15 */
16#include "pro.h" 16#include "pro.h"
17
18#ifdef RGB_MATRIX_ENABLE
19led_config_t g_led_config = { {
20 { 4, NO_LED, NO_LED, 95, 65, 79, 5, 28 },
21 { 8, 2, 9, 0, 10, 75, 1, 7 },
22 { 14, 3, 15, NO_LED, 16, 86, 6, 13 },
23 { 20, 18, 21, 23, 22, 94, 12, 19 },
24 { 25, 30, 26, 31, 27, 32, 29, 24 },
25 { 41, 36, 42, 37, 43, 38, 35, 40 },
26 { 46, 89, 47, 34, 48, 72, 78, 45 },
27 { 52, 39, 53, 97, 54, 82, 44, 51 },
28 { 58, 63, 59, 64, NO_LED, 60, 62, 57 },
29 { 11, 90, 55, 17, 33, 49, NO_LED, 69 },
30 { NO_LED, 85, 93, 61, 96, 66, 50, 56 }
31}, {
32 { 0, 0 }, // 0, ESC, k13
33 { 0, 15 }, // 1, ~, k16
34 { 4, 26 }, // 2, Tab, k11
35 { 5, 38 }, // 3, Caps, k21
36 { 9, 49 }, // 4, Sh_L, k00
37 { 2, 61 }, // 5, Ct_L, k06
38 { 18, 0 }, // 6, F1, k26
39 { 14, 15 }, // 7, 1, k17
40 { 22, 26 }, // 8, Q, k10
41 { 25, 38 }, // 9, A, k12
42 { 33, 49 }, // 10, Z, k14
43 { 20, 61 }, // 11, Win_L, k90
44 { 33, 0 }, // 12, F2, k36
45 { 29, 15 }, // 13, 2, k27
46 { 36, 26 }, // 14, W, k20
47 { 40, 38 }, // 15, S, k22
48 { 47, 49 }, // 16, X, k24
49 { 38, 61 }, // 17, Alt_L, k93
50 { 47, 0 }, // 18, F3, k31
51 { 43, 15 }, // 19, 3, k37
52 { 51, 26 }, // 20, E, k30
53 { 54, 38 }, // 21, D, k32
54 { 61, 49 }, // 22, C, k34
55 { 61, 0 }, // 23, F4, k33
56 { 58, 15 }, // 24, 4, k47
57 { 65, 26 }, // 25, R, k40
58 { 69, 38 }, // 26, F, k42
59 { 76, 49 }, // 27, V, k44
60 { 79, 0 }, // 28, F5, k07
61 { 72, 15 }, // 29, 5, k46
62 { 79, 26 }, // 30, T, k41
63 { 83, 38 }, // 31, G, k43
64 { 90, 49 }, // 32, B, k45
65 { 92, 61 }, // 33, SPACE, k94
66 { 94, 0 }, // 34, F6, k63
67 { 87, 15 }, // 35, 6, k56
68 { 94, 26 }, // 36, Y, k51
69 { 98, 38 }, // 37, H, k53
70 { 105, 49 }, // 38, N, k55
71 { 108, 0 }, // 39, F7, k71
72 { 101, 15 }, // 40, 7, k57
73 { 108, 26 }, // 41, U, k50
74 { 112, 38 }, // 42, J, k52
75 { 119, 49 }, // 43, M, k54
76 { 123, 0 }, // 44, F8, k76
77 { 116, 15 }, // 45, 8, k67
78 { 123, 26 }, // 46, I, k60
79 { 126, 38 }, // 47, K, k62
80 { 134, 49 }, // 48, ,, k64
81 { 145, 61 }, // 49, Alt_R, k95
82 { 141, 0 }, // 50, F9, ka6
83 { 130, 15 }, // 51, 9, k77
84 { 137, 26 }, // 52, O, k70
85 { 141, 38 }, // 53, L, k72
86 { 148, 49 }, // 54, ., k74
87 { 159, 61 }, // 55, FN, k92
88 { 155, 0 }, // 56, F10, ka7
89 { 145, 15 }, // 57, 0, k87
90 { 152, 26 }, // 58, P, k80
91 { 155, 38 }, // 59, ;, k82
92 { 163, 49 }, // 60, ?, k85
93 { 170, 0 }, // 61, F11, ka3
94 { 159, 15 }, // 62, -, k86
95 { 166, 26 }, // 63, [, k81
96 { 170, 38 }, // 64, ", k83
97 { 173, 61 }, // 65, Ct_R, k04
98 { 184, 0 }, // 66, F12, ka5
99 { 0, 8 }, // 67, LED, l01
100 { 224, 8 }, // 68, LED, l11
101 { 202, 0 }, // 69, Prt, k97
102 { 0, 15 }, // 70, LED, l02
103 { 224, 15 }, // 71, LED, l12
104 { 224, 15 }, // 72, Del, k65
105 { 0, 21 }, // 73, LED, l03
106 { 224, 21 }, // 74, LED, l13
107 { 224, 26 }, // 75, PgUp, k15
108 { 0, 28 }, // 76, LED, l04
109 { 224, 28 }, // 77, LED, l14
110 { 173, 15 }, // 78, =, k66
111 { 220, 64 }, // 79, Right, k05
112 { 0, 35 }, // 80, LED, l05
113 { 224, 35 }, // 81, LED, l15
114 { 224, 49 }, // 82, End, k75
115 { 0, 42 }, // 83, LED, l06
116 { 224, 42 }, // 84, LED, l16
117 { 195, 15 }, // 85, BSpc, ka1
118 { 224, 38 }, // 86, PgDn, k25
119 { 0, 48 }, // 87, LED, l07
120 { 224, 48 }, // 88, LED, l17
121 { 181, 26 }, // 89, ], k61
122 { 182, 49 }, // 90, Sh_R, k91
123 { 0, 55 }, // 91, LED, l08
124 { 224, 55 }, // 92, LED, l18
125 { 199, 26 }, // 93, \, ka2
126 { 206, 52 }, // 94, Up, k35
127 { 191, 64 }, // 95, Left, k03
128 { 193, 38 }, // 96, Enter, ka4
129 { 206, 64 } // 97, Down, k73
130}, {
131 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
132 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
133 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 2, 2, 4, 2, 2,
134 4, 2, 2, 4, 4, 2, 2, 4, 2, 2, 4, 4, 2, 2, 4, 4, 2, 2, 4, 4, 4, 4, 4
135} };
136
137const aw_led g_aw_leds[DRIVER_LED_TOTAL] = {
138 { 0, CS1_SW1, CS2_SW1, CS3_SW1 }, // 0, ESC, k13
139 { 0, CS4_SW1, CS5_SW1, CS6_SW1 }, // 1, ~, k16
140 { 0, CS7_SW1, CS8_SW1, CS9_SW1 }, // 2, Tab, k11
141 { 0, CS10_SW1, CS11_SW1, CS12_SW1 }, // 3, Caps, k21
142 { 0, CS13_SW1, CS14_SW1, CS15_SW1 }, // 4, Sh_L, k00
143 { 0, CS16_SW1, CS17_SW1, CS18_SW1 }, // 5, Ct_L, k06
144 { 0, CS1_SW2, CS2_SW2, CS3_SW2 }, // 6, F1, k26
145 { 0, CS4_SW2, CS5_SW2, CS6_SW2 }, // 7, 1, k17
146 { 0, CS7_SW2, CS8_SW2, CS9_SW2 }, // 8, Q, k10
147 { 0, CS10_SW2, CS11_SW2, CS12_SW2 }, // 9, A, k12
148 { 0, CS13_SW2, CS14_SW2, CS15_SW2 }, // 10, Z, k14
149 { 0, CS16_SW2, CS17_SW2, CS18_SW2 }, // 11, Win_L, k90
150 { 0, CS1_SW3, CS2_SW3, CS3_SW3 }, // 12, F2, k36
151 { 0, CS4_SW3, CS5_SW3, CS6_SW3 }, // 13, 2, k27
152 { 0, CS7_SW3, CS8_SW3, CS9_SW3 }, // 14, W, k20
153 { 0, CS10_SW3, CS11_SW3, CS12_SW3 }, // 15, S, k22
154 { 0, CS13_SW3, CS14_SW3, CS15_SW3 }, // 16, X, k24
155 { 0, CS16_SW3, CS17_SW3, CS18_SW3 }, // 17, Alt_L, k93
156 { 0, CS1_SW4, CS2_SW4, CS3_SW4 }, // 18, F3, k31
157 { 0, CS4_SW4, CS5_SW4, CS6_SW4 }, // 19, 3, k37
158 { 0, CS7_SW4, CS8_SW4, CS9_SW4 }, // 20, E, k30
159 { 0, CS10_SW4, CS11_SW4, CS12_SW4 }, // 21, D, k32
160 { 0, CS13_SW4, CS14_SW4, CS15_SW4 }, // 22, C, k34
161 { 0, CS1_SW5, CS2_SW5, CS3_SW5 }, // 23, F4, k33
162 { 0, CS4_SW5, CS5_SW5, CS6_SW5 }, // 24, 4, k47
163 { 0, CS7_SW5, CS8_SW5, CS9_SW5 }, // 25, R, k40
164 { 0, CS10_SW5, CS11_SW5, CS12_SW5 }, // 26, F, k42
165 { 0, CS13_SW5, CS14_SW5, CS15_SW5 }, // 27, V, k44
166 { 0, CS1_SW6, CS2_SW6, CS3_SW6 }, // 28, F5, k07
167 { 0, CS4_SW6, CS5_SW6, CS6_SW6 }, // 29, 5, k46
168 { 0, CS7_SW6, CS8_SW6, CS9_SW6 }, // 30, T, k41
169 { 0, CS10_SW6, CS11_SW6, CS12_SW6 }, // 31, G, k43
170 { 0, CS13_SW6, CS14_SW6, CS15_SW6 }, // 32, B, k45
171 { 0, CS16_SW6, CS17_SW6, CS18_SW6 }, // 33, SPACE, k94
172 { 0, CS1_SW7, CS2_SW7, CS3_SW7 }, // 34, F6, k63
173 { 0, CS4_SW7, CS5_SW7, CS6_SW7 }, // 35, 6, k56
174 { 0, CS7_SW7, CS8_SW7, CS9_SW7 }, // 36, Y, k51
175 { 0, CS10_SW7, CS11_SW7, CS12_SW7 }, // 37, H, k53
176 { 0, CS13_SW7, CS14_SW7, CS15_SW7 }, // 38, N, k55
177 { 0, CS1_SW8, CS2_SW8, CS3_SW8 }, // 39, F7, k71
178 { 0, CS4_SW8, CS5_SW8, CS6_SW8 }, // 40, 7, k57
179 { 0, CS7_SW8, CS8_SW8, CS9_SW8 }, // 41, U, k50
180 { 0, CS10_SW8, CS11_SW8, CS12_SW8 }, // 42, J, k52
181 { 0, CS13_SW8, CS14_SW8, CS15_SW8 }, // 43, M, k54
182 { 0, CS1_SW9, CS2_SW9, CS3_SW9 }, // 44, F8, k76
183 { 0, CS4_SW9, CS5_SW9, CS6_SW9 }, // 45, 8, k67
184 { 0, CS7_SW9, CS8_SW9, CS9_SW9 }, // 46, I, k60
185 { 0, CS10_SW9, CS11_SW9, CS12_SW9 }, // 47, K, k62
186 { 0, CS13_SW9, CS14_SW9, CS15_SW9 }, // 48, ,, k64
187 { 0, CS16_SW9, CS17_SW9, CS18_SW9 }, // 49, Alt_R, k95
188 { 0, CS1_SW10, CS2_SW10, CS3_SW10 }, // 50, F9, ka6
189 { 0, CS4_SW10, CS5_SW10, CS6_SW10 }, // 51, 9, k77
190 { 0, CS7_SW10, CS8_SW10, CS9_SW10 }, // 52, O, k70
191 { 0, CS10_SW10, CS11_SW10, CS12_SW10 }, // 53, L, k72
192 { 0, CS13_SW10, CS14_SW10, CS15_SW10 }, // 54, ., k74
193 { 0, CS16_SW10, CS17_SW10, CS18_SW10 }, // 55, FN, k92
194 { 0, CS1_SW11, CS2_SW11, CS3_SW11 }, // 56, F10, ka7
195 { 0, CS4_SW11, CS5_SW11, CS6_SW11 }, // 57, 0, k87
196 { 0, CS7_SW11, CS8_SW11, CS9_SW11 }, // 58, P, k80
197 { 0, CS10_SW11, CS11_SW11, CS12_SW11 }, // 59, ;, k82
198 { 0, CS13_SW11, CS14_SW11, CS15_SW11 }, // 60, ?, k85
199 { 0, CS1_SW12, CS2_SW12, CS3_SW12 }, // 61, F11, ka3
200 { 0, CS4_SW12, CS5_SW12, CS6_SW12 }, // 62, -, k86
201 { 0, CS7_SW12, CS8_SW12, CS9_SW12 }, // 63, [, k81
202 { 0, CS10_SW12, CS11_SW12, CS12_SW12 }, // 64, ", k83
203 { 0, CS16_SW12, CS17_SW12, CS18_SW12 }, // 65, Ct_R, k04
204
205 { 1, CS1_SW1, CS2_SW1, CS3_SW1 }, // 66, F12, ka5
206 { 1, CS13_SW1, CS14_SW1, CS15_SW1 }, // 67, LED, l01
207 { 1, CS16_SW1, CS17_SW1, CS18_SW1 }, // 68, LED, l11
208 { 1, CS4_SW2, CS5_SW2, CS6_SW2 }, // 69, Prt, k97
209 { 1, CS13_SW2, CS14_SW2, CS15_SW2 }, // 70, LED, l02
210 { 1, CS16_SW2, CS17_SW2, CS18_SW2 }, // 71, LED, l12
211 { 1, CS4_SW3, CS5_SW3, CS6_SW3 }, // 72, Del, k65
212 { 1, CS13_SW3, CS14_SW3, CS15_SW3 }, // 73, LED, l03
213 { 1, CS16_SW3, CS17_SW3, CS18_SW3 }, // 74, LED, l13
214 { 1, CS4_SW4, CS5_SW4, CS6_SW4 }, // 75, PgUp, k15
215 { 1, CS13_SW4, CS14_SW4, CS15_SW4 }, // 76, LED, l04
216 { 1, CS16_SW4, CS17_SW4, CS18_SW4 }, // 77, LED, l14
217 { 1, CS1_SW5, CS2_SW5, CS3_SW5 }, // 78, =, k66
218 { 1, CS10_SW5, CS11_SW5, CS12_SW5 }, // 79, Right, k05
219 { 1, CS13_SW5, CS14_SW5, CS15_SW5 }, // 80, LED, l05
220 { 1, CS16_SW5, CS17_SW5, CS18_SW5 }, // 81, LED, l15
221 { 1, CS4_SW6, CS5_SW6, CS6_SW6 }, // 82, End, k75
222 { 1, CS13_SW6, CS14_SW6, CS15_SW6 }, // 83, LED, l06
223 { 1, CS16_SW6, CS17_SW6, CS18_SW6 }, // 84, LED, l16
224 { 1, CS1_SW7, CS2_SW7, CS3_SW7 }, // 85, BSpc, ka1
225 { 1, CS4_SW7, CS5_SW7, CS6_SW7 }, // 86, PgDn, k25
226 { 1, CS13_SW7, CS14_SW7, CS15_SW7 }, // 87, LED, l07
227 { 1, CS16_SW7, CS17_SW7, CS18_SW7 }, // 88, LED, l17
228 { 1, CS1_SW8, CS2_SW8, CS3_SW8 }, // 89, ], k61
229 { 1, CS4_SW8, CS5_SW8, CS6_SW8 }, // 90, Sh_R, k91
230 { 1, CS13_SW8, CS14_SW8, CS15_SW8 }, // 91, LED, l08
231 { 1, CS16_SW8, CS17_SW8, CS18_SW8 }, // 92, LED, l18
232 { 1, CS1_SW9, CS2_SW9, CS3_SW9 }, // 93, \, ka2
233 { 1, CS4_SW9, CS5_SW9, CS6_SW9 }, // 94, Up, k35
234 { 1, CS4_SW10, CS5_SW10, CS6_SW10 }, // 95, Left, k03
235 { 1, CS1_SW11, CS2_SW11, CS3_SW11 }, // 96, Enter, ka4
236 { 1, CS4_SW11, CS5_SW11, CS6_SW11 }, // 97, Down, k73
237};
238#endif
diff --git a/keyboards/gmmk/pro/rules.mk b/keyboards/gmmk/pro/rules.mk
index b12d055a3..6221d6408 100644
--- a/keyboards/gmmk/pro/rules.mk
+++ b/keyboards/gmmk/pro/rules.mk
@@ -21,3 +21,5 @@ RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
21BLUETOOTH_ENABLE = no # Enable Bluetooth 21BLUETOOTH_ENABLE = no # Enable Bluetooth
22AUDIO_ENABLE = no # Audio output 22AUDIO_ENABLE = no # Audio output
23ENCODER_ENABLE = yes 23ENCODER_ENABLE = yes
24RGB_MATRIX_ENABLE = yes
25RGB_MATRIX_DRIVER = AW20216
diff --git a/keyboards/handwired/colorlice/config.h b/keyboards/handwired/colorlice/config.h
index 206a4004e..0148817f3 100644
--- a/keyboards/handwired/colorlice/config.h
+++ b/keyboards/handwired/colorlice/config.h
@@ -49,7 +49,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
49/* RGB LEDs */ 49/* RGB LEDs */
50#define RGB_DI_PIN B1 50#define RGB_DI_PIN B1
51#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 51#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
52#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 52#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
53#define RGB_MATRIX_KEYPRESSES 53#define RGB_MATRIX_KEYPRESSES
54#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 54#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
55#define RGB_MATRIX_LED_PROCESS_LIMIT 4 55#define RGB_MATRIX_LED_PROCESS_LIMIT 4
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.h b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.h
index c8650f73d..ed408563f 100644
--- a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.h
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/5x6_right_trackball.h
@@ -19,7 +19,7 @@
19#include "dactyl_manuform.h" 19#include "dactyl_manuform.h"
20#include "quantum.h" 20#include "quantum.h"
21#include "spi_master.h" 21#include "spi_master.h"
22#include "pmw3360.h" 22#include "drivers/sensors/pmw3360.h"
23#include "pointing_device.h" 23#include "pointing_device.h"
24 24
25 25
diff --git a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/rules.mk b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/rules.mk
index 3fb9ab2a8..9f4a5ea02 100644
--- a/keyboards/handwired/dactyl_manuform/5x6_right_trackball/rules.mk
+++ b/keyboards/handwired/dactyl_manuform/5x6_right_trackball/rules.mk
@@ -27,5 +27,5 @@ MOUSE_SHARED_EP = no
27SPLIT_KEYBOARD = yes 27SPLIT_KEYBOARD = yes
28SPLIT_TRANSPORT = custom 28SPLIT_TRANSPORT = custom
29 29
30SRC += pmw3360.c 30SRC += drivers/sensors/pmw3360.c
31QUANTUM_LIB_SRC += pointer_transport.c serial.c i2c_master.c i2c_slave.c spi_master.c 31QUANTUM_LIB_SRC += pointer_transport.c serial.c i2c_master.c i2c_slave.c spi_master.c
diff --git a/keyboards/handwired/frankie_macropad/keymaps/default/config.h b/keyboards/handwired/frankie_macropad/keymaps/default/config.h
new file mode 100644
index 000000000..dd687cad5
--- /dev/null
+++ b/keyboards/handwired/frankie_macropad/keymaps/default/config.h
@@ -0,0 +1,19 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#define LAYER_STATE_8BIT
diff --git a/keyboards/handwired/freoduo/rules.mk b/keyboards/handwired/freoduo/rules.mk
index e3da3753e..d8923557d 100644
--- a/keyboards/handwired/freoduo/rules.mk
+++ b/keyboards/handwired/freoduo/rules.mk
@@ -11,7 +11,7 @@ BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
11MOUSEKEY_ENABLE = yes # Mouse keys 11MOUSEKEY_ENABLE = yes # Mouse keys
12EXTRAKEY_ENABLE = yes # Audio control and System control 12EXTRAKEY_ENABLE = yes # Audio control and System control
13CONSOLE_ENABLE = no # Console for debug 13CONSOLE_ENABLE = no # Console for debug
14COMMAND_ENABLE = yes # Commands for debug and configuration 14COMMAND_ENABLE = no # Commands for debug and configuration
15# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE 15# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
16SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend 16SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
17# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work 17# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
@@ -21,4 +21,4 @@ RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow
21BLUETOOTH_ENABLE = no # Enable Bluetooth 21BLUETOOTH_ENABLE = no # Enable Bluetooth
22AUDIO_ENABLE = no # Audio output 22AUDIO_ENABLE = no # Audio output
23VELOCIKEY_ENABLE = yes 23VELOCIKEY_ENABLE = yes
24SPLIT_KEYBOARD = yes \ No newline at end of file 24SPLIT_KEYBOARD = yes
diff --git a/keyboards/handwired/hnah40rgb/config.h b/keyboards/handwired/hnah40rgb/config.h
index e6271738c..3d558f97f 100644
--- a/keyboards/handwired/hnah40rgb/config.h
+++ b/keyboards/handwired/hnah40rgb/config.h
@@ -60,7 +60,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
60#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 60#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
61#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 61#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
62#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 62#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
63#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 63// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
64#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 64#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
65#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 65#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
66#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set 66#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set
diff --git a/keyboards/handwired/p65rgb/config.h b/keyboards/handwired/p65rgb/config.h
index c50fc2826..142d3c03e 100644
--- a/keyboards/handwired/p65rgb/config.h
+++ b/keyboards/handwired/p65rgb/config.h
@@ -40,7 +40,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
40 40
41#define RGB_DI_PIN B4 41#define RGB_DI_PIN B4
42#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 42#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
43#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 43#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
44#define RGB_MATRIX_KEYPRESSES 44#define RGB_MATRIX_KEYPRESSES
45#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 45#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
46#define RGB_MATRIX_LED_PROCESS_LIMIT 4 46#define RGB_MATRIX_LED_PROCESS_LIMIT 4
diff --git a/keyboards/helix/rev2/keymaps/default/rules.mk b/keyboards/helix/rev2/keymaps/default/rules.mk
index 206e836ec..c16f3e2b8 100644
--- a/keyboards/helix/rev2/keymaps/default/rules.mk
+++ b/keyboards/helix/rev2/keymaps/default/rules.mk
@@ -5,7 +5,7 @@
5# See TOP/keyboards/helix/rules.mk for a list of options that can be set. 5# See TOP/keyboards/helix/rules.mk for a list of options that can be set.
6# See TOP/docs/config_options.md for more information. 6# See TOP/docs/config_options.md for more information.
7# 7#
8LTO_ENABLE = no # if firmware size over limit, try this option 8LTO_ENABLE = yes # if firmware size over limit, try this option
9 9
10# Helix Spacific Build Options 10# Helix Spacific Build Options
11# you can uncomment and edit follows 7 Variables 11# you can uncomment and edit follows 7 Variables
diff --git a/keyboards/helix/rev3_4rows/config.h b/keyboards/helix/rev3_4rows/config.h
index 9102104bf..95eb8bf0c 100644
--- a/keyboards/helix/rev3_4rows/config.h
+++ b/keyboards/helix/rev3_4rows/config.h
@@ -68,7 +68,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
68# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 68# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
69// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 69// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
70// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 70// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
71# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 71# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
72# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 72# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
73// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 73// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
74// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 74// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
diff --git a/keyboards/helix/rev3_5rows/config.h b/keyboards/helix/rev3_5rows/config.h
index 4dda76206..a373de7d1 100644
--- a/keyboards/helix/rev3_5rows/config.h
+++ b/keyboards/helix/rev3_5rows/config.h
@@ -68,7 +68,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
68# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 68# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
69// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 69// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
70// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 70// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
71# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 71# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
72# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 72# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
73// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 73// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
74// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 74// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
diff --git a/keyboards/hs60/v1/config.h b/keyboards/hs60/v1/config.h
index 68c75b2af..41246b6ee 100644
--- a/keyboards/hs60/v1/config.h
+++ b/keyboards/hs60/v1/config.h
@@ -118,7 +118,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
118//#define RGB_MATRIX_KEYPRESSES // reacts to keypresses (will slow down matrix scan by a lot) 118//#define RGB_MATRIX_KEYPRESSES // reacts to keypresses (will slow down matrix scan by a lot)
119 119
120#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 120#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
121#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 121// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
122#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 215 122#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 215
123 123
124#define DRIVER_ADDR_1 0b1110100 124#define DRIVER_ADDR_1 0b1110100
diff --git a/keyboards/kbdfans/bella/rgb/config.h b/keyboards/kbdfans/bella/rgb/config.h
index f56049690..07594a34a 100644
--- a/keyboards/kbdfans/bella/rgb/config.h
+++ b/keyboards/kbdfans/bella/rgb/config.h
@@ -37,7 +37,7 @@
37/* disable these deprecated features by default */ 37/* disable these deprecated features by default */
38#ifdef RGB_MATRIX_ENABLE 38#ifdef RGB_MATRIX_ENABLE
39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41#define RGB_MATRIX_KEYPRESSES 41#define RGB_MATRIX_KEYPRESSES
42#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 42#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
43#define RGB_MATRIX_LED_PROCESS_LIMIT 4 43#define RGB_MATRIX_LED_PROCESS_LIMIT 4
diff --git a/keyboards/kbdfans/bella/rgb_iso/config.h b/keyboards/kbdfans/bella/rgb_iso/config.h
index fc7a9d7c0..4fda99867 100644
--- a/keyboards/kbdfans/bella/rgb_iso/config.h
+++ b/keyboards/kbdfans/bella/rgb_iso/config.h
@@ -37,7 +37,7 @@
37/* disable these deprecated features by default */ 37/* disable these deprecated features by default */
38#ifdef RGB_MATRIX_ENABLE 38#ifdef RGB_MATRIX_ENABLE
39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41#define RGB_MATRIX_KEYPRESSES 41#define RGB_MATRIX_KEYPRESSES
42#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 42#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
43#define RGB_MATRIX_LED_PROCESS_LIMIT 4 43#define RGB_MATRIX_LED_PROCESS_LIMIT 4
diff --git a/keyboards/kbdfans/kbd67/mkiirgb/v1/config.h b/keyboards/kbdfans/kbd67/mkiirgb/v1/config.h
index a832110d3..b0b7e1dad 100644
--- a/keyboards/kbdfans/kbd67/mkiirgb/v1/config.h
+++ b/keyboards/kbdfans/kbd67/mkiirgb/v1/config.h
@@ -16,9 +16,9 @@
16#define RGB_MATRIX_LED_FLUSH_LIMIT 26 16#define RGB_MATRIX_LED_FLUSH_LIMIT 26
17#define DEBOUNCE 3 17#define DEBOUNCE 3
18#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 18#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
19#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 19#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
20#define RGB_MATRIX_KEYPRESSES 20#define RGB_MATRIX_KEYPRESSES
21#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 21#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
22#define DISABLE_RGB_MATRIX_BAND_SAT 22#define DISABLE_RGB_MATRIX_BAND_SAT
23#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT 23#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
24#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT 24#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
diff --git a/keyboards/kbdfans/kbd67/mkiirgb/v2/config.h b/keyboards/kbdfans/kbd67/mkiirgb/v2/config.h
index 1ac9c770d..51e732f10 100644
--- a/keyboards/kbdfans/kbd67/mkiirgb/v2/config.h
+++ b/keyboards/kbdfans/kbd67/mkiirgb/v2/config.h
@@ -16,10 +16,10 @@
16#define RGB_MATRIX_LED_FLUSH_LIMIT 26 16#define RGB_MATRIX_LED_FLUSH_LIMIT 26
17#define DEBOUNCE 3 17#define DEBOUNCE 3
18#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 18#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
19#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 19#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
20#define RGB_MATRIX_KEYPRESSES 20#define RGB_MATRIX_KEYPRESSES
21#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_ALL 21#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_ALL
22#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 22#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
23#define DISABLE_RGB_MATRIX_BAND_SAT 23#define DISABLE_RGB_MATRIX_BAND_SAT
24#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT 24#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
25#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT 25#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
diff --git a/keyboards/kbdfans/kbd67/rev1/keymaps/default/config.h b/keyboards/kbdfans/kbd67/rev1/keymaps/default/config.h
index a3ed4f762..90fb10ebb 100644
--- a/keyboards/kbdfans/kbd67/rev1/keymaps/default/config.h
+++ b/keyboards/kbdfans/kbd67/rev1/keymaps/default/config.h
@@ -16,4 +16,4 @@
16 16
17#pragma once 17#pragma once
18 18
19// place overrides here 19#define LAYER_STATE_8BIT
diff --git a/keyboards/kbdfans/kbdmini/config.h b/keyboards/kbdfans/kbdmini/config.h
index 5a36e983d..fc65f4341 100644
--- a/keyboards/kbdfans/kbdmini/config.h
+++ b/keyboards/kbdfans/kbdmini/config.h
@@ -35,7 +35,7 @@
35 35
36#ifdef RGB_MATRIX_ENABLE 36#ifdef RGB_MATRIX_ENABLE
37#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 37#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
38#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 38#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
39#define RGB_MATRIX_KEYPRESSES 39#define RGB_MATRIX_KEYPRESSES
40#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 40#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
41#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 41#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
diff --git a/keyboards/kbdfans/maja/config.h b/keyboards/kbdfans/maja/config.h
index d8553766b..3722c8381 100755
--- a/keyboards/kbdfans/maja/config.h
+++ b/keyboards/kbdfans/maja/config.h
@@ -18,9 +18,9 @@
18#define RGB_MATRIX_LED_FLUSH_LIMIT 26 18#define RGB_MATRIX_LED_FLUSH_LIMIT 26
19#define DEBOUNCE 3 19#define DEBOUNCE 3
20#define RGB_DISABLE_AFTER_TIMEOUT 0 20#define RGB_DISABLE_AFTER_TIMEOUT 0
21#define RGB_DISABLE_WHEN_USB_SUSPENDED true 21#define RGB_DISABLE_WHEN_USB_SUSPENDED
22#define RGB_MATRIX_KEYPRESSES 22#define RGB_MATRIX_KEYPRESSES
23#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 23#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
24#define DISABLE_RGB_MATRIX_BAND_SAT 24#define DISABLE_RGB_MATRIX_BAND_SAT
25#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT 25#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
26#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT 26#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
diff --git a/keyboards/keebio/iris/rev2/rules.mk b/keyboards/keebio/iris/rev2/rules.mk
index 765fa7f07..197bad476 100644
--- a/keyboards/keebio/iris/rev2/rules.mk
+++ b/keyboards/keebio/iris/rev2/rules.mk
@@ -32,3 +32,5 @@ RGBLIGHT_ENABLE = yes # Enable WS2812 RGB underlight.
32SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend 32SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
33 33
34SPLIT_KEYBOARD = yes 34SPLIT_KEYBOARD = yes
35
36LTO_ENABLE = yes \ No newline at end of file
diff --git a/keyboards/keebio/iris/rev3/rules.mk b/keyboards/keebio/iris/rev3/rules.mk
index ea92bc98f..b64eab5a4 100644
--- a/keyboards/keebio/iris/rev3/rules.mk
+++ b/keyboards/keebio/iris/rev3/rules.mk
@@ -33,3 +33,4 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
33 33
34SPLIT_KEYBOARD = yes 34SPLIT_KEYBOARD = yes
35ENCODER_ENABLE = yes 35ENCODER_ENABLE = yes
36LTO_ENABLE = yes \ No newline at end of file
diff --git a/keyboards/keebio/iris/rev4/rules.mk b/keyboards/keebio/iris/rev4/rules.mk
index ea92bc98f..9bf5688da 100644
--- a/keyboards/keebio/iris/rev4/rules.mk
+++ b/keyboards/keebio/iris/rev4/rules.mk
@@ -33,3 +33,5 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
33 33
34SPLIT_KEYBOARD = yes 34SPLIT_KEYBOARD = yes
35ENCODER_ENABLE = yes 35ENCODER_ENABLE = yes
36
37LTO_ENABLE = yes \ No newline at end of file
diff --git a/keyboards/keebio/quefrency/rules.mk b/keyboards/keebio/quefrency/rules.mk
index 2c5ad0c36..c674e1016 100644
--- a/keyboards/keebio/quefrency/rules.mk
+++ b/keyboards/keebio/quefrency/rules.mk
@@ -19,3 +19,4 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
19SPLIT_KEYBOARD = yes 19SPLIT_KEYBOARD = yes
20 20
21DEFAULT_FOLDER = keebio/quefrency/rev1 21DEFAULT_FOLDER = keebio/quefrency/rev1
22LTO_ENABLE = yes
diff --git a/keyboards/keebio/viterbi/rev2/rules.mk b/keyboards/keebio/viterbi/rev2/rules.mk
index f95e7ae6a..829d6a56e 100644
--- a/keyboards/keebio/viterbi/rev2/rules.mk
+++ b/keyboards/keebio/viterbi/rev2/rules.mk
@@ -1,3 +1,5 @@
1BACKLIGHT_ENABLE = yes 1BACKLIGHT_ENABLE = yes
2 2
3LAYOUTS = ortho_5x14 3LAYOUTS = ortho_5x14
4
5LTO_ENABLE = yes \ No newline at end of file
diff --git a/keyboards/keebio/viterbi/rules.mk b/keyboards/keebio/viterbi/rules.mk
index 0b746d172..92576d33e 100644
--- a/keyboards/keebio/viterbi/rules.mk
+++ b/keyboards/keebio/viterbi/rules.mk
@@ -19,16 +19,16 @@ BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
19MOUSEKEY_ENABLE = yes # Mouse keys 19MOUSEKEY_ENABLE = yes # Mouse keys
20EXTRAKEY_ENABLE = yes # Audio control and System control 20EXTRAKEY_ENABLE = yes # Audio control and System control
21CONSOLE_ENABLE = no # Console for debug 21CONSOLE_ENABLE = no # Console for debug
22COMMAND_ENABLE = yes # Commands for debug and configuration 22COMMAND_ENABLE = no # Commands for debug and configuration
23NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work 23NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
24BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality 24BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
25MIDI_ENABLE = no # MIDI controls 25MIDI_ENABLE = no # MIDI controls
26AUDIO_ENABLE = no # Audio output on port C6 26AUDIO_ENABLE = no # Audio output on port C6
27UNICODE_ENABLE = no # Unicode 27UNICODE_ENABLE = no # Unicode
28BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID 28BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
29RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. 29RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight.
30# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE 30# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
31SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend 31SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
32 32
33SPLIT_KEYBOARD = yes 33SPLIT_KEYBOARD = yes
34 34
diff --git a/keyboards/kinesis/kint36/config.h b/keyboards/kinesis/kint36/config.h
index be5752603..8b46b3fc1 100644
--- a/keyboards/kinesis/kint36/config.h
+++ b/keyboards/kinesis/kint36/config.h
@@ -64,3 +64,5 @@
64#define LED_CAPS_LOCK_PIN C7 64#define LED_CAPS_LOCK_PIN C7
65#define LED_SCROLL_LOCK_PIN A5 65#define LED_SCROLL_LOCK_PIN A5
66#define LED_COMPOSE_PIN E26 66#define LED_COMPOSE_PIN E26
67
68#define EEPROM_SIZE 4096
diff --git a/keyboards/latin17rgb/config.h b/keyboards/latin17rgb/config.h
index 013899f60..6a7ea8e78 100644
--- a/keyboards/latin17rgb/config.h
+++ b/keyboards/latin17rgb/config.h
@@ -1,18 +1,18 @@
1 /* Copyright 2021 18438880 1 /* Copyright 2021 18438880
2 * 2 *
3 * This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or 5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version. 6 * (at your option) any later version.
7 * 7 *
8 * This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details. 11 * GNU General Public License for more details.
12 * 12 *
13 * You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 15 */
16 16
17#pragma once 17#pragma once
18 18
@@ -56,7 +56,7 @@
56 56
57#ifdef RGB_MATRIX_ENABLE 57#ifdef RGB_MATRIX_ENABLE
58# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 58# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
59# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 59# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
60# define RGB_MATRIX_KEYPRESSES 60# define RGB_MATRIX_KEYPRESSES
61# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 61# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
62# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 62# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
@@ -100,5 +100,3 @@
100#define RGBLIGHT_VAL_STEP 5 100#define RGBLIGHT_VAL_STEP 5
101#define RGBLIGHT_SLEEP 101#define RGBLIGHT_SLEEP
102#endif 102#endif
103
104
diff --git a/keyboards/latin60rgb/config.h b/keyboards/latin60rgb/config.h
index bbe502054..97b481291 100644
--- a/keyboards/latin60rgb/config.h
+++ b/keyboards/latin60rgb/config.h
@@ -1,18 +1,18 @@
1 /* Copyright 2021 latincompass 1 /* Copyright 2021 latincompass
2 * 2 *
3 * This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or 5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version. 6 * (at your option) any later version.
7 * 7 *
8 * This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details. 11 * GNU General Public License for more details.
12 * 12 *
13 * You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 15 */
16#pragma once 16#pragma once
17 17
18/* USB Device descriptor parameter */ 18/* USB Device descriptor parameter */
@@ -53,7 +53,7 @@
53 53
54#ifdef RGB_MATRIX_ENABLE 54#ifdef RGB_MATRIX_ENABLE
55# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 55# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
56# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 56# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
57# define RGB_MATRIX_KEYPRESSES 57# define RGB_MATRIX_KEYPRESSES
58# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 58# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
59# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 59# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
@@ -77,4 +77,3 @@
77# define DRIVER_1_LED_TOTAL 60 77# define DRIVER_1_LED_TOTAL 60
78# define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL 78# define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL
79#endif 79#endif
80
diff --git a/keyboards/le_chiffre/config.h b/keyboards/le_chiffre/config.h
index e14b4665f..af4d1e49c 100644
--- a/keyboards/le_chiffre/config.h
+++ b/keyboards/le_chiffre/config.h
@@ -69,7 +69,7 @@
69 69
70#ifdef RGB_MATRIX_ENABLE 70#ifdef RGB_MATRIX_ENABLE
71#define RGB_MATRIX_KEYPRESSES // reacts to keypresses 71#define RGB_MATRIX_KEYPRESSES // reacts to keypresses
72#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 72#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
73#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 73#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
74#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash. 74#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
75#define RGB_MATRIX_HUE_STEP 8 75#define RGB_MATRIX_HUE_STEP 8
diff --git a/keyboards/marksard/rhymestone/rev1/config.h b/keyboards/marksard/rhymestone/rev1/config.h
index 9a1bf0a1d..983392511 100644
--- a/keyboards/marksard/rhymestone/rev1/config.h
+++ b/keyboards/marksard/rhymestone/rev1/config.h
@@ -93,7 +93,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
93 #define RGB_MATRIX_KEYPRESSES // reacts to keypresses 93 #define RGB_MATRIX_KEYPRESSES // reacts to keypresses
94 // #define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 94 // #define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
95 // #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 95 // #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
96 #define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 96 #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
97 // #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 97 // #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
98 // #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 98 // #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
99 #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 99 #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
diff --git a/keyboards/massdrop/alt/keymaps/pregame/config.h b/keyboards/massdrop/alt/keymaps/pregame/config.h
index acd041ce1..32dee56d3 100644
--- a/keyboards/massdrop/alt/keymaps/pregame/config.h
+++ b/keyboards/massdrop/alt/keymaps/pregame/config.h
@@ -89,7 +89,7 @@
89// #define RGBLIGHT_SAT_STEP 25 // Units to step when in/decreasing saturation 89// #define RGBLIGHT_SAT_STEP 25 // Units to step when in/decreasing saturation
90// #define RGBLIGHT_VAL_STEP 12 // Units to step when in/decreasing value (brightness) 90// #define RGBLIGHT_VAL_STEP 12 // Units to step when in/decreasing value (brightness)
91// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 91// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
92// #define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 92// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
93// #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 93// #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
94// #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 94// #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
95#define RGBLIGHT_ANIMATIONS // Run RGB animations 95#define RGBLIGHT_ANIMATIONS // Run RGB animations
@@ -103,7 +103,7 @@
103// #define RGBLIGHT_EFFECT_RGB_TEST // Enable RGB test animation mode. 103// #define RGBLIGHT_EFFECT_RGB_TEST // Enable RGB test animation mode.
104// #define RGBLIGHT_EFFECT_SNAKE // Enable snake animation mode. 104// #define RGBLIGHT_EFFECT_SNAKE // Enable snake animation mode.
105// #define RGBLIGHT_EFFECT_STATIC_GRADIENT // Enable static gradient mode. 105// #define RGBLIGHT_EFFECT_STATIC_GRADIENT // Enable static gradient mode.
106 106
107// #define RGBLIGHT_EFFECT_BREATHE_CENTER // If defined, used to calculate the curve for the breathing animation. Valid values are 1.0 to 2.7 107// #define RGBLIGHT_EFFECT_BREATHE_CENTER // If defined, used to calculate the curve for the breathing animation. Valid values are 1.0 to 2.7
108// #define RGBLIGHT_EFFECT_BREATHE_MAX 255 // The maximum brightness for the breathing mode. Valid values are 1 to 255 108// #define RGBLIGHT_EFFECT_BREATHE_MAX 255 // The maximum brightness for the breathing mode. Valid values are 1 to 255
109// #define RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL 1000 // How long to wait between light changes for the "Christmas" animation, in milliseconds 109// #define RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL 1000 // How long to wait between light changes for the "Christmas" animation, in milliseconds
diff --git a/keyboards/massdrop/alt/keymaps/urbanvanilla/config.h b/keyboards/massdrop/alt/keymaps/urbanvanilla/config.h
index 0f2740013..f2a7e5038 100644
--- a/keyboards/massdrop/alt/keymaps/urbanvanilla/config.h
+++ b/keyboards/massdrop/alt/keymaps/urbanvanilla/config.h
@@ -24,4 +24,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
24#define RGB_MATRIX_LED_PROCESS_LIMIT 15 24#define RGB_MATRIX_LED_PROCESS_LIMIT 15
25#define RGB_MATRIX_LED_FLUSH_LIMIT 10 25#define RGB_MATRIX_LED_FLUSH_LIMIT 10
26 26
27#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 27// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
diff --git a/keyboards/massdrop/ctrl/keymaps/endgame/config.h b/keyboards/massdrop/ctrl/keymaps/endgame/config.h
index 0ef485591..ad738347a 100644
--- a/keyboards/massdrop/ctrl/keymaps/endgame/config.h
+++ b/keyboards/massdrop/ctrl/keymaps/endgame/config.h
@@ -49,7 +49,7 @@
49// #define RGBLIGHT_SAT_STEP 25 // Units to step when in/decreasing saturation 49// #define RGBLIGHT_SAT_STEP 25 // Units to step when in/decreasing saturation
50// #define RGBLIGHT_VAL_STEP 12 // Units to step when in/decreasing value (brightness) 50// #define RGBLIGHT_VAL_STEP 12 // Units to step when in/decreasing value (brightness)
51// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 51// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
52// #define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 52// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
53// #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 53// #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
54// #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 54// #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
55// #define RGBLIGHT_ANIMATIONS // Run RGB animations 55// #define RGBLIGHT_ANIMATIONS // Run RGB animations
diff --git a/keyboards/massdrop/ctrl/keymaps/matthewrobo/config.h b/keyboards/massdrop/ctrl/keymaps/matthewrobo/config.h
index 6e16c3a5f..89c129c58 100644
--- a/keyboards/massdrop/ctrl/keymaps/matthewrobo/config.h
+++ b/keyboards/massdrop/ctrl/keymaps/matthewrobo/config.h
@@ -67,7 +67,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
67// #define RGBLIGHT_SAT_STEP 25 // Units to step when in/decreasing saturation 67// #define RGBLIGHT_SAT_STEP 25 // Units to step when in/decreasing saturation
68// #define RGBLIGHT_VAL_STEP 12 // Units to step when in/decreasing value (brightness) 68// #define RGBLIGHT_VAL_STEP 12 // Units to step when in/decreasing value (brightness)
69// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 69// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
70// #define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 70// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
71// #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 71// #define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
72// #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 72// #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
73// #define RGBLIGHT_ANIMATIONS // Run RGB animations 73// #define RGBLIGHT_ANIMATIONS // Run RGB animations
diff --git a/keyboards/mechlovin/adelais/rgb_led/rev1/config.h b/keyboards/mechlovin/adelais/rgb_led/rev1/config.h
index 1ba7d27df..d75cbd3f2 100644
--- a/keyboards/mechlovin/adelais/rgb_led/rev1/config.h
+++ b/keyboards/mechlovin/adelais/rgb_led/rev1/config.h
@@ -13,7 +13,7 @@
13#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 13#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
14#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 14#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
15#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 15#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
16#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 16// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
17#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 17#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
18#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 220 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 18#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 220 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
19#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set \ No newline at end of file 19#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set
diff --git a/keyboards/mechlovin/adelais/rgb_led/rev2/config.h b/keyboards/mechlovin/adelais/rgb_led/rev2/config.h
index 38ffdd40a..c830edce2 100644
--- a/keyboards/mechlovin/adelais/rgb_led/rev2/config.h
+++ b/keyboards/mechlovin/adelais/rgb_led/rev2/config.h
@@ -1,7 +1,7 @@
1#pragma once 1#pragma once
2 2
3#define PRODUCT_ID 0xAEC2 3#define PRODUCT_ID 0xAEC2
4#define PRODUCT Adelais En Ciel Rev2 4#define PRODUCT Adelais En Ciel Rev2
5 5
6#define MATRIX_ROW_PINS { B1, A0, C13, A1, A2} 6#define MATRIX_ROW_PINS { B1, A0, C13, A1, A2}
7#define MATRIX_COL_PINS { A10, A9, A8, B15, B14, B13, B12, B11, B10, B8, B4, B5, B3, C14, A7 } 7#define MATRIX_COL_PINS { A10, A9, A8, B15, B14, B13, B12, B11, B10, B8, B4, B5, B3, C14, A7 }
@@ -31,7 +31,7 @@
31#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 31#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
32#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 32#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
33#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 33#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
34#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 34// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
35#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 35#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
36#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 36#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
37#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set 37#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set
@@ -42,4 +42,4 @@
42#define ENCODERS_PAD_B { A3 } 42#define ENCODERS_PAD_B { A3 }
43#define ENCODER_RESOLUTION 4 43#define ENCODER_RESOLUTION 4
44 44
45#define TAP_CODE_DELAY 10 \ No newline at end of file 45#define TAP_CODE_DELAY 10
diff --git a/keyboards/mechlovin/delphine/rgb_led/config.h b/keyboards/mechlovin/delphine/rgb_led/config.h
index 4d5c853d0..9a653d759 100644
--- a/keyboards/mechlovin/delphine/rgb_led/config.h
+++ b/keyboards/mechlovin/delphine/rgb_led/config.h
@@ -24,7 +24,7 @@
24// #define RGBLIGHT_EFFECT_RGB_TEST 24// #define RGBLIGHT_EFFECT_RGB_TEST
25// #define RGBLIGHT_EFFECT_ALTERNATING 25// #define RGBLIGHT_EFFECT_ALTERNATING
26#endif 26#endif
27 27
28//rgb matrix setting// This is a 7-bit address, that gets left-shifted and bit 0 28//rgb matrix setting// This is a 7-bit address, that gets left-shifted and bit 0
29// set to 0 for write, 1 for read (as per I2C protocol) 29// set to 0 for write, 1 for read (as per I2C protocol)
30// The address will vary depending on your wiring: 30// The address will vary depending on your wiring:
@@ -41,7 +41,7 @@
41#define RGB_MATRIX_KEYPRESSES // reacts to keypresses 41#define RGB_MATRIX_KEYPRESSES // reacts to keypresses
42#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 42#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
43#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 43#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
44#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 44// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
45#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 45#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
46#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 46#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
47#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set 47#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set
diff --git a/keyboards/mechlovin/hannah60rgb/rev1/config.h b/keyboards/mechlovin/hannah60rgb/rev1/config.h
index 20873e716..fd45ecca6 100644
--- a/keyboards/mechlovin/hannah60rgb/rev1/config.h
+++ b/keyboards/mechlovin/hannah60rgb/rev1/config.h
@@ -11,8 +11,8 @@
11# define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 11# define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
12# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 12# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
13# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 13# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
14# define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 14// # define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
15# define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 15# define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
16# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 16# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
17# define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set 17# define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set
18#endif \ No newline at end of file 18#endif
diff --git a/keyboards/mechlovin/hannah60rgb/rev2/config.h b/keyboards/mechlovin/hannah60rgb/rev2/config.h
index 2bcffbc85..5e57f985d 100644
--- a/keyboards/mechlovin/hannah60rgb/rev2/config.h
+++ b/keyboards/mechlovin/hannah60rgb/rev2/config.h
@@ -30,11 +30,11 @@
30#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 30#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
31#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 31#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
32#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 32#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
33#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 33// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
34#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 34#define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
35#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 35#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
36#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set 36#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_PINWHEEL // Sets the default mode, if none has been set
37 37
38#if defined(RGBLIGHT_ENABLE) && defined(RGB_MATRIX_ENABLE) 38#if defined(RGBLIGHT_ENABLE) && defined(RGB_MATRIX_ENABLE)
39# define RGB_MATRIX_DISABLE_KEYCODES 39# define RGB_MATRIX_DISABLE_KEYCODES
40#endif \ No newline at end of file 40#endif
diff --git a/keyboards/mechlovin/infinity87/rgb_rev1/config.h b/keyboards/mechlovin/infinity87/rgb_rev1/config.h
index 0c16c684c..76c6e0db7 100644
--- a/keyboards/mechlovin/infinity87/rgb_rev1/config.h
+++ b/keyboards/mechlovin/infinity87/rgb_rev1/config.h
@@ -35,7 +35,7 @@
35// 0b0110001 AD <-> SCL 35// 0b0110001 AD <-> SCL
36// 0b0110010 AD <-> SDA 36// 0b0110010 AD <-> SDA
37#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 37#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
38#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 38#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
39#define RGB_MATRIX_KEYPRESSES 39#define RGB_MATRIX_KEYPRESSES
40#define DISABLE_RGB_MATRIX_SPLASH 40#define DISABLE_RGB_MATRIX_SPLASH
41#define DISABLE_RGB_MATRIX_MULTISPLASH 41#define DISABLE_RGB_MATRIX_MULTISPLASH
diff --git a/keyboards/melgeek/mj61/config.h b/keyboards/melgeek/mj61/config.h
index 164c04fb5..6ba19dd75 100644
--- a/keyboards/melgeek/mj61/config.h
+++ b/keyboards/melgeek/mj61/config.h
@@ -37,7 +37,7 @@
37#define NO_ACTION_FUNCTION 37#define NO_ACTION_FUNCTION
38 38
39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41#define RGB_MATRIX_KEYPRESSES 41#define RGB_MATRIX_KEYPRESSES
42#define RGB_MATRIX_LED_PROCESS_LIMIT 4 42#define RGB_MATRIX_LED_PROCESS_LIMIT 4
43#define RGB_MATRIX_LED_FLUSH_LIMIT 26 43#define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/melgeek/mj63/config.h b/keyboards/melgeek/mj63/config.h
index 47ad2f96c..46d3b0fb7 100644
--- a/keyboards/melgeek/mj63/config.h
+++ b/keyboards/melgeek/mj63/config.h
@@ -37,7 +37,7 @@
37#define NO_ACTION_FUNCTION 37#define NO_ACTION_FUNCTION
38 38
39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41#define RGB_MATRIX_KEYPRESSES 41#define RGB_MATRIX_KEYPRESSES
42#define RGB_MATRIX_LED_PROCESS_LIMIT 4 42#define RGB_MATRIX_LED_PROCESS_LIMIT 4
43#define RGB_MATRIX_LED_FLUSH_LIMIT 26 43#define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/melgeek/mj64/config.h b/keyboards/melgeek/mj64/config.h
index 29cb95f17..920d34acd 100644
--- a/keyboards/melgeek/mj64/config.h
+++ b/keyboards/melgeek/mj64/config.h
@@ -37,7 +37,7 @@
37#define NO_ACTION_FUNCTION 37#define NO_ACTION_FUNCTION
38 38
39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41#define RGB_MATRIX_KEYPRESSES 41#define RGB_MATRIX_KEYPRESSES
42#define RGB_MATRIX_LED_PROCESS_LIMIT 4 42#define RGB_MATRIX_LED_PROCESS_LIMIT 4
43#define RGB_MATRIX_LED_FLUSH_LIMIT 26 43#define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/melgeek/mj65/config.h b/keyboards/melgeek/mj65/config.h
index 12a7c7ce1..399c243ac 100644
--- a/keyboards/melgeek/mj65/config.h
+++ b/keyboards/melgeek/mj65/config.h
@@ -37,7 +37,7 @@
37#define NO_ACTION_FUNCTION 37#define NO_ACTION_FUNCTION
38 38
39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41#define RGB_MATRIX_KEYPRESSES 41#define RGB_MATRIX_KEYPRESSES
42#define RGB_MATRIX_LED_PROCESS_LIMIT 4 42#define RGB_MATRIX_LED_PROCESS_LIMIT 4
43#define RGB_MATRIX_LED_FLUSH_LIMIT 26 43#define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/melgeek/mojo75/config.h b/keyboards/melgeek/mojo75/config.h
index c1a8083f1..d5bb4b454 100644
--- a/keyboards/melgeek/mojo75/config.h
+++ b/keyboards/melgeek/mojo75/config.h
@@ -37,7 +37,7 @@
37#define NO_ACTION_FUNCTION 37#define NO_ACTION_FUNCTION
38 38
39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 39#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
40#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41#define RGB_MATRIX_KEYPRESSES 41#define RGB_MATRIX_KEYPRESSES
42#define RGB_MATRIX_LED_PROCESS_LIMIT 4 42#define RGB_MATRIX_LED_PROCESS_LIMIT 4
43#define RGB_MATRIX_LED_FLUSH_LIMIT 26 43#define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/melgeek/z70ultra/config.h b/keyboards/melgeek/z70ultra/config.h
index d5a9d0a89..e4530e2ea 100644
--- a/keyboards/melgeek/z70ultra/config.h
+++ b/keyboards/melgeek/z70ultra/config.h
@@ -36,7 +36,7 @@
36#define NO_ACTION_FUNCTION 36#define NO_ACTION_FUNCTION
37 37
38#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 38#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
39#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 39#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
40#define RGB_MATRIX_KEYPRESSES 40#define RGB_MATRIX_KEYPRESSES
41#define RGB_MATRIX_LED_PROCESS_LIMIT 4 41#define RGB_MATRIX_LED_PROCESS_LIMIT 4
42#define RGB_MATRIX_LED_FLUSH_LIMIT 26 42#define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/miller/gm862/config.h b/keyboards/miller/gm862/config.h
index 2b084efc2..e6e1b4c1d 100644
--- a/keyboards/miller/gm862/config.h
+++ b/keyboards/miller/gm862/config.h
@@ -36,10 +36,10 @@
36#define DEBOUNCE 3 36#define DEBOUNCE 3
37#ifdef RGB_MATRIX_ENABLE 37#ifdef RGB_MATRIX_ENABLE
38# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 38# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
39# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 39# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
40# define RGB_MATRIX_KEYPRESSES 40# define RGB_MATRIX_KEYPRESSES
41# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 41# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
42# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 42# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
43# define DISABLE_RGB_MATRIX_BAND_SAT 43# define DISABLE_RGB_MATRIX_BAND_SAT
44# define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT 44# define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
45# define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT 45# define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
diff --git a/keyboards/monstargear/xo87/rgb/config.h b/keyboards/monstargear/xo87/rgb/config.h
index 83eee8349..5ed0ed445 100644
--- a/keyboards/monstargear/xo87/rgb/config.h
+++ b/keyboards/monstargear/xo87/rgb/config.h
@@ -36,7 +36,7 @@
36#define DIODE_DIRECTION ROW2COL 36#define DIODE_DIRECTION ROW2COL
37#define RGB_DI_PIN D7 37#define RGB_DI_PIN D7
38#define DRIVER_LED_TOTAL 110 38#define DRIVER_LED_TOTAL 110
39#define RGB_DISABLE_WHEN_USB_SUSPENDED true 39#define RGB_DISABLE_WHEN_USB_SUSPENDED
40 40
41#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 100 // limits maximum brightness of LEDs to 100 out of 255. 41#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 100 // limits maximum brightness of LEDs to 100 out of 255.
42#define RGBLIGHT_LIMIT_VAL 100 // limits maximum brightness of LEDs to 100 out of 255. 42#define RGBLIGHT_LIMIT_VAL 100 // limits maximum brightness of LEDs to 100 out of 255.
diff --git a/keyboards/moonlander/config.h b/keyboards/moonlander/config.h
index c88feea3d..c1a139dc7 100644
--- a/keyboards/moonlander/config.h
+++ b/keyboards/moonlander/config.h
@@ -91,7 +91,7 @@
91#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 175 91#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 175
92#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 92#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
93#define RGB_MATRIX_KEYPRESSES 93#define RGB_MATRIX_KEYPRESSES
94#define RGB_DISABLE_WHEN_USB_SUSPENDED true 94#define RGB_DISABLE_WHEN_USB_SUSPENDED
95 95
96#define MUSIC_MAP 96#define MUSIC_MAP
97 97
diff --git a/keyboards/mt84/keymaps/default/config.h b/keyboards/mt84/keymaps/default/config.h
new file mode 100644
index 000000000..dd687cad5
--- /dev/null
+++ b/keyboards/mt84/keymaps/default/config.h
@@ -0,0 +1,19 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#define LAYER_STATE_8BIT
diff --git a/keyboards/naked48/keymaps/salicylic/config.h b/keyboards/naked48/keymaps/salicylic/config.h
index b6372db3b..71a43e208 100644
--- a/keyboards/naked48/keymaps/salicylic/config.h
+++ b/keyboards/naked48/keymaps/salicylic/config.h
@@ -31,7 +31,7 @@
31# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 31# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
32// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 32// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
33// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 33// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
34# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 34# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
35// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 35// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
36// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 36// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
37// # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 37// # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
@@ -41,4 +41,3 @@
41# define RGB_MATRIX_VAL_STEP 5 41# define RGB_MATRIX_VAL_STEP 5
42# define RGB_MATRIX_SPD_STEP 10 42# define RGB_MATRIX_SPD_STEP 10
43#endif 43#endif
44
diff --git a/keyboards/oddball/optical_sensor/optical_sensor.h b/keyboards/oddball/optical_sensor/optical_sensor.h
index a152d02cf..00955209e 100644
--- a/keyboards/oddball/optical_sensor/optical_sensor.h
+++ b/keyboards/oddball/optical_sensor/optical_sensor.h
@@ -17,7 +17,7 @@
17/* common interface for opitcal sensors */ 17/* common interface for opitcal sensors */
18 18
19#if defined ADNS_9800 19#if defined ADNS_9800
20 #include "../adns/adns.h" 20 #include "drivers/sensors/adns9800.h"
21 #define config_optical_sensor_t config_adns_t 21 #define config_optical_sensor_t config_adns_t
22 #define report_optical_sensor_t report_adns_t 22 #define report_optical_sensor_t report_adns_t
23 #define optical_sensor_init adns_init 23 #define optical_sensor_init adns_init
diff --git a/keyboards/oddball/rules.mk b/keyboards/oddball/rules.mk
index e9e540c3c..8fc86b570 100644
--- a/keyboards/oddball/rules.mk
+++ b/keyboards/oddball/rules.mk
@@ -25,5 +25,5 @@ POINTING_DEVICE_ENABLE = yes
25DEFAULT_FOLDER = oddball/v1 25DEFAULT_FOLDER = oddball/v1
26 26
27SRC += spi_master.c 27SRC += spi_master.c
28SRC += adns/adns.c 28SRC += drivers/sensors/adns9800.c
29SRC += pmw/pmw.c 29SRC += pmw/pmw.c
diff --git a/keyboards/opendeck/32/rev1/config.h b/keyboards/opendeck/32/rev1/config.h
index 9f8ed7427..8b25ab256 100644
--- a/keyboards/opendeck/32/rev1/config.h
+++ b/keyboards/opendeck/32/rev1/config.h
@@ -38,7 +38,7 @@
38#define DRIVER_COUNT 1 38#define DRIVER_COUNT 1
39#define DRIVER_1_LED_TOTAL (4 * 8 * 3) 39#define DRIVER_1_LED_TOTAL (4 * 8 * 3)
40#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL) 40#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL)
41#define RGB_DISABLE_WHEN_USB_SUSPENDED true 41#define RGB_DISABLE_WHEN_USB_SUSPENDED
42#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_SPIRAL 42#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_SPIRAL
43#define RGB_MATRIX_DISABLE_KEYCODES 43#define RGB_MATRIX_DISABLE_KEYCODES
44 44
diff --git a/keyboards/percent/canoe_gen2/config.h b/keyboards/percent/canoe_gen2/config.h
index bac5ebb3f..6409371d4 100644
--- a/keyboards/percent/canoe_gen2/config.h
+++ b/keyboards/percent/canoe_gen2/config.h
@@ -64,4 +64,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
64#define RGB_MATRIX_STARTUP_SAT 255 64#define RGB_MATRIX_STARTUP_SAT 255
65#define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS 65#define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS
66#define RGB_MATRIX_STARTUP_SPD 127 66#define RGB_MATRIX_STARTUP_SPD 127
67#define RGB_DISABLE_WHEN_USB_SUSPENDED true 67#define RGB_DISABLE_WHEN_USB_SUSPENDED
diff --git a/keyboards/phase_studio/titan65/config.h b/keyboards/phase_studio/titan65/config.h
index 4104c2ec2..66ae4f20b 100644
--- a/keyboards/phase_studio/titan65/config.h
+++ b/keyboards/phase_studio/titan65/config.h
@@ -47,5 +47,5 @@
47#define RGB_DI_PIN E6 47#define RGB_DI_PIN E6
48#define DRIVER_LED_TOTAL 67 48#define DRIVER_LED_TOTAL 67
49#define RGB_MATRIX_KEYPRESSES // reacts to keypresses 49#define RGB_MATRIX_KEYPRESSES // reacts to keypresses
50#define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended 50// #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
51#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 51#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
diff --git a/keyboards/planck/ez/config.h b/keyboards/planck/ez/config.h
index 7f8876496..5317a5156 100644
--- a/keyboards/planck/ez/config.h
+++ b/keyboards/planck/ez/config.h
@@ -147,7 +147,7 @@
147 147
148#define RGB_MATRIX_KEYPRESSES 148#define RGB_MATRIX_KEYPRESSES
149#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 149#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
150#define RGB_DISABLE_WHEN_USB_SUSPENDED true 150#define RGB_DISABLE_WHEN_USB_SUSPENDED
151 151
152#define RGB_MATRIX_LED_PROCESS_LIMIT 5 152#define RGB_MATRIX_LED_PROCESS_LIMIT 5
153#define RGB_MATRIX_LED_FLUSH_LIMIT 26 153#define RGB_MATRIX_LED_FLUSH_LIMIT 26
diff --git a/keyboards/planck/rev6/config.h b/keyboards/planck/rev6/config.h
index 4bc8a509f..18bb74096 100644
--- a/keyboards/planck/rev6/config.h
+++ b/keyboards/planck/rev6/config.h
@@ -141,7 +141,7 @@
141#define WS2812_DMA_CHANNEL 2 141#define WS2812_DMA_CHANNEL 2
142 142
143#ifndef RGB_DISABLE_WHEN_USB_SUSPENDED 143#ifndef RGB_DISABLE_WHEN_USB_SUSPENDED
144# define RGB_DISABLE_WHEN_USB_SUSPENDED true 144# define RGB_DISABLE_WHEN_USB_SUSPENDED
145#endif 145#endif
146 146
147#endif 147#endif
diff --git a/keyboards/ploopyco/mouse/mouse.h b/keyboards/ploopyco/mouse/mouse.h
index 5d49d2f2d..d11aa5e9a 100644
--- a/keyboards/ploopyco/mouse/mouse.h
+++ b/keyboards/ploopyco/mouse/mouse.h
@@ -20,7 +20,7 @@
20 20
21#include "quantum.h" 21#include "quantum.h"
22#include "spi_master.h" 22#include "spi_master.h"
23#include "pmw3360.h" 23#include "drivers/sensors/pmw3360.h"
24#include "analog.h" 24#include "analog.h"
25#include "opt_encoder.h" 25#include "opt_encoder.h"
26#include "pointing_device.h" 26#include "pointing_device.h"
diff --git a/keyboards/ploopyco/mouse/rules.mk b/keyboards/ploopyco/mouse/rules.mk
index f998672f1..17aac9801 100644
--- a/keyboards/ploopyco/mouse/rules.mk
+++ b/keyboards/ploopyco/mouse/rules.mk
@@ -27,4 +27,4 @@ POINTING_DEVICE_ENABLE = yes
27MOUSEKEY_ENABLE = yes # Mouse keys 27MOUSEKEY_ENABLE = yes # Mouse keys
28 28
29QUANTUM_LIB_SRC += analog.c spi_master.c 29QUANTUM_LIB_SRC += analog.c spi_master.c
30SRC += pmw3360.c opt_encoder.c 30SRC += drivers/sensors/pmw3360.c opt_encoder.c
diff --git a/keyboards/ploopyco/pmw3360.c b/keyboards/ploopyco/pmw3360.c
deleted file mode 100644
index 5f9f72a9e..000000000
--- a/keyboards/ploopyco/pmw3360.c
+++ /dev/null
@@ -1,218 +0,0 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * Copyright 2019 Sunjun Kim
3 * Copyright 2020 Ploopy Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "wait.h"
20#include "debug.h"
21#include "print.h"
22#include "pmw3360.h"
23#include "pmw3360_firmware.h"
24
25bool _inBurst = false;
26
27#ifndef PMW_CPI
28# define PMW_CPI 1600
29#endif
30#ifndef SPI_DIVISOR
31# define SPI_DIVISOR 2
32#endif
33#ifndef ROTATIONAL_TRANSFORM_ANGLE
34# define ROTATIONAL_TRANSFORM_ANGLE 0x00
35#endif
36
37void 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')); }
38
39
40bool spi_start_adv(void) {
41 bool status = spi_start(SPI_SS_PIN, false, 3, SPI_DIVISOR);
42 wait_us(1);
43 return status;
44}
45
46void spi_stop_adv(void) {
47 wait_us(1);
48 spi_stop();
49}
50
51spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data) {
52 if (reg_addr != REG_Motion_Burst) {
53 _inBurst = false;
54 }
55
56 spi_start_adv();
57 // send address of the register, with MSBit = 1 to indicate it's a write
58 spi_status_t status = spi_write(reg_addr | 0x80);
59 status = spi_write(data);
60
61 // tSCLK-NCS for write operation
62 wait_us(20);
63
64 // tSWW/tSWR (=120us) minus tSCLK-NCS. Could be shortened, but is looks like a safe lower bound
65 wait_us(100);
66 spi_stop();
67 return status;
68}
69
70uint8_t spi_read_adv(uint8_t reg_addr) {
71 spi_start_adv();
72 // send adress of the register, with MSBit = 0 to indicate it's a read
73 spi_write(reg_addr & 0x7f);
74
75 uint8_t data = spi_read();
76
77 // tSCLK-NCS for read operation is 120ns
78 wait_us(1);
79
80 // tSRW/tSRR (=20us) minus tSCLK-NCS
81 wait_us(19);
82
83 spi_stop();
84 return data;
85}
86
87void pmw_set_cpi(uint16_t cpi) {
88 int cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119
89
90 spi_start_adv();
91 spi_write_adv(REG_Config1, cpival);
92 spi_stop();
93}
94
95bool pmw_spi_init(void) {
96 spi_init();
97 _inBurst = false;
98
99 spi_stop();
100 spi_start_adv();
101 spi_stop();
102
103 spi_write_adv(REG_Shutdown, 0xb6); // Shutdown first
104 wait_ms(300);
105
106 spi_start_adv();
107 wait_us(40);
108 spi_stop_adv();
109 wait_us(40);
110
111 spi_write_adv(REG_Power_Up_Reset, 0x5a);
112 wait_ms(50);
113
114 spi_read_adv(REG_Motion);
115 spi_read_adv(REG_Delta_X_L);
116 spi_read_adv(REG_Delta_X_H);
117 spi_read_adv(REG_Delta_Y_L);
118 spi_read_adv(REG_Delta_Y_H);
119
120 pmw_upload_firmware();
121
122 spi_stop_adv();
123
124 wait_ms(10);
125 pmw_set_cpi(PMW_CPI);
126
127 wait_ms(1);
128
129 return pmw_check_signature();
130}
131
132void pmw_upload_firmware(void) {
133 spi_write_adv(REG_Config2, 0x00);
134
135 spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30));
136
137 spi_write_adv(REG_SROM_Enable, 0x1d);
138
139 wait_ms(10);
140
141 spi_write_adv(REG_SROM_Enable, 0x18);
142
143 spi_start_adv();
144 spi_write(REG_SROM_Load_Burst | 0x80);
145 wait_us(15);
146
147 unsigned char c;
148 for (int i = 0; i < firmware_length; i++) {
149 c = (unsigned char)pgm_read_byte(firmware_data + i);
150 spi_write(c);
151 wait_us(15);
152 }
153 wait_us(200);
154
155 spi_read_adv(REG_SROM_ID);
156
157 spi_write_adv(REG_Config2, 0x00);
158
159 spi_stop();
160 wait_ms(10);
161}
162
163bool pmw_check_signature(void) {
164 uint8_t pid = spi_read_adv(REG_Product_ID);
165 uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID);
166 uint8_t SROM_ver = spi_read_adv(REG_SROM_ID);
167 return (pid == 0x42 && iv_pid == 0xBD && SROM_ver == 0x04); // signature for SROM 0x04
168}
169
170report_pmw_t pmw_read_burst(void) {
171 if (!_inBurst) {
172 dprintf("burst on");
173 spi_write_adv(REG_Motion_Burst, 0x00);
174 _inBurst = true;
175 }
176
177 spi_start_adv();
178 spi_write(REG_Motion_Burst);
179 wait_us(35); // waits for tSRAD
180
181 report_pmw_t data;
182 data.motion = 0;
183 data.dx = 0;
184 data.mdx = 0;
185 data.dy = 0;
186 data.mdx = 0;
187
188 data.motion = spi_read();
189 spi_write(0x00); // skip Observation
190 data.dx = spi_read();
191 data.mdx = spi_read();
192 data.dy = spi_read();
193 data.mdy = spi_read();
194
195 spi_stop();
196
197 print_byte(data.motion);
198 print_byte(data.dx);
199 print_byte(data.mdx);
200 print_byte(data.dy);
201 print_byte(data.mdy);
202 dprintf("\n");
203
204 data.isMotion = (data.motion & 0x80) != 0;
205 data.isOnSurface = (data.motion & 0x08) == 0;
206 data.dx |= (data.mdx << 8);
207 data.dx = data.dx * -1;
208 data.dy |= (data.mdy << 8);
209 data.dy = data.dy * -1;
210
211 spi_stop();
212
213 if (data.motion & 0b111) { // panic recovery, sometimes burst mode works weird.
214 _inBurst = false;
215 }
216
217 return data;
218}
diff --git a/keyboards/ploopyco/pmw3360.h b/keyboards/ploopyco/pmw3360.h
deleted file mode 100644
index c1d5e3bad..000000000
--- a/keyboards/ploopyco/pmw3360.h
+++ /dev/null
@@ -1,103 +0,0 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * Copyright 2019 Sunjun Kim
3 * Copyright 2020 Ploopy Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21#include "spi_master.h"
22
23// Registers
24#define REG_Product_ID 0x00
25#define REG_Revision_ID 0x01
26#define REG_Motion 0x02
27#define REG_Delta_X_L 0x03
28#define REG_Delta_X_H 0x04
29#define REG_Delta_Y_L 0x05
30#define REG_Delta_Y_H 0x06
31#define REG_SQUAL 0x07
32#define REG_Raw_Data_Sum 0x08
33#define REG_Maximum_Raw_data 0x09
34#define REG_Minimum_Raw_data 0x0A
35#define REG_Shutter_Lower 0x0B
36#define REG_Shutter_Upper 0x0C
37#define REG_Control 0x0D
38#define REG_Config1 0x0F
39#define REG_Config2 0x10
40#define REG_Angle_Tune 0x11
41#define REG_Frame_Capture 0x12
42#define REG_SROM_Enable 0x13
43#define REG_Run_Downshift 0x14
44#define REG_Rest1_Rate_Lower 0x15
45#define REG_Rest1_Rate_Upper 0x16
46#define REG_Rest1_Downshift 0x17
47#define REG_Rest2_Rate_Lower 0x18
48#define REG_Rest2_Rate_Upper 0x19
49#define REG_Rest2_Downshift 0x1A
50#define REG_Rest3_Rate_Lower 0x1B
51#define REG_Rest3_Rate_Upper 0x1C
52#define REG_Observation 0x24
53#define REG_Data_Out_Lower 0x25
54#define REG_Data_Out_Upper 0x26
55#define REG_Raw_Data_Dump 0x29
56#define REG_SROM_ID 0x2A
57#define REG_Min_SQ_Run 0x2B
58#define REG_Raw_Data_Threshold 0x2C
59#define REG_Config5 0x2F
60#define REG_Power_Up_Reset 0x3A
61#define REG_Shutdown 0x3B
62#define REG_Inverse_Product_ID 0x3F
63#define REG_LiftCutoff_Tune3 0x41
64#define REG_Angle_Snap 0x42
65#define REG_LiftCutoff_Tune1 0x4A
66#define REG_Motion_Burst 0x50
67#define REG_LiftCutoff_Tune_Timeout 0x58
68#define REG_LiftCutoff_Tune_Min_Length 0x5A
69#define REG_SROM_Load_Burst 0x62
70#define REG_Lift_Config 0x63
71#define REG_Raw_Data_Burst 0x64
72#define REG_LiftCutoff_Tune2 0x65
73
74#ifdef CONSOLE_ENABLE
75void print_byte(uint8_t byte);
76#endif
77
78typedef struct {
79 int8_t motion;
80 bool isMotion; // True if a motion is detected.
81 bool isOnSurface; // True when a chip is on a surface
82 int16_t dx; // displacement on x directions. Unit: Count. (CPI * Count = Inch value)
83 int8_t mdx;
84 int16_t dy; // displacement on y directions.
85 int8_t mdy;
86} report_pmw_t;
87
88
89
90bool spi_start_adv(void);
91void spi_stop_adv(void);
92spi_status_t spi_write_adv(uint8_t reg_addr, uint8_t data);
93uint8_t spi_read_adv(uint8_t reg_addr);
94bool pmw_spi_init(void);
95void pmw_set_cpi(uint16_t cpi);
96void pmw_upload_firmware(void);
97bool pmw_check_signature(void);
98report_pmw_t pmw_read_burst(void);
99
100
101#define degToRad(angleInDegrees) ((angleInDegrees)*M_PI / 180.0)
102#define radToDeg(angleInRadians) ((angleInRadians)*180.0 / M_PI)
103#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
diff --git a/keyboards/ploopyco/pmw3360_firmware.h b/keyboards/ploopyco/pmw3360_firmware.h
deleted file mode 100644
index cca5a6a4d..000000000
--- a/keyboards/ploopyco/pmw3360_firmware.h
+++ /dev/null
@@ -1,300 +0,0 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 * Copyright 2019 Sunjun Kim
3 * Copyright 2020 Ploopy Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21// clang-format off
22// Firmware Blob foor PMW3360
23const uint16_t firmware_length = 4094;
24// clang-format off
25const uint8_t firmware_data[] PROGMEM = { // SROM 0x04
260x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
270xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
280xc3, 0xe5, 0x29, 0xb1, 0xe0, 0x23, 0xa5, 0xa9, 0xb1, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0x1a,
290x97, 0x8d, 0x79, 0x51, 0x20, 0xc7, 0x06, 0x8e, 0x7c, 0x7c, 0x7a, 0x76, 0x4f, 0xfd, 0x59,
300x30, 0xe2, 0x46, 0x0e, 0x9e, 0xbe, 0xdf, 0x1d, 0x99, 0x91, 0xa0, 0xa5, 0xa1, 0xa9, 0xd0,
310x22, 0xc6, 0xef, 0x5c, 0x1b, 0x95, 0x89, 0x90, 0xa2, 0xa7, 0xcc, 0xfb, 0x55, 0x28, 0xb3,
320xe4, 0x4a, 0xf7, 0x6c, 0x3b, 0xf4, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0x9d, 0xb8, 0xd3, 0x05,
330x88, 0x92, 0xa6, 0xce, 0x1e, 0xbe, 0xdf, 0x1d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x5c, 0x07,
340x11, 0x5d, 0x98, 0x0b, 0x9d, 0x94, 0x97, 0xee, 0x4e, 0x45, 0x33, 0x6b, 0x44, 0xc7, 0x29,
350x56, 0x27, 0x30, 0xc6, 0xa7, 0xd5, 0xf2, 0x56, 0xdf, 0xb4, 0x38, 0x62, 0xcb, 0xa0, 0xb6,
360xe3, 0x0f, 0x84, 0x06, 0x24, 0x05, 0x65, 0x6f, 0x76, 0x89, 0xb5, 0x77, 0x41, 0x27, 0x82,
370x66, 0x65, 0x82, 0xcc, 0xd5, 0xe6, 0x20, 0xd5, 0x27, 0x17, 0xc5, 0xf8, 0x03, 0x23, 0x7c,
380x5f, 0x64, 0xa5, 0x1d, 0xc1, 0xd6, 0x36, 0xcb, 0x4c, 0xd4, 0xdb, 0x66, 0xd7, 0x8b, 0xb1,
390x99, 0x7e, 0x6f, 0x4c, 0x36, 0x40, 0x06, 0xd6, 0xeb, 0xd7, 0xa2, 0xe4, 0xf4, 0x95, 0x51,
400x5a, 0x54, 0x96, 0xd5, 0x53, 0x44, 0xd7, 0x8c, 0xe0, 0xb9, 0x40, 0x68, 0xd2, 0x18, 0xe9,
410xdd, 0x9a, 0x23, 0x92, 0x48, 0xee, 0x7f, 0x43, 0xaf, 0xea, 0x77, 0x38, 0x84, 0x8c, 0x0a,
420x72, 0xaf, 0x69, 0xf8, 0xdd, 0xf1, 0x24, 0x83, 0xa3, 0xf8, 0x4a, 0xbf, 0xf5, 0x94, 0x13,
430xdb, 0xbb, 0xd8, 0xb4, 0xb3, 0xa0, 0xfb, 0x45, 0x50, 0x60, 0x30, 0x59, 0x12, 0x31, 0x71,
440xa2, 0xd3, 0x13, 0xe7, 0xfa, 0xe7, 0xce, 0x0f, 0x63, 0x15, 0x0b, 0x6b, 0x94, 0xbb, 0x37,
450x83, 0x26, 0x05, 0x9d, 0xfb, 0x46, 0x92, 0xfc, 0x0a, 0x15, 0xd1, 0x0d, 0x73, 0x92, 0xd6,
460x8c, 0x1b, 0x8c, 0xb8, 0x55, 0x8a, 0xce, 0xbd, 0xfe, 0x8e, 0xfc, 0xed, 0x09, 0x12, 0x83,
470x91, 0x82, 0x51, 0x31, 0x23, 0xfb, 0xb4, 0x0c, 0x76, 0xad, 0x7c, 0xd9, 0xb4, 0x4b, 0xb2,
480x67, 0x14, 0x09, 0x9c, 0x7f, 0x0c, 0x18, 0xba, 0x3b, 0xd6, 0x8e, 0x14, 0x2a, 0xe4, 0x1b,
490x52, 0x9f, 0x2b, 0x7d, 0xe1, 0xfb, 0x6a, 0x33, 0x02, 0xfa, 0xac, 0x5a, 0xf2, 0x3e, 0x88,
500x7e, 0xae, 0xd1, 0xf3, 0x78, 0xe8, 0x05, 0xd1, 0xe3, 0xdc, 0x21, 0xf6, 0xe1, 0x9a, 0xbd,
510x17, 0x0e, 0xd9, 0x46, 0x9b, 0x88, 0x03, 0xea, 0xf6, 0x66, 0xbe, 0x0e, 0x1b, 0x50, 0x49,
520x96, 0x40, 0x97, 0xf1, 0xf1, 0xe4, 0x80, 0xa6, 0x6e, 0xe8, 0x77, 0x34, 0xbf, 0x29, 0x40,
530x44, 0xc2, 0xff, 0x4e, 0x98, 0xd3, 0x9c, 0xa3, 0x32, 0x2b, 0x76, 0x51, 0x04, 0x09, 0xe7,
540xa9, 0xd1, 0xa6, 0x32, 0xb1, 0x23, 0x53, 0xe2, 0x47, 0xab, 0xd6, 0xf5, 0x69, 0x5c, 0x3e,
550x5f, 0xfa, 0xae, 0x45, 0x20, 0xe5, 0xd2, 0x44, 0xff, 0x39, 0x32, 0x6d, 0xfd, 0x27, 0x57,
560x5c, 0xfd, 0xf0, 0xde, 0xc1, 0xb5, 0x99, 0xe5, 0xf5, 0x1c, 0x77, 0x01, 0x75, 0xc5, 0x6d,
570x58, 0x92, 0xf2, 0xb2, 0x47, 0x00, 0x01, 0x26, 0x96, 0x7a, 0x30, 0xff, 0xb7, 0xf0, 0xef,
580x77, 0xc1, 0x8a, 0x5d, 0xdc, 0xc0, 0xd1, 0x29, 0x30, 0x1e, 0x77, 0x38, 0x7a, 0x94, 0xf1,
590xb8, 0x7a, 0x7e, 0xef, 0xa4, 0xd1, 0xac, 0x31, 0x4a, 0xf2, 0x5d, 0x64, 0x3d, 0xb2, 0xe2,
600xf0, 0x08, 0x99, 0xfc, 0x70, 0xee, 0x24, 0xa7, 0x7e, 0xee, 0x1e, 0x20, 0x69, 0x7d, 0x44,
610xbf, 0x87, 0x42, 0xdf, 0x88, 0x3b, 0x0c, 0xda, 0x42, 0xc9, 0x04, 0xf9, 0x45, 0x50, 0xfc,
620x83, 0x8f, 0x11, 0x6a, 0x72, 0xbc, 0x99, 0x95, 0xf0, 0xac, 0x3d, 0xa7, 0x3b, 0xcd, 0x1c,
630xe2, 0x88, 0x79, 0x37, 0x11, 0x5f, 0x39, 0x89, 0x95, 0x0a, 0x16, 0x84, 0x7a, 0xf6, 0x8a,
640xa4, 0x28, 0xe4, 0xed, 0x83, 0x80, 0x3b, 0xb1, 0x23, 0xa5, 0x03, 0x10, 0xf4, 0x66, 0xea,
650xbb, 0x0c, 0x0f, 0xc5, 0xec, 0x6c, 0x69, 0xc5, 0xd3, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0x99,
660x88, 0x76, 0x08, 0xa0, 0xa8, 0x95, 0x7c, 0xd8, 0x38, 0x6d, 0xcd, 0x59, 0x02, 0x51, 0x4b,
670xf1, 0xb5, 0x2b, 0x50, 0xe3, 0xb6, 0xbd, 0xd0, 0x72, 0xcf, 0x9e, 0xfd, 0x6e, 0xbb, 0x44,
680xc8, 0x24, 0x8a, 0x77, 0x18, 0x8a, 0x13, 0x06, 0xef, 0x97, 0x7d, 0xfa, 0x81, 0xf0, 0x31,
690xe6, 0xfa, 0x77, 0xed, 0x31, 0x06, 0x31, 0x5b, 0x54, 0x8a, 0x9f, 0x30, 0x68, 0xdb, 0xe2,
700x40, 0xf8, 0x4e, 0x73, 0xfa, 0xab, 0x74, 0x8b, 0x10, 0x58, 0x13, 0xdc, 0xd2, 0xe6, 0x78,
710xd1, 0x32, 0x2e, 0x8a, 0x9f, 0x2c, 0x58, 0x06, 0x48, 0x27, 0xc5, 0xa9, 0x5e, 0x81, 0x47,
720x89, 0x46, 0x21, 0x91, 0x03, 0x70, 0xa4, 0x3e, 0x88, 0x9c, 0xda, 0x33, 0x0a, 0xce, 0xbc,
730x8b, 0x8e, 0xcf, 0x9f, 0xd3, 0x71, 0x80, 0x43, 0xcf, 0x6b, 0xa9, 0x51, 0x83, 0x76, 0x30,
740x82, 0xc5, 0x6a, 0x85, 0x39, 0x11, 0x50, 0x1a, 0x82, 0xdc, 0x1e, 0x1c, 0xd5, 0x7d, 0xa9,
750x71, 0x99, 0x33, 0x47, 0x19, 0x97, 0xb3, 0x5a, 0xb1, 0xdf, 0xed, 0xa4, 0xf2, 0xe6, 0x26,
760x84, 0xa2, 0x28, 0x9a, 0x9e, 0xdf, 0xa6, 0x6a, 0xf4, 0xd6, 0xfc, 0x2e, 0x5b, 0x9d, 0x1a,
770x2a, 0x27, 0x68, 0xfb, 0xc1, 0x83, 0x21, 0x4b, 0x90, 0xe0, 0x36, 0xdd, 0x5b, 0x31, 0x42,
780x55, 0xa0, 0x13, 0xf7, 0xd0, 0x89, 0x53, 0x71, 0x99, 0x57, 0x09, 0x29, 0xc5, 0xf3, 0x21,
790xf8, 0x37, 0x2f, 0x40, 0xf3, 0xd4, 0xaf, 0x16, 0x08, 0x36, 0x02, 0xfc, 0x77, 0xc5, 0x8b,
800x04, 0x90, 0x56, 0xb9, 0xc9, 0x67, 0x9a, 0x99, 0xe8, 0x00, 0xd3, 0x86, 0xff, 0x97, 0x2d,
810x08, 0xe9, 0xb7, 0xb3, 0x91, 0xbc, 0xdf, 0x45, 0xc6, 0xed, 0x0f, 0x8c, 0x4c, 0x1e, 0xe6,
820x5b, 0x6e, 0x38, 0x30, 0xe4, 0xaa, 0xe3, 0x95, 0xde, 0xb9, 0xe4, 0x9a, 0xf5, 0xb2, 0x55,
830x9a, 0x87, 0x9b, 0xf6, 0x6a, 0xb2, 0xf2, 0x77, 0x9a, 0x31, 0xf4, 0x7a, 0x31, 0xd1, 0x1d,
840x04, 0xc0, 0x7c, 0x32, 0xa2, 0x9e, 0x9a, 0xf5, 0x62, 0xf8, 0x27, 0x8d, 0xbf, 0x51, 0xff,
850xd3, 0xdf, 0x64, 0x37, 0x3f, 0x2a, 0x6f, 0x76, 0x3a, 0x7d, 0x77, 0x06, 0x9e, 0x77, 0x7f,
860x5e, 0xeb, 0x32, 0x51, 0xf9, 0x16, 0x66, 0x9a, 0x09, 0xf3, 0xb0, 0x08, 0xa4, 0x70, 0x96,
870x46, 0x30, 0xff, 0xda, 0x4f, 0xe9, 0x1b, 0xed, 0x8d, 0xf8, 0x74, 0x1f, 0x31, 0x92, 0xb3,
880x73, 0x17, 0x36, 0xdb, 0x91, 0x30, 0xd6, 0x88, 0x55, 0x6b, 0x34, 0x77, 0x87, 0x7a, 0xe7,
890xee, 0x06, 0xc6, 0x1c, 0x8c, 0x19, 0x0c, 0x48, 0x46, 0x23, 0x5e, 0x9c, 0x07, 0x5c, 0xbf,
900xb4, 0x7e, 0xd6, 0x4f, 0x74, 0x9c, 0xe2, 0xc5, 0x50, 0x8b, 0xc5, 0x8b, 0x15, 0x90, 0x60,
910x62, 0x57, 0x29, 0xd0, 0x13, 0x43, 0xa1, 0x80, 0x88, 0x91, 0x00, 0x44, 0xc7, 0x4d, 0x19,
920x86, 0xcc, 0x2f, 0x2a, 0x75, 0x5a, 0xfc, 0xeb, 0x97, 0x2a, 0x70, 0xe3, 0x78, 0xd8, 0x91,
930xb0, 0x4f, 0x99, 0x07, 0xa3, 0x95, 0xea, 0x24, 0x21, 0xd5, 0xde, 0x51, 0x20, 0x93, 0x27,
940x0a, 0x30, 0x73, 0xa8, 0xff, 0x8a, 0x97, 0xe9, 0xa7, 0x6a, 0x8e, 0x0d, 0xe8, 0xf0, 0xdf,
950xec, 0xea, 0xb4, 0x6c, 0x1d, 0x39, 0x2a, 0x62, 0x2d, 0x3d, 0x5a, 0x8b, 0x65, 0xf8, 0x90,
960x05, 0x2e, 0x7e, 0x91, 0x2c, 0x78, 0xef, 0x8e, 0x7a, 0xc1, 0x2f, 0xac, 0x78, 0xee, 0xaf,
970x28, 0x45, 0x06, 0x4c, 0x26, 0xaf, 0x3b, 0xa2, 0xdb, 0xa3, 0x93, 0x06, 0xb5, 0x3c, 0xa5,
980xd8, 0xee, 0x8f, 0xaf, 0x25, 0xcc, 0x3f, 0x85, 0x68, 0x48, 0xa9, 0x62, 0xcc, 0x97, 0x8f,
990x7f, 0x2a, 0xea, 0xe0, 0x15, 0x0a, 0xad, 0x62, 0x07, 0xbd, 0x45, 0xf8, 0x41, 0xd8, 0x36,
1000xcb, 0x4c, 0xdb, 0x6e, 0xe6, 0x3a, 0xe7, 0xda, 0x15, 0xe9, 0x29, 0x1e, 0x12, 0x10, 0xa0,
1010x14, 0x2c, 0x0e, 0x3d, 0xf4, 0xbf, 0x39, 0x41, 0x92, 0x75, 0x0b, 0x25, 0x7b, 0xa3, 0xce,
1020x39, 0x9c, 0x15, 0x64, 0xc8, 0xfa, 0x3d, 0xef, 0x73, 0x27, 0xfe, 0x26, 0x2e, 0xce, 0xda,
1030x6e, 0xfd, 0x71, 0x8e, 0xdd, 0xfe, 0x76, 0xee, 0xdc, 0x12, 0x5c, 0x02, 0xc5, 0x3a, 0x4e,
1040x4e, 0x4f, 0xbf, 0xca, 0x40, 0x15, 0xc7, 0x6e, 0x8d, 0x41, 0xf1, 0x10, 0xe0, 0x4f, 0x7e,
1050x97, 0x7f, 0x1c, 0xae, 0x47, 0x8e, 0x6b, 0xb1, 0x25, 0x31, 0xb0, 0x73, 0xc7, 0x1b, 0x97,
1060x79, 0xf9, 0x80, 0xd3, 0x66, 0x22, 0x30, 0x07, 0x74, 0x1e, 0xe4, 0xd0, 0x80, 0x21, 0xd6,
1070xee, 0x6b, 0x6c, 0x4f, 0xbf, 0xf5, 0xb7, 0xd9, 0x09, 0x87, 0x2f, 0xa9, 0x14, 0xbe, 0x27,
1080xd9, 0x72, 0x50, 0x01, 0xd4, 0x13, 0x73, 0xa6, 0xa7, 0x51, 0x02, 0x75, 0x25, 0xe1, 0xb3,
1090x45, 0x34, 0x7d, 0xa8, 0x8e, 0xeb, 0xf3, 0x16, 0x49, 0xcb, 0x4f, 0x8c, 0xa1, 0xb9, 0x36,
1100x85, 0x39, 0x75, 0x5d, 0x08, 0x00, 0xae, 0xeb, 0xf6, 0xea, 0xd7, 0x13, 0x3a, 0x21, 0x5a,
1110x5f, 0x30, 0x84, 0x52, 0x26, 0x95, 0xc9, 0x14, 0xf2, 0x57, 0x55, 0x6b, 0xb1, 0x10, 0xc2,
1120xe1, 0xbd, 0x3b, 0x51, 0xc0, 0xb7, 0x55, 0x4c, 0x71, 0x12, 0x26, 0xc7, 0x0d, 0xf9, 0x51,
1130xa4, 0x38, 0x02, 0x05, 0x7f, 0xb8, 0xf1, 0x72, 0x4b, 0xbf, 0x71, 0x89, 0x14, 0xf3, 0x77,
1140x38, 0xd9, 0x71, 0x24, 0xf3, 0x00, 0x11, 0xa1, 0xd8, 0xd4, 0x69, 0x27, 0x08, 0x37, 0x35,
1150xc9, 0x11, 0x9d, 0x90, 0x1c, 0x0e, 0xe7, 0x1c, 0xff, 0x2d, 0x1e, 0xe8, 0x92, 0xe1, 0x18,
1160x10, 0x95, 0x7c, 0xe0, 0x80, 0xf4, 0x96, 0x43, 0x21, 0xf9, 0x75, 0x21, 0x64, 0x38, 0xdd,
1170x9f, 0x1e, 0x95, 0x16, 0xda, 0x56, 0x1d, 0x4f, 0x9a, 0x53, 0xb2, 0xe2, 0xe4, 0x18, 0xcb,
1180x6b, 0x1a, 0x65, 0xeb, 0x56, 0xc6, 0x3b, 0xe5, 0xfe, 0xd8, 0x26, 0x3f, 0x3a, 0x84, 0x59,
1190x72, 0x66, 0xa2, 0xf3, 0x75, 0xff, 0xfb, 0x60, 0xb3, 0x22, 0xad, 0x3f, 0x2d, 0x6b, 0xf9,
1200xeb, 0xea, 0x05, 0x7c, 0xd8, 0x8f, 0x6d, 0x2c, 0x98, 0x9e, 0x2b, 0x93, 0xf1, 0x5e, 0x46,
1210xf0, 0x87, 0x49, 0x29, 0x73, 0x68, 0xd7, 0x7f, 0xf9, 0xf0, 0xe5, 0x7d, 0xdb, 0x1d, 0x75,
1220x19, 0xf3, 0xc4, 0x58, 0x9b, 0x17, 0x88, 0xa8, 0x92, 0xe0, 0xbe, 0xbd, 0x8b, 0x1d, 0x8d,
1230x9f, 0x56, 0x76, 0xad, 0xaf, 0x29, 0xe2, 0xd9, 0xd5, 0x52, 0xf6, 0xb5, 0x56, 0x35, 0x57,
1240x3a, 0xc8, 0xe1, 0x56, 0x43, 0x19, 0x94, 0xd3, 0x04, 0x9b, 0x6d, 0x35, 0xd8, 0x0b, 0x5f,
1250x4d, 0x19, 0x8e, 0xec, 0xfa, 0x64, 0x91, 0x0a, 0x72, 0x20, 0x2b, 0xbc, 0x1a, 0x4a, 0xfe,
1260x8b, 0xfd, 0xbb, 0xed, 0x1b, 0x23, 0xea, 0xad, 0x72, 0x82, 0xa1, 0x29, 0x99, 0x71, 0xbd,
1270xf0, 0x95, 0xc1, 0x03, 0xdd, 0x7b, 0xc2, 0xb2, 0x3c, 0x28, 0x54, 0xd3, 0x68, 0xa4, 0x72,
1280xc8, 0x66, 0x96, 0xe0, 0xd1, 0xd8, 0x7f, 0xf8, 0xd1, 0x26, 0x2b, 0xf7, 0xad, 0xba, 0x55,
1290xca, 0x15, 0xb9, 0x32, 0xc3, 0xe5, 0x88, 0x97, 0x8e, 0x5c, 0xfb, 0x92, 0x25, 0x8b, 0xbf,
1300xa2, 0x45, 0x55, 0x7a, 0xa7, 0x6f, 0x8b, 0x57, 0x5b, 0xcf, 0x0e, 0xcb, 0x1d, 0xfb, 0x20,
1310x82, 0x77, 0xa8, 0x8c, 0xcc, 0x16, 0xce, 0x1d, 0xfa, 0xde, 0xcc, 0x0b, 0x62, 0xfe, 0xcc,
1320xe1, 0xb7, 0xf0, 0xc3, 0x81, 0x64, 0x73, 0x40, 0xa0, 0xc2, 0x4d, 0x89, 0x11, 0x75, 0x33,
1330x55, 0x33, 0x8d, 0xe8, 0x4a, 0xfd, 0xea, 0x6e, 0x30, 0x0b, 0xd7, 0x31, 0x2c, 0xde, 0x47,
1340xe3, 0xbf, 0xf8, 0x55, 0x42, 0xe2, 0x7f, 0x59, 0xe5, 0x17, 0xef, 0x99, 0x34, 0x69, 0x91,
1350xb1, 0x23, 0x8e, 0x20, 0x87, 0x2d, 0xa8, 0xfe, 0xd5, 0x8a, 0xf3, 0x84, 0x3a, 0xf0, 0x37,
1360xe4, 0x09, 0x00, 0x54, 0xee, 0x67, 0x49, 0x93, 0xe4, 0x81, 0x70, 0xe3, 0x90, 0x4d, 0xef,
1370xfe, 0x41, 0xb7, 0x99, 0x7b, 0xc1, 0x83, 0xba, 0x62, 0x12, 0x6f, 0x7d, 0xde, 0x6b, 0xaf,
1380xda, 0x16, 0xf9, 0x55, 0x51, 0xee, 0xa6, 0x0c, 0x2b, 0x02, 0xa3, 0xfd, 0x8d, 0xfb, 0x30,
1390x17, 0xe4, 0x6f, 0xdf, 0x36, 0x71, 0xc4, 0xca, 0x87, 0x25, 0x48, 0xb0, 0x47, 0xec, 0xea,
1400xb4, 0xbf, 0xa5, 0x4d, 0x9b, 0x9f, 0x02, 0x93, 0xc4, 0xe3, 0xe4, 0xe8, 0x42, 0x2d, 0x68,
1410x81, 0x15, 0x0a, 0xeb, 0x84, 0x5b, 0xd6, 0xa8, 0x74, 0xfb, 0x7d, 0x1d, 0xcb, 0x2c, 0xda,
1420x46, 0x2a, 0x76, 0x62, 0xce, 0xbc, 0x5c, 0x9e, 0x8b, 0xe7, 0xcf, 0xbe, 0x78, 0xf5, 0x7c,
1430xeb, 0xb3, 0x3a, 0x9c, 0xaa, 0x6f, 0xcc, 0x72, 0xd1, 0x59, 0xf2, 0x11, 0x23, 0xd6, 0x3f,
1440x48, 0xd1, 0xb7, 0xce, 0xb0, 0xbf, 0xcb, 0xea, 0x80, 0xde, 0x57, 0xd4, 0x5e, 0x97, 0x2f,
1450x75, 0xd1, 0x50, 0x8e, 0x80, 0x2c, 0x66, 0x79, 0xbf, 0x72, 0x4b, 0xbd, 0x8a, 0x81, 0x6c,
1460xd3, 0xe1, 0x01, 0xdc, 0xd2, 0x15, 0x26, 0xc5, 0x36, 0xda, 0x2c, 0x1a, 0xc0, 0x27, 0x94,
1470xed, 0xb7, 0x9b, 0x85, 0x0b, 0x5e, 0x80, 0x97, 0xc5, 0xec, 0x4f, 0xec, 0x88, 0x5d, 0x50,
1480x07, 0x35, 0x47, 0xdc, 0x0b, 0x3b, 0x3d, 0xdd, 0x60, 0xaf, 0xa8, 0x5d, 0x81, 0x38, 0x24,
1490x25, 0x5d, 0x5c, 0x15, 0xd1, 0xde, 0xb3, 0xab, 0xec, 0x05, 0x69, 0xef, 0x83, 0xed, 0x57,
1500x54, 0xb8, 0x64, 0x64, 0x11, 0x16, 0x32, 0x69, 0xda, 0x9f, 0x2d, 0x7f, 0x36, 0xbb, 0x44,
1510x5a, 0x34, 0xe8, 0x7f, 0xbf, 0x03, 0xeb, 0x00, 0x7f, 0x59, 0x68, 0x22, 0x79, 0xcf, 0x73,
1520x6c, 0x2c, 0x29, 0xa7, 0xa1, 0x5f, 0x38, 0xa1, 0x1d, 0xf0, 0x20, 0x53, 0xe0, 0x1a, 0x63,
1530x14, 0x58, 0x71, 0x10, 0xaa, 0x08, 0x0c, 0x3e, 0x16, 0x1a, 0x60, 0x22, 0x82, 0x7f, 0xba,
1540xa4, 0x43, 0xa0, 0xd0, 0xac, 0x1b, 0xd5, 0x6b, 0x64, 0xb5, 0x14, 0x93, 0x31, 0x9e, 0x53,
1550x50, 0xd0, 0x57, 0x66, 0xee, 0x5a, 0x4f, 0xfb, 0x03, 0x2a, 0x69, 0x58, 0x76, 0xf1, 0x83,
1560xf7, 0x4e, 0xba, 0x8c, 0x42, 0x06, 0x60, 0x5d, 0x6d, 0xce, 0x60, 0x88, 0xae, 0xa4, 0xc3,
1570xf1, 0x03, 0xa5, 0x4b, 0x98, 0xa1, 0xff, 0x67, 0xe1, 0xac, 0xa2, 0xb8, 0x62, 0xd7, 0x6f,
1580xa0, 0x31, 0xb4, 0xd2, 0x77, 0xaf, 0x21, 0x10, 0x06, 0xc6, 0x9a, 0xff, 0x1d, 0x09, 0x17,
1590x0e, 0x5f, 0xf1, 0xaa, 0x54, 0x34, 0x4b, 0x45, 0x8a, 0x87, 0x63, 0xa6, 0xdc, 0xf9, 0x24,
1600x30, 0x67, 0xc6, 0xb2, 0xd6, 0x61, 0x33, 0x69, 0xee, 0x50, 0x61, 0x57, 0x28, 0xe7, 0x7e,
1610xee, 0xec, 0x3a, 0x5a, 0x73, 0x4e, 0xa8, 0x8d, 0xe4, 0x18, 0xea, 0xec, 0x41, 0x64, 0xc8,
1620xe2, 0xe8, 0x66, 0xb6, 0x2d, 0xb6, 0xfb, 0x6a, 0x6c, 0x16, 0xb3, 0xdd, 0x46, 0x43, 0xb9,
1630x73, 0x00, 0x6a, 0x71, 0xed, 0x4e, 0x9d, 0x25, 0x1a, 0xc3, 0x3c, 0x4a, 0x95, 0x15, 0x99,
1640x35, 0x81, 0x14, 0x02, 0xd6, 0x98, 0x9b, 0xec, 0xd8, 0x23, 0x3b, 0x84, 0x29, 0xaf, 0x0c,
1650x99, 0x83, 0xa6, 0x9a, 0x34, 0x4f, 0xfa, 0xe8, 0xd0, 0x3c, 0x4b, 0xd0, 0xfb, 0xb6, 0x68,
1660xb8, 0x9e, 0x8f, 0xcd, 0xf7, 0x60, 0x2d, 0x7a, 0x22, 0xe5, 0x7d, 0xab, 0x65, 0x1b, 0x95,
1670xa7, 0xa8, 0x7f, 0xb6, 0x77, 0x47, 0x7b, 0x5f, 0x8b, 0x12, 0x72, 0xd0, 0xd4, 0x91, 0xef,
1680xde, 0x19, 0x50, 0x3c, 0xa7, 0x8b, 0xc4, 0xa9, 0xb3, 0x23, 0xcb, 0x76, 0xe6, 0x81, 0xf0,
1690xc1, 0x04, 0x8f, 0xa3, 0xb8, 0x54, 0x5b, 0x97, 0xac, 0x19, 0xff, 0x3f, 0x55, 0x27, 0x2f,
1700xe0, 0x1d, 0x42, 0x9b, 0x57, 0xfc, 0x4b, 0x4e, 0x0f, 0xce, 0x98, 0xa9, 0x43, 0x57, 0x03,
1710xbd, 0xe7, 0xc8, 0x94, 0xdf, 0x6e, 0x36, 0x73, 0x32, 0xb4, 0xef, 0x2e, 0x85, 0x7a, 0x6e,
1720xfc, 0x6c, 0x18, 0x82, 0x75, 0x35, 0x90, 0x07, 0xf3, 0xe4, 0x9f, 0x3e, 0xdc, 0x68, 0xf3,
1730xb5, 0xf3, 0x19, 0x80, 0x92, 0x06, 0x99, 0xa2, 0xe8, 0x6f, 0xff, 0x2e, 0x7f, 0xae, 0x42,
1740xa4, 0x5f, 0xfb, 0xd4, 0x0e, 0x81, 0x2b, 0xc3, 0x04, 0xff, 0x2b, 0xb3, 0x74, 0x4e, 0x36,
1750x5b, 0x9c, 0x15, 0x00, 0xc6, 0x47, 0x2b, 0xe8, 0x8b, 0x3d, 0xf1, 0x9c, 0x03, 0x9a, 0x58,
1760x7f, 0x9b, 0x9c, 0xbf, 0x85, 0x49, 0x79, 0x35, 0x2e, 0x56, 0x7b, 0x41, 0x14, 0x39, 0x47,
1770x83, 0x26, 0xaa, 0x07, 0x89, 0x98, 0x11, 0x1b, 0x86, 0xe7, 0x73, 0x7a, 0xd8, 0x7d, 0x78,
1780x61, 0x53, 0xe9, 0x79, 0xf5, 0x36, 0x8d, 0x44, 0x92, 0x84, 0xf9, 0x13, 0x50, 0x58, 0x3b,
1790xa4, 0x6a, 0x36, 0x65, 0x49, 0x8e, 0x3c, 0x0e, 0xf1, 0x6f, 0xd2, 0x84, 0xc4, 0x7e, 0x8e,
1800x3f, 0x39, 0xae, 0x7c, 0x84, 0xf1, 0x63, 0x37, 0x8e, 0x3c, 0xcc, 0x3e, 0x44, 0x81, 0x45,
1810xf1, 0x4b, 0xb9, 0xed, 0x6b, 0x36, 0x5d, 0xbb, 0x20, 0x60, 0x1a, 0x0f, 0xa3, 0xaa, 0x55,
1820x77, 0x3a, 0xa9, 0xae, 0x37, 0x4d, 0xba, 0xb8, 0x86, 0x6b, 0xbc, 0x08, 0x50, 0xf6, 0xcc,
1830xa4, 0xbd, 0x1d, 0x40, 0x72, 0xa5, 0x86, 0xfa, 0xe2, 0x10, 0xae, 0x3d, 0x58, 0x4b, 0x97,
1840xf3, 0x43, 0x74, 0xa9, 0x9e, 0xeb, 0x21, 0xb7, 0x01, 0xa4, 0x86, 0x93, 0x97, 0xee, 0x2f,
1850x4f, 0x3b, 0x86, 0xa1, 0x41, 0x6f, 0x41, 0x26, 0x90, 0x78, 0x5c, 0x7f, 0x30, 0x38, 0x4b,
1860x3f, 0xaa, 0xec, 0xed, 0x5c, 0x6f, 0x0e, 0xad, 0x43, 0x87, 0xfd, 0x93, 0x35, 0xe6, 0x01,
1870xef, 0x41, 0x26, 0x90, 0x99, 0x9e, 0xfb, 0x19, 0x5b, 0xad, 0xd2, 0x91, 0x8a, 0xe0, 0x46,
1880xaf, 0x65, 0xfa, 0x4f, 0x84, 0xc1, 0xa1, 0x2d, 0xcf, 0x45, 0x8b, 0xd3, 0x85, 0x50, 0x55,
1890x7c, 0xf9, 0x67, 0x88, 0xd4, 0x4e, 0xe9, 0xd7, 0x6b, 0x61, 0x54, 0xa1, 0xa4, 0xa6, 0xa2,
1900xc2, 0xbf, 0x30, 0x9c, 0x40, 0x9f, 0x5f, 0xd7, 0x69, 0x2b, 0x24, 0x82, 0x5e, 0xd9, 0xd6,
1910xa7, 0x12, 0x54, 0x1a, 0xf7, 0x55, 0x9f, 0x76, 0x50, 0xa9, 0x95, 0x84, 0xe6, 0x6b, 0x6d,
1920xb5, 0x96, 0x54, 0xd6, 0xcd, 0xb3, 0xa1, 0x9b, 0x46, 0xa7, 0x94, 0x4d, 0xc4, 0x94, 0xb4,
1930x98, 0xe3, 0xe1, 0xe2, 0x34, 0xd5, 0x33, 0x16, 0x07, 0x54, 0xcd, 0xb7, 0x77, 0x53, 0xdb,
1940x4f, 0x4d, 0x46, 0x9d, 0xe9, 0xd4, 0x9c, 0x8a, 0x36, 0xb6, 0xb8, 0x38, 0x26, 0x6c, 0x0e,
1950xff, 0x9c, 0x1b, 0x43, 0x8b, 0x80, 0xcc, 0xb9, 0x3d, 0xda, 0xc7, 0xf1, 0x8a, 0xf2, 0x6d,
1960xb8, 0xd7, 0x74, 0x2f, 0x7e, 0x1e, 0xb7, 0xd3, 0x4a, 0xb4, 0xac, 0xfc, 0x79, 0x48, 0x6c,
1970xbc, 0x96, 0xb6, 0x94, 0x46, 0x57, 0x2d, 0xb0, 0xa3, 0xfc, 0x1e, 0xb9, 0x52, 0x60, 0x85,
1980x2d, 0x41, 0xd0, 0x43, 0x01, 0x1e, 0x1c, 0xd5, 0x7d, 0xfc, 0xf3, 0x96, 0x0d, 0xc7, 0xcb,
1990x2a, 0x29, 0x9a, 0x93, 0xdd, 0x88, 0x2d, 0x37, 0x5d, 0xaa, 0xfb, 0x49, 0x68, 0xa0, 0x9c,
2000x50, 0x86, 0x7f, 0x68, 0x56, 0x57, 0xf9, 0x79, 0x18, 0x39, 0xd4, 0xe0, 0x01, 0x84, 0x33,
2010x61, 0xca, 0xa5, 0xd2, 0xd6, 0xe4, 0xc9, 0x8a, 0x4a, 0x23, 0x44, 0x4e, 0xbc, 0xf0, 0xdc,
2020x24, 0xa1, 0xa0, 0xc4, 0xe2, 0x07, 0x3c, 0x10, 0xc4, 0xb5, 0x25, 0x4b, 0x65, 0x63, 0xf4,
2030x80, 0xe7, 0xcf, 0x61, 0xb1, 0x71, 0x82, 0x21, 0x87, 0x2c, 0xf5, 0x91, 0x00, 0x32, 0x0c,
2040xec, 0xa9, 0xb5, 0x9a, 0x74, 0x85, 0xe3, 0x36, 0x8f, 0x76, 0x4f, 0x9c, 0x6d, 0xce, 0xbc,
2050xad, 0x0a, 0x4b, 0xed, 0x76, 0x04, 0xcb, 0xc3, 0xb9, 0x33, 0x9e, 0x01, 0x93, 0x96, 0x69,
2060x7d, 0xc5, 0xa2, 0x45, 0x79, 0x9b, 0x04, 0x5c, 0x84, 0x09, 0xed, 0x88, 0x43, 0xc7, 0xab,
2070x93, 0x14, 0x26, 0xa1, 0x40, 0xb5, 0xce, 0x4e, 0xbf, 0x2a, 0x42, 0x85, 0x3e, 0x2c, 0x3b,
2080x54, 0xe8, 0x12, 0x1f, 0x0e, 0x97, 0x59, 0xb2, 0x27, 0x89, 0xfa, 0xf2, 0xdf, 0x8e, 0x68,
2090x59, 0xdc, 0x06, 0xbc, 0xb6, 0x85, 0x0d, 0x06, 0x22, 0xec, 0xb1, 0xcb, 0xe5, 0x04, 0xe6,
2100x3d, 0xb3, 0xb0, 0x41, 0x73, 0x08, 0x3f, 0x3c, 0x58, 0x86, 0x63, 0xeb, 0x50, 0xee, 0x1d,
2110x2c, 0x37, 0x74, 0xa9, 0xd3, 0x18, 0xa3, 0x47, 0x6e, 0x93, 0x54, 0xad, 0x0a, 0x5d, 0xb8,
2120x2a, 0x55, 0x5d, 0x78, 0xf6, 0xee, 0xbe, 0x8e, 0x3c, 0x76, 0x69, 0xb9, 0x40, 0xc2, 0x34,
2130xec, 0x2a, 0xb9, 0xed, 0x7e, 0x20, 0xe4, 0x8d, 0x00, 0x38, 0xc7, 0xe6, 0x8f, 0x44, 0xa8,
2140x86, 0xce, 0xeb, 0x2a, 0xe9, 0x90, 0xf1, 0x4c, 0xdf, 0x32, 0xfb, 0x73, 0x1b, 0x6d, 0x92,
2150x1e, 0x95, 0xfe, 0xb4, 0xdb, 0x65, 0xdf, 0x4d, 0x23, 0x54, 0x89, 0x48, 0xbf, 0x4a, 0x2e,
2160x70, 0xd6, 0xd7, 0x62, 0xb4, 0x33, 0x29, 0xb1, 0x3a, 0x33, 0x4c, 0x23, 0x6d, 0xa6, 0x76,
2170xa5, 0x21, 0x63, 0x48, 0xe6, 0x90, 0x5d, 0xed, 0x90, 0x95, 0x0b, 0x7a, 0x84, 0xbe, 0xb8,
2180x0d, 0x5e, 0x63, 0x0c, 0x62, 0x26, 0x4c, 0x14, 0x5a, 0xb3, 0xac, 0x23, 0xa4, 0x74, 0xa7,
2190x6f, 0x33, 0x30, 0x05, 0x60, 0x01, 0x42, 0xa0, 0x28, 0xb7, 0xee, 0x19, 0x38, 0xf1, 0x64,
2200x80, 0x82, 0x43, 0xe1, 0x41, 0x27, 0x1f, 0x1f, 0x90, 0x54, 0x7a, 0xd5, 0x23, 0x2e, 0xd1,
2210x3d, 0xcb, 0x28, 0xba, 0x58, 0x7f, 0xdc, 0x7c, 0x91, 0x24, 0xe9, 0x28, 0x51, 0x83, 0x6e,
2220xc5, 0x56, 0x21, 0x42, 0xed, 0xa0, 0x56, 0x22, 0xa1, 0x40, 0x80, 0x6b, 0xa8, 0xf7, 0x94,
2230xca, 0x13, 0x6b, 0x0c, 0x39, 0xd9, 0xfd, 0xe9, 0xf3, 0x6f, 0xa6, 0x9e, 0xfc, 0x70, 0x8a,
2240xb3, 0xbc, 0x59, 0x3c, 0x1e, 0x1d, 0x6c, 0xf9, 0x7c, 0xaf, 0xf9, 0x88, 0x71, 0x95, 0xeb,
2250x57, 0x00, 0xbd, 0x9f, 0x8c, 0x4f, 0xe1, 0x24, 0x83, 0xc5, 0x22, 0xea, 0xfd, 0xd3, 0x0c,
2260xe2, 0x17, 0x18, 0x7c, 0x6a, 0x4c, 0xde, 0x77, 0xb4, 0x53, 0x9b, 0x4c, 0x81, 0xcd, 0x23,
2270x60, 0xaa, 0x0e, 0x25, 0x73, 0x9c, 0x02, 0x79, 0x32, 0x30, 0xdf, 0x74, 0xdf, 0x75, 0x19,
2280xf4, 0xa5, 0x14, 0x5c, 0xf7, 0x7a, 0xa8, 0xa5, 0x91, 0x84, 0x7c, 0x60, 0x03, 0x06, 0x3b,
2290xcd, 0x50, 0xb6, 0x27, 0x9c, 0xfe, 0xb1, 0xdd, 0xcc, 0xd3, 0xb0, 0x59, 0x24, 0xb2, 0xca,
2300xe2, 0x1c, 0x81, 0x22, 0x9d, 0x07, 0x8f, 0x8e, 0xb9, 0xbe, 0x4e, 0xfa, 0xfc, 0x39, 0x65,
2310xba, 0xbf, 0x9d, 0x12, 0x37, 0x5e, 0x97, 0x7e, 0xf3, 0x89, 0xf5, 0x5d, 0xf5, 0xe3, 0x09,
2320x8c, 0x62, 0xb5, 0x20, 0x9d, 0x0c, 0x53, 0x8a, 0x68, 0x1b, 0xd2, 0x8f, 0x75, 0x17, 0x5d,
2330xd4, 0xe5, 0xda, 0x75, 0x62, 0x19, 0x14, 0x6a, 0x26, 0x2d, 0xeb, 0xf8, 0xaf, 0x37, 0xf0,
2340x6c, 0xa4, 0x55, 0xb1, 0xbc, 0xe2, 0x33, 0xc0, 0x9a, 0xca, 0xb0, 0x11, 0x49, 0x4f, 0x68,
2350x9b, 0x3b, 0x6b, 0x3c, 0xcc, 0x13, 0xf6, 0xc7, 0x85, 0x61, 0x68, 0x42, 0xae, 0xbb, 0xdd,
2360xcd, 0x45, 0x16, 0x29, 0x1d, 0xea, 0xdb, 0xc8, 0x03, 0x94, 0x3c, 0xee, 0x4f, 0x82, 0x11,
2370xc3, 0xec, 0x28, 0xbd, 0x97, 0x05, 0x99, 0xde, 0xd7, 0xbb, 0x5e, 0x22, 0x1f, 0xd4, 0xeb,
2380x64, 0xd9, 0x92, 0xd9, 0x85, 0xb7, 0x6a, 0x05, 0x6a, 0xe4, 0x24, 0x41, 0xf1, 0xcd, 0xf0,
2390xd8, 0x3f, 0xf8, 0x9e, 0x0e, 0xcd, 0x0b, 0x7a, 0x70, 0x6b, 0x5a, 0x75, 0x0a, 0x6a, 0x33,
2400x88, 0xec, 0x17, 0x75, 0x08, 0x70, 0x10, 0x2f, 0x24, 0xcf, 0xc4, 0xe9, 0x42, 0x00, 0x61,
2410x94, 0xca, 0x1f, 0x3a, 0x76, 0x06, 0xfa, 0xd2, 0x48, 0x81, 0xf0, 0x77, 0x60, 0x03, 0x45,
2420xd9, 0x61, 0xf4, 0xa4, 0x6f, 0x3d, 0xd9, 0x30, 0xc3, 0x04, 0x6b, 0x54, 0x2a, 0xb7, 0xec,
2430x3b, 0xf4, 0x4b, 0xf5, 0x68, 0x52, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xa5,
2440xa9, 0xb1, 0xe0, 0x23, 0xc4, 0x0a, 0x77, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xa5, 0xa9, 0xb1,
2450xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0xeb, 0x54, 0x0b,
2460x75, 0x68, 0x52, 0x07, 0x8c, 0x9a, 0x97, 0x8d, 0x79, 0x70, 0x62, 0x46, 0xef, 0x5c, 0x1b,
2470x95, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x67, 0x4c, 0x1a, 0xb6,
2480xcf, 0xfd, 0x78, 0x53, 0x24, 0xab, 0xb5, 0xc9, 0xf1, 0x60, 0x23, 0xa5, 0xc8, 0x12, 0x87,
2490x6d, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xc7, 0x0c, 0x9a, 0x97, 0xac,
2500xda, 0x36, 0xee, 0x5e, 0x3e, 0xdf, 0x1d, 0xb8, 0xf2, 0x66, 0x2f, 0xbd, 0xf8, 0x72, 0x47,
2510xed, 0x58, 0x13, 0x85, 0x88, 0x92, 0x87, 0x8c, 0x7b, 0x55, 0x09, 0x90, 0xa2, 0xc6, 0xef,
2520x3d, 0xf8, 0x53, 0x24, 0xab, 0xd4, 0x2a, 0xb7, 0xec, 0x5a, 0x36, 0xee, 0x5e, 0x3e, 0xdf,
2530x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x59, 0x30, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x53, 0x05, 0x69,
2540x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d, 0x19, 0xb0, 0xe2, 0x27, 0xcc, 0xfb, 0x74,
2550x4b, 0x14, 0x8b, 0x94, 0x8b, 0x75, 0x68, 0x33, 0xc5, 0x08, 0x92, 0x87, 0x8c, 0x9a, 0xb6,
2560xcf, 0x1c, 0xba, 0xd7, 0x0d, 0x98, 0xb2, 0xe6, 0x2f, 0xdc, 0x1b, 0x95, 0x89, 0x71, 0x60,
2570x23, 0xc4, 0x0a, 0x96, 0x8f, 0x9c, 0xba, 0xf6, 0x6e, 0x3f, 0xfc, 0x5b, 0x15, 0xa8, 0xd2,
2580x26, 0xaf, 0xbd, 0xf8, 0x72, 0x66, 0x2f, 0xdc, 0x1b, 0xb4, 0xcb, 0x14, 0x8b, 0x94, 0xaa,
2590xb7, 0xcd, 0xf9, 0x51, 0x01, 0x80, 0x82, 0x86, 0x6f, 0x3d, 0xd9, 0x30, 0xe2, 0x27, 0xcc,
2600xfb, 0x74, 0x4b, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x70, 0x43, 0x04, 0x6b, 0x35, 0xc9, 0xf1,
2610x60, 0x23, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87, 0x6d, 0x58, 0x32, 0xe6, 0x2f, 0xbd,
2620xf8, 0x72, 0x66, 0x4e, 0x1e, 0xbe, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x1d, 0x99, 0x91, 0xa0,
2630xa3, 0xc4, 0x0a, 0x77, 0x4d, 0x18, 0x93, 0xa4, 0xab, 0xd4, 0x0b, 0x75, 0x49, 0x10, 0xa2,
2640xc6, 0xef, 0x3d, 0xf8, 0x53, 0x24, 0xab, 0xb5, 0xe8, 0x33, 0xe4, 0x4a, 0x16, 0xae, 0xde,
2650x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xb3, 0xc5, 0x08, 0x73, 0x45, 0xe9, 0x31, 0xc1, 0xe1, 0x21,
2660xa1, 0xa1, 0xa1, 0xc0, 0x02, 0x86, 0x6f, 0x5c, 0x3a, 0xd7, 0x0d, 0x98, 0x93, 0xa4, 0xca,
2670x16, 0xae, 0xde, 0x1f, 0x9d, 0x99, 0xb0, 0xe2, 0x46, 0xef, 0x3d, 0xf8, 0x72, 0x47, 0x0c,
2680x9a, 0xb6, 0xcf, 0xfd, 0x59, 0x11, 0xa0, 0xa3, 0xa5, 0xc8, 0xf3, 0x45, 0x08, 0x92, 0x87,
2690x6d, 0x39, 0xf0, 0x43, 0x04, 0x8a, 0x96, 0xae, 0xde, 0x3e, 0xdf, 0x1d, 0x99, 0x91, 0xa0,
2700xc2, 0x06, 0x6f, 0x3d, 0xf8, 0x72, 0x47, 0x0c, 0x9a, 0x97, 0x8d, 0x98, 0x93, 0x85, 0x88,
2710x73, 0x45, 0xe9, 0x31, 0xe0, 0x23, 0xa5, 0xa9, 0xd0, 0x03, 0x84, 0x8a, 0x96, 0xae, 0xde,
2720x1f, 0xbc, 0xdb, 0x15, 0xa8, 0xd2, 0x26, 0xce, 0xff, 0x5d, 0x19, 0x91, 0x81, 0x80, 0x82,
2730x67, 0x2d, 0xd8, 0x13, 0xa4, 0xab, 0xd4, 0x0b, 0x94, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20,
2740xa3, 0xa5, 0xc8, 0xf3, 0x45, 0xe9, 0x50, 0x22, 0xc6, 0xef, 0x5c, 0x3a, 0xd7, 0x0d, 0x98,
2750x93, 0x85, 0x88, 0x73, 0x64, 0x4a, 0xf7, 0x4d, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0x0a, 0x96,
2760xae, 0xde, 0x3e, 0xfe, 0x7e, 0x7e, 0x7e, 0x5f, 0x3c, 0xfa, 0x76, 0x4f, 0xfd, 0x78, 0x72,
2770x66, 0x2f, 0xbd, 0xd9, 0x30, 0xc3, 0xe5, 0x48, 0x12, 0x87, 0x8c, 0x7b, 0x55, 0x28, 0xd2,
2780x07, 0x8c, 0x9a, 0x97, 0xac, 0xda, 0x17, 0x8d, 0x79, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x54,
2790x0b, 0x94, 0x8b, 0x94, 0xaa, 0xd6, 0x2e, 0xbf, 0xfc, 0x5b, 0x15, 0xa8, 0xd2, 0x26, 0xaf,
2800xdc, 0x1b, 0xb4, 0xea, 0x37, 0xec, 0x3b, 0xf4, 0x6a, 0x37, 0xcd, 0x18, 0x93, 0x85, 0x69,
2810x31, 0xc1, 0xe1, 0x40, 0xe3, 0x25, 0xc8, 0x12, 0x87, 0x8c, 0x9a, 0xb6, 0xcf, 0xfd, 0x59,
2820x11, 0xa0, 0xc2, 0x06, 0x8e, 0x7f, 0x5d, 0x38, 0xf2, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x37,
2830xec, 0x5a, 0x36, 0xee, 0x3f, 0xfc, 0x7a, 0x76, 0x4f, 0x1c, 0x9b, 0x95, 0x89, 0x71, 0x41,
2840x00, 0x63, 0x44, 0xeb, 0x54, 0x2a, 0xd6, 0x0f, 0x9c, 0xba, 0xd7, 0x0d, 0x98, 0x93, 0x85,
2850x69, 0x31, 0xc1, 0x00, 0x82, 0x86, 0x8e, 0x9e, 0xbe, 0xdf, 0x3c, 0xfa, 0x57, 0x2c, 0xda,
2860x36, 0xee, 0x3f, 0xfc, 0x5b, 0x15, 0x89, 0x71, 0x41, 0x00, 0x82, 0x86, 0x8e, 0x7f, 0x5d,
2870x38, 0xf2, 0x47, 0xed, 0x58, 0x13, 0xa4, 0xca, 0xf7, 0x4d, 0xf9, 0x51, 0x01, 0x80, 0x63,
2880x44, 0xeb, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0x91, 0xa0, 0xa3, 0xa5, 0xa9, 0xb1,
2890xe0, 0x42, 0x06, 0x8e, 0x7f, 0x5d, 0x19, 0x91, 0xa0, 0xa3, 0xc4, 0x0a, 0x96, 0x8f, 0x7d,
2900x78, 0x72, 0x47, 0x0c, 0x7b, 0x74, 0x6a, 0x56, 0x2e, 0xde, 0x1f, 0xbc, 0xfa, 0x57, 0x0d,
2910x79, 0x51, 0x01, 0x61, 0x21, 0xa1, 0xc0, 0xe3, 0x25, 0xa9, 0xb1, 0xc1, 0xe1, 0x40, 0x02,
2920x67, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0x93, 0xa4, 0xab, 0xd4, 0x2a, 0xd6, 0x0f, 0x9c, 0x9b,
2930xb4, 0xcb, 0x14, 0xaa, 0xb7, 0xcd, 0xf9, 0x51, 0x20, 0xa3, 0xc4, 0xeb, 0x35, 0xc9, 0xf1,
2940x60, 0x42, 0x06, 0x8e, 0x7f, 0x7c, 0x7a, 0x76, 0x6e, 0x3f, 0xfc, 0x7a, 0x76, 0x6e, 0x5e,
2950x3e, 0xfe, 0x7e, 0x5f, 0x3c, 0xdb, 0x15, 0x89, 0x71, 0x41, 0xe1, 0x21, 0xc0, 0xe3, 0x44,
2960xeb, 0x54, 0x2a, 0xb7, 0xcd, 0xf9, 0x70, 0x62, 0x27, 0xad, 0xd8, 0x32, 0xc7, 0x0c, 0x7b,
2970x74, 0x4b, 0x14, 0xaa, 0xb7, 0xec, 0x3b, 0xd5, 0x28, 0xd2, 0x07, 0x6d, 0x39, 0xd1, 0x20,
2980xc2, 0xe7, 0x4c, 0x1a, 0x97, 0x8d, 0x98, 0xb2, 0xc7, 0x0c, 0x59, 0x28, 0xf3, 0x9b };
299
300// clang-format off
diff --git a/keyboards/ploopyco/trackball/rules.mk b/keyboards/ploopyco/trackball/rules.mk
index e1eb998fe..4ac92ebf6 100644
--- a/keyboards/ploopyco/trackball/rules.mk
+++ b/keyboards/ploopyco/trackball/rules.mk
@@ -24,6 +24,6 @@ POINTING_DEVICE_ENABLE = yes
24MOUSEKEY_ENABLE = yes # Mouse keys 24MOUSEKEY_ENABLE = yes # Mouse keys
25 25
26QUANTUM_LIB_SRC += analog.c spi_master.c 26QUANTUM_LIB_SRC += analog.c spi_master.c
27SRC += pmw3360.c opt_encoder.c 27SRC += drivers/sensors/pmw3360.c opt_encoder.c
28 28
29DEFAULT_FOLDER = ploopyco/trackball/rev1_005 29DEFAULT_FOLDER = ploopyco/trackball/rev1_005
diff --git a/keyboards/ploopyco/trackball/trackball.h b/keyboards/ploopyco/trackball/trackball.h
index fd2bf465a..70f5d83b1 100644
--- a/keyboards/ploopyco/trackball/trackball.h
+++ b/keyboards/ploopyco/trackball/trackball.h
@@ -20,7 +20,7 @@
20 20
21#include "quantum.h" 21#include "quantum.h"
22#include "spi_master.h" 22#include "spi_master.h"
23#include "pmw3360.h" 23#include "drivers/sensors/pmw3360.h"
24#include "analog.h" 24#include "analog.h"
25#include "opt_encoder.h" 25#include "opt_encoder.h"
26#include "pointing_device.h" 26#include "pointing_device.h"
diff --git a/keyboards/ploopyco/trackball_mini/rules.mk b/keyboards/ploopyco/trackball_mini/rules.mk
index 58fad239f..22c5e3c06 100644
--- a/keyboards/ploopyco/trackball_mini/rules.mk
+++ b/keyboards/ploopyco/trackball_mini/rules.mk
@@ -27,6 +27,6 @@ POINTING_DEVICE_ENABLE = yes
27MOUSEKEY_ENABLE = no # Mouse keys 27MOUSEKEY_ENABLE = no # Mouse keys
28 28
29QUANTUM_LIB_SRC += analog.c 29QUANTUM_LIB_SRC += analog.c
30SRC += adns5050.c opt_encoder.c 30SRC += drivers/sensors/adns5050.c opt_encoder.c
31 31
32DEFAULT_FOLDER = ploopyco/trackball_mini/rev1_001 32DEFAULT_FOLDER = ploopyco/trackball_mini/rev1_001
diff --git a/keyboards/ploopyco/trackball_mini/trackball_mini.h b/keyboards/ploopyco/trackball_mini/trackball_mini.h
index a12d12a0c..7bcb02a94 100644
--- a/keyboards/ploopyco/trackball_mini/trackball_mini.h
+++ b/keyboards/ploopyco/trackball_mini/trackball_mini.h
@@ -20,7 +20,7 @@
20#pragma once 20#pragma once
21 21
22#include "quantum.h" 22#include "quantum.h"
23#include "adns5050.h" 23#include "drivers/sensors/adns5050.h"
24#include "analog.h" 24#include "analog.h"
25#include "opt_encoder.h" 25#include "opt_encoder.h"
26#include "pointing_device.h" 26#include "pointing_device.h"
diff --git a/keyboards/ploopyco/trackball_nano/rules.mk b/keyboards/ploopyco/trackball_nano/rules.mk
index 0286194b9..f47c31615 100644
--- a/keyboards/ploopyco/trackball_nano/rules.mk
+++ b/keyboards/ploopyco/trackball_nano/rules.mk
@@ -27,6 +27,6 @@ POINTING_DEVICE_ENABLE = yes
27MOUSEKEY_ENABLE = no # Mouse keys 27MOUSEKEY_ENABLE = no # Mouse keys
28 28
29QUANTUM_LIB_SRC += analog.c 29QUANTUM_LIB_SRC += analog.c
30SRC += adns5050.c opt_encoder.c 30SRC += drivers/sensors/adns5050.c opt_encoder.c
31 31
32DEFAULT_FOLDER = ploopyco/trackball_nano/rev1_001 32DEFAULT_FOLDER = ploopyco/trackball_nano/rev1_001
diff --git a/keyboards/ploopyco/trackball_nano/trackball_nano.h b/keyboards/ploopyco/trackball_nano/trackball_nano.h
index 5692383b1..6c8ecace7 100644
--- a/keyboards/ploopyco/trackball_nano/trackball_nano.h
+++ b/keyboards/ploopyco/trackball_nano/trackball_nano.h
@@ -20,7 +20,7 @@
20#pragma once 20#pragma once
21 21
22#include "quantum.h" 22#include "quantum.h"
23#include "adns5050.h" 23#include "drivers/sensors/adns5050.h"
24#include "analog.h" 24#include "analog.h"
25#include "opt_encoder.h" 25#include "opt_encoder.h"
26#include "pointing_device.h" 26#include "pointing_device.h"
diff --git a/keyboards/ramonimbao/chevron/info.json b/keyboards/ramonimbao/chevron/info.json
index 11ed02e53..2a88fedb1 100644
--- a/keyboards/ramonimbao/chevron/info.json
+++ b/keyboards/ramonimbao/chevron/info.json
@@ -1,7 +1,5 @@
1{ 1{
2 "keyboard_name": "Chevron", 2 "keyboard_name": "Chevron",
3 "url": "",
4 "maintainer": "",
5 "width": 14.5, 3 "width": 14.5,
6 "height": 5, 4 "height": 5,
7 "layouts": { 5 "layouts": {
diff --git a/keyboards/sendyyeah/75pixels/info.json b/keyboards/sendyyeah/75pixels/info.json
index 20d158cf7..d952cac13 100644
--- a/keyboards/sendyyeah/75pixels/info.json
+++ b/keyboards/sendyyeah/75pixels/info.json
@@ -7,7 +7,7 @@
7 "layouts": { 7 "layouts": {
8 "LAYOUT_ortho_5x15": { 8 "LAYOUT_ortho_5x15": {
9 "layout": [ 9 "layout": [
10 {"label": "Esc", "X": 0, "y": 0}, 10 {"label": "Esc", "x": 0, "y": 0},
11 {"label": "1", "x": 1, "y": 0}, 11 {"label": "1", "x": 1, "y": 0},
12 {"label": "2", "x": 2, "y": 0}, 12 {"label": "2", "x": 2, "y": 0},
13 {"label": "3", "x": 3, "y": 0}, 13 {"label": "3", "x": 3, "y": 0},
@@ -22,21 +22,21 @@
22 {"label": "NumLock", "x": 12, "y": 0}, 22 {"label": "NumLock", "x": 12, "y": 0},
23 {"label": "/", "x": 13, "y": 0}, 23 {"label": "/", "x": 13, "y": 0},
24 {"label": "*", "x": 14, "y": 0}, 24 {"label": "*", "x": 14, "y": 0},
25 {"label": "Tab", "X": 0, "y": 1}, 25 {"label": "Tab", "x": 0, "y": 1},
26 {"label": "Q", "X": 1, "y": 1}, 26 {"label": "Q", "x": 1, "y": 1},
27 {"label": "W", "X": 2, "y": 1}, 27 {"label": "W", "x": 2, "y": 1},
28 {"label": "E", "X": 3, "y": 1}, 28 {"label": "E", "x": 3, "y": 1},
29 {"label": "R", "X": 4, "y": 1}, 29 {"label": "R", "x": 4, "y": 1},
30 {"label": "T", "X": 5, "y": 1}, 30 {"label": "T", "x": 5, "y": 1},
31 {"label": "Y", "X": 6, "y": 1}, 31 {"label": "Y", "x": 6, "y": 1},
32 {"label": "U", "X": 7, "y": 1}, 32 {"label": "U", "x": 7, "y": 1},
33 {"label": "I", "X": 8, "y": 1}, 33 {"label": "I", "x": 8, "y": 1},
34 {"label": "O", "X": 9, "y": 1}, 34 {"label": "O", "x": 9, "y": 1},
35 {"label": "P", "X": 10, "y": 1}, 35 {"label": "P", "x": 10, "y": 1},
36 {"label": "|\n\\", "X": 11, "y": 1}, 36 {"label": "|\n\\", "x": 11, "y": 1},
37 {"label": "7\nHome", "X": 12, "y": 1}, 37 {"label": "7\nHome", "x": 12, "y": 1},
38 {"label": "8\nUp", "X": 13, "y": 1}, 38 {"label": "8\nUp", "x": 13, "y": 1},
39 {"label": "9\nPgUp", "X": 14, "y": 1}, 39 {"label": "9\nPgUp", "x": 14, "y": 1},
40 {"label": "Caps", "x": 0, "y": 2}, 40 {"label": "Caps", "x": 0, "y": 2},
41 {"label": "A", "x": 1, "y": 2}, 41 {"label": "A", "x": 1, "y": 2},
42 {"label": "S", "x": 2, "y": 2}, 42 {"label": "S", "x": 2, "y": 2},
@@ -67,21 +67,21 @@
67 {"label": "1\nEnd", "x": 12, "y": 3}, 67 {"label": "1\nEnd", "x": 12, "y": 3},
68 {"label": "2\nDown", "x": 13, "y": 3}, 68 {"label": "2\nDown", "x": 13, "y": 3},
69 {"label": "3\nPgDn", "x": 14, "y": 3}, 69 {"label": "3\nPgDn", "x": 14, "y": 3},
70 {"label": "Ctrl", "X": 0, "y": 4}, 70 {"label": "Ctrl", "x": 0, "y": 4},
71 {"label": "Win", "X": 1, "y": 4}, 71 {"label": "Win", "x": 1, "y": 4},
72 {"label": "Alt", "X": 2, "y": 4}, 72 {"label": "Alt", "x": 2, "y": 4},
73 {"label": "Fn", "X": 3, "y": 4}, 73 {"label": "Fn", "x": 3, "y": 4},
74 {"label": "Lower", "X": 4, "y": 4}, 74 {"label": "Lower", "x": 4, "y": 4},
75 {"label": "Space", "X": 5, "y": 4}, 75 {"label": "Space", "x": 5, "y": 4},
76 {"label": "Space", "X": 6, "y": 4}, 76 {"label": "Space", "x": 6, "y": 4},
77 {"label": "Raise", "X": 7, "y": 4}, 77 {"label": "Raise", "x": 7, "y": 4},
78 {"label": "Alt", "X": 8, "y": 4}, 78 {"label": "Alt", "x": 8, "y": 4},
79 {"label": "Win", "X": 9, "y": 4}, 79 {"label": "Win", "x": 9, "y": 4},
80 {"label": "Menu", "X": 10, "y": 4}, 80 {"label": "Menu", "x": 10, "y": 4},
81 {"label": "Ctrl", "X": 11, "y": 4}, 81 {"label": "Ctrl", "x": 11, "y": 4},
82 {"label": "0\nIns", "X": 12, "y": 4}, 82 {"label": "0\nIns", "x": 12, "y": 4},
83 {"label": ".\nDel", "X": 13, "y": 4}, 83 {"label": ".\nDel", "x": 13, "y": 4},
84 {"label": "Enter", "X": 14, "y": 4} 84 {"label": "Enter", "x": 14, "y": 4}
85 ] 85 ]
86 } 86 }
87 } 87 }
diff --git a/keyboards/setta21/keymaps/salicylic/config.h b/keyboards/setta21/keymaps/salicylic/config.h
index 44b34aa2f..06e23ba7a 100644
--- a/keyboards/setta21/keymaps/salicylic/config.h
+++ b/keyboards/setta21/keymaps/salicylic/config.h
@@ -27,7 +27,7 @@
27# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 27# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
28// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 28// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
29// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 29// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
30# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 30# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
31// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 31// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
32// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 32// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
33// # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 33// # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
@@ -37,4 +37,3 @@
37# define RGB_MATRIX_VAL_STEP 5 37# define RGB_MATRIX_VAL_STEP 5
38# define RGB_MATRIX_SPD_STEP 10 38# define RGB_MATRIX_SPD_STEP 10
39#endif 39#endif
40
diff --git a/keyboards/sofle/keymaps/devdev/config.h b/keyboards/sofle/keymaps/devdev/config.h
index 7d597d991..32d071735 100644
--- a/keyboards/sofle/keymaps/devdev/config.h
+++ b/keyboards/sofle/keymaps/devdev/config.h
@@ -1,18 +1,18 @@
1 /* Copyright 2021 Dane Evans 1 /* Copyright 2021 Dane Evans
2 * 2 *
3 * This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or 5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version. 6 * (at your option) any later version.
7 * 7 *
8 * This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details. 11 * GNU General Public License for more details.
12 * 12 *
13 * You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/ 15*/
16 #pragma once 16 #pragma once
17 17
18 18
@@ -29,7 +29,7 @@
29 29
30#define CUSTOM_FONT 30#define CUSTOM_FONT
31 31
32#define CUSTOM_LAYER_READ //if you remove this it causes issues - needs better guarding 32#define CUSTOM_LAYER_READ //if you remove this it causes issues - needs better guarding
33 33
34 34
35#define TAPPING_FORCE_HOLD 35#define TAPPING_FORCE_HOLD
@@ -56,7 +56,7 @@
56 56
57#ifdef RGBLIGHT_ENABLE 57#ifdef RGBLIGHT_ENABLE
58 #undef RGBLED_NUM 58 #undef RGBLED_NUM
59 59
60 //#define RGBLIGHT_ANIMATIONS 60 //#define RGBLIGHT_ANIMATIONS
61 //#define RGBLIGHT_EFFECT_BREATHING 61 //#define RGBLIGHT_EFFECT_BREATHING
62 #define RGBLIGHT_EFFECT_RAINBOW_MOOD 62 #define RGBLIGHT_EFFECT_RAINBOW_MOOD
@@ -68,11 +68,11 @@
68 //#define RGBLIGHT_EFFECT_RGB_TEST 68 //#define RGBLIGHT_EFFECT_RGB_TEST
69 //#define RGBLIGHT_EFFECT_ALTERNATING 69 //#define RGBLIGHT_EFFECT_ALTERNATING
70 //#define RGBLIGHT_EFFECT_TWINKLE 70 //#define RGBLIGHT_EFFECT_TWINKLE
71 71
72 #define RGBLED_NUM 70 72 #define RGBLED_NUM 70
73 //#define RGBLED_SPLIT 73 //#define RGBLED_SPLIT
74 #define RGBLED_SPLIT { 35, 35 } // haven't figured out how to use this yet 74 #define RGBLED_SPLIT { 35, 35 } // haven't figured out how to use this yet
75 75
76 //#define RGBLED_NUM 30 76 //#define RGBLED_NUM 30
77 #define RGBLIGHT_LIMIT_VAL 120 77 #define RGBLIGHT_LIMIT_VAL 120
78 #define RGBLIGHT_HUE_STEP 10 78 #define RGBLIGHT_HUE_STEP 10
@@ -84,11 +84,11 @@
84# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 84# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
85// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 85// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
86// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 86// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
87# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 87# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
88# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 88# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
89// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 89// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
90// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 90// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
91# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash. 91# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
92 92
93#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_GRADIENT_LEFT_RIGHT 93#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_GRADIENT_LEFT_RIGHT
94 94
@@ -127,4 +127,4 @@
127// # define DISABLE_RGB_MATRIX_MULTISPLASH 127// # define DISABLE_RGB_MATRIX_MULTISPLASH
128// # define DISABLE_RGB_MATRIX_SOLID_SPLASH 128// # define DISABLE_RGB_MATRIX_SOLID_SPLASH
129// # define DISABLE_RGB_MATRIX_SOLID_MULTISPLASH 129// # define DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
130#endif \ No newline at end of file 130#endif
diff --git a/keyboards/sofle/keymaps/killmaster/config.h b/keyboards/sofle/keymaps/killmaster/config.h
new file mode 100644
index 000000000..2e6abe84e
--- /dev/null
+++ b/keyboards/sofle/keymaps/killmaster/config.h
@@ -0,0 +1,64 @@
1/* Copyright 2021 Carlos Martins
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#pragma once
17
18/* The way how "handedness" is decided (which half is which),
19see https://docs.qmk.fm/#/feature_split_keyboard?id=setting-handedness
20for more options.
21*/
22
23#define RGB_DI_PIN D3
24
25#ifdef RGB_MATRIX_ENABLE
26
27#define RGBLED_NUM 72
28#define DRIVER_LED_TOTAL RGBLED_NUM
29#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 120 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
30#define RGB_MATRIX_HUE_STEP 8
31#define RGB_MATRIX_SAT_STEP 8
32#define RGB_MATRIX_VAL_STEP 8
33#define RGB_MATRIX_SPD_STEP 10
34#define RGB_MATRIX_KEYPRESSES
35#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
36#define RGB_MATRIX_SPLIT {36,36}
37#define SPLIT_TRANSPORT_MIRROR
38
39#endif
40
41#ifdef RGBLIGHT_ENABLE
42#define RGBLIGHT_SPLIT
43#define RGBLED_NUM 70
44#define RGB_SPLIT {36,36}
45#define RGBLIGHT_LIMIT_VAL 120
46// #define RGBLIGHT_SLEEP /* If defined, the RGB lighting will be switched off when the host goes to sleep */
47// /*== all animations enable ==*/
48// #define RGBLIGHT_ANIMATIONS
49// /*== or choose animations ==*/
50// #define RGBLIGHT_EFFECT_BREATHING
51 //#define RGBLIGHT_EFFECT_RAINBOW_MOOD
52 //#define RGBLIGHT_EFFECT_RAINBOW_SWIRL
53// #define RGBLIGHT_EFFECT_SNAKE
54// #define RGBLIGHT_EFFECT_KNIGHT
55// #define RGBLIGHT_EFFECT_CHRISTMAS
56 #define RGBLIGHT_EFFECT_STATIC_GRADIENT
57 #define RGBLIGHT_EFFECT_RGB_TEST
58// #define RGBLIGHT_EFFECT_ALTERNATING
59#endif
60
61#define MEDIA_KEY_DELAY 2
62
63#define USB_POLLING_INTERVAL_MS 1
64#define QMK_KEYS_PER_SCAN 12
diff --git a/keyboards/sofle/keymaps/killmaster/keymap.c b/keyboards/sofle/keymaps/killmaster/keymap.c
new file mode 100644
index 000000000..950dee36b
--- /dev/null
+++ b/keyboards/sofle/keymaps/killmaster/keymap.c
@@ -0,0 +1,403 @@
1/* Copyright 2021 Carlos Martins
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include QMK_KEYBOARD_H
18#include <stdio.h>
19
20enum sofle_layers {
21 /* _M_XYZ = Mac Os, _W_XYZ = Win/Linux */
22 _QWERTY,
23 _LOWER,
24 _RAISE,
25 _ADJUST,
26};
27
28enum custom_keycodes {
29 KC_QWERTY = SAFE_RANGE,
30 KC_LOWER,
31 KC_RAISE,
32 KC_ADJUST,
33 KC_PRVWD,
34 KC_NXTWD,
35 KC_LSTRT,
36 KC_LEND,
37 KC_DLINE
38};
39
40
41const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
42/*
43 * QWERTY
44 * ,-----------------------------------------. ,-----------------------------------------.
45 * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | ` |
46 * |------+------+------+------+------+------| |------+------+------+------+------+------|
47 * | ESC | Q | W | E | R | T | | Y | U | I | O | P | Bspc |
48 * |------+------+------+------+------+------| |------+------+------+------+------+------|
49 * | Tab | A | S | D | F | G |-------. ,-------| H | J | K | L | ; | ' |
50 * |------+------+------+------+------+------| | | |------+------+------+------+------+------|
51 * |LShift| Z | X | C | V | B |-------| |-------| N | M | , | . | / |RShift|
52 * `-----------------------------------------/ / \ \-----------------------------------------'
53 * | LGUI | LAlt | LCTR |LOWER | /Space / \Enter \ |RAISE | RCTR | RAlt | RGUI |
54 * | | | | |/ / \ \ | | | | |
55 * `----------------------------------' '------''---------------------------'
56 */
57
58[_QWERTY] = LAYOUT(
59 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
60 KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC,
61 KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
62 KC_LSPO, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_MUTE, KC_MPLY,KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSPC,
63 KC_LGUI,KC_LALT,KC_LCTRL, KC_LOWER, KC_SPC, KC_ENT, KC_RAISE, KC_RCTRL, KC_RALT, KC_RGUI
64),
65/* LOWER
66 * ,-----------------------------------------. ,-----------------------------------------.
67 * | | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 |
68 * |------+------+------+------+------+------| |------+------+------+------+------+------|
69 * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | F12 |
70 * |------+------+------+------+------+------| |------+------+------+------+------+------|
71 * | Tab | ! | @ | # | $ | % |-------. ,-------| ^ | & | * | ( | ) | | |
72 * |------+------+------+------+------+------| MUTE | | |------+------+------+------+------+------|
73 * | Shift| = | - | + | { | } |-------| |-------| [ | ] | ; | : | \ | Shift|
74 * `-----------------------------------------/ / \ \-----------------------------------------'
75 * | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
76 * | | | | |/ / \ \ | | | | |
77 * `----------------------------------' '------''---------------------------'
78 */
79[_LOWER] = LAYOUT(
80 _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
81 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_F12,
82 _______, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_PIPE,
83 _______, KC_EQL, KC_MINS, KC_PLUS, KC_LCBR, KC_RCBR, _______, _______, KC_LBRC, KC_RBRC, KC_SCLN, KC_COLN, KC_BSLS, _______,
84 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
85),
86/* RAISE
87 * ,----------------------------------------. ,-----------------------------------------.
88 * | | | | | | | | | | | | | |
89 * |------+------+------+------+------+------| |------+------+------+------+------+------|
90 * | Esc | Ins | Pscr | Menu | |RGBTog| | | PWrd | Up | NWrd | DLine| Bspc |
91 * |------+------+------+------+------+------| |------+------+------+------+------+------|
92 * | Tab | LAt | LCtl |LShift| | Caps |-------. ,-------| | Left | Down | Rigth| Del | Bspc |
93 * |------+------+------+------+------+------| MUTE | | |------+------+------+------+------+------|
94 * |Shift | Undo | Cut | Copy | Paste| |-------| |-------| | LStr | | LEnd | | Shift|
95 * `-----------------------------------------/ / \ \-----------------------------------------'
96 * | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
97 * | | | | |/ / \ \ | | | | |
98 * `----------------------------------' '------''---------------------------'
99 */
100[_RAISE] = LAYOUT(
101 _______, _______ , _______ , _______ , RGB_RMOD , RGB_MOD, _______, _______ , _______, _______ , _______ ,_______,
102 _______, KC_INS, KC_PSCR, KC_APP, XXXXXXX, RGB_TOG, KC_PGUP, KC_PRVWD, KC_UP, KC_NXTWD,KC_DLINE, KC_BSPC,
103 _______, KC_LALT, KC_LCTL, KC_LSFT, XXXXXXX, KC_CAPS, KC_PGDN, KC_LEFT, KC_DOWN, KC_RGHT, KC_DEL, KC_BSPC,
104 _______,XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, XXXXXXX, KC_LSTRT, XXXXXXX, KC_LEND, XXXXXXX, _______,
105 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
106),
107/* ADJUST
108 * ,-----------------------------------------. ,-----------------------------------------.
109 * | | | | | | | | | | | | | |
110 * |------+------+------+------+------+------| |------+------+------+------+------+------|
111 * | RESET| |QWERTY|COLEMAK| | | | | | | | | |
112 * |------+------+------+------+------+------| |------+------+------+------+------+------|
113 * | | |MACWIN| | | |-------. ,-------| | VOLDO| MUTE | VOLUP| | |
114 * |------+------+------+------+------+------| MUTE | | |------+------+------+------+------+------|
115 * | | | | | | |-------| |-------| | PREV | PLAY | NEXT | | |
116 * `-----------------------------------------/ / \ \-----------------------------------------'
117 * | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
118 * | | | | |/ / \ \ | | | | |
119 * `----------------------------------' '------''---------------------------'
120 */
121 [_ADJUST] = LAYOUT(
122 XXXXXXX , XXXXXXX, XXXXXXX , XXXXXXX , XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
123 RESET , XXXXXXX, KC_QWERTY, XXXXXXX , CG_TOGG,XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
124 XXXXXXX , XXXXXXX,CG_TOGG, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_VOLD, KC_MUTE, KC_VOLU, XXXXXXX, XXXXXXX,
125 XXXXXXX , XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_MPRV, KC_MPLY, KC_MNXT, XXXXXXX, XXXXXXX,
126 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
127 )
128};
129
130#ifdef OLED_DRIVER_ENABLE
131
132static void render_logo(void) {
133 static const char PROGMEM bananas_logo[] = {
134 // 'killmaster_bananas', 128x32px
135 0x00, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xe0, 0x02, 0x0e, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
145 0x00, 0x00, 0x80, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0xd8, 0xc8, 0x00, 0x00, 0x00, 0x00,
146 0x08, 0x08, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf8, 0xf8, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0xc0, 0x40, 0x40, 0xc0, 0x80, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40,
148 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0xc0, 0x40, 0x00, 0x00, 0x40, 0x40, 0xf0,
149 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0xc0, 0x80, 0x00, 0x00, 0x00,
150 0x40, 0xc0, 0x80, 0x40, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x01, 0x0f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xf0,
152 0xe0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
153 0x02, 0x07, 0x0d, 0x10, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x3f, 0x3f, 0x20, 0x20, 0x00, 0x00,
154 0x00, 0x00, 0x1f, 0x3f, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x3f, 0x20, 0x20, 0x20,
155 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x1c, 0x36, 0x22, 0x22, 0x22,
156 0x1f, 0x20, 0x00, 0x00, 0x10, 0x23, 0x22, 0x22, 0x26, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x1f,
157 0x30, 0x20, 0x20, 0x20, 0x00, 0x00, 0x0f, 0x1f, 0x32, 0x22, 0x22, 0x32, 0x23, 0x00, 0x00, 0x00,
158 0x20, 0x3f, 0x21, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x0f, 0x0f, 0x1f, 0x1f,
160 0x1f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3e, 0x3e, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
167 };
168 oled_write_raw_P(bananas_logo, sizeof(bananas_logo));
169}
170
171static void print_status_narrow(void) {
172 // Print current mode
173 oled_write_P(PSTR("Sofle"), false);
174 oled_write_P(PSTR("\n\n\n"), false);
175 switch (get_highest_layer(default_layer_state)) {
176 case _QWERTY:
177 oled_write_ln_P(PSTR("QWERT"), false);
178 break;
179 default:
180 oled_write_P(PSTR("Undef"), false);
181 }
182 oled_write_P(PSTR("\n\n"), false);
183 // Print current layer
184 oled_write_ln_P(PSTR("Layer"), false);
185 switch (get_highest_layer(layer_state)) {
186 case _QWERTY:
187 oled_write_P(PSTR("Base\n"), false);
188 break;
189 case _RAISE:
190 oled_write_P(PSTR("Raise"), false);
191 break;
192 case _LOWER:
193 oled_write_P(PSTR("Lower"), false);
194 break;
195 case _ADJUST:
196 oled_write_P(PSTR("Adj\n"), false);
197 break;
198 default:
199 oled_write_ln_P(PSTR("Undef"), false);
200 }
201 oled_write_P(PSTR("\n\n"), false);
202}
203
204oled_rotation_t oled_init_user(oled_rotation_t rotation) {
205 if (is_keyboard_master()) {
206 return OLED_ROTATION_270;
207 }
208 else {
209 return OLED_ROTATION_180;
210 }
211 return rotation;
212}
213
214void oled_task_user(void) {
215 if (is_keyboard_master()) {
216 print_status_narrow();
217 } else {
218 render_logo();
219 }
220}
221
222
223
224#endif // OLED_DRIVER_ENABLE
225
226bool process_record_user(uint16_t keycode, keyrecord_t *record) {
227 switch (keycode) {
228 case KC_QWERTY:
229 if (record->event.pressed) {
230 set_single_persistent_default_layer(_QWERTY);
231 }
232 return false;
233 case KC_LOWER:
234 if (record->event.pressed) {
235 layer_on(_LOWER);
236 update_tri_layer(_LOWER, _RAISE, _ADJUST);
237 } else {
238 layer_off(_LOWER);
239 update_tri_layer(_LOWER, _RAISE, _ADJUST);
240 }
241 return false;
242 case KC_RAISE:
243 if (record->event.pressed) {
244 layer_on(_RAISE);
245 update_tri_layer(_LOWER, _RAISE, _ADJUST);
246 } else {
247 layer_off(_RAISE);
248 update_tri_layer(_LOWER, _RAISE, _ADJUST);
249 }
250 return false;
251 case KC_ADJUST:
252 if (record->event.pressed) {
253 layer_on(_ADJUST);
254 } else {
255 layer_off(_ADJUST);
256 }
257 return false;
258 case KC_PRVWD:
259 if (record->event.pressed) {
260 if (keymap_config.swap_lctl_lgui) {
261 register_mods(mod_config(MOD_LALT));
262 register_code(KC_LEFT);
263 } else {
264 register_mods(mod_config(MOD_LCTL));
265 register_code(KC_LEFT);
266 }
267 } else {
268 if (keymap_config.swap_lctl_lgui) {
269 unregister_mods(mod_config(MOD_LALT));
270 unregister_code(KC_LEFT);
271 } else {
272 unregister_mods(mod_config(MOD_LCTL));
273 unregister_code(KC_LEFT);
274 }
275 }
276 break;
277 case KC_NXTWD:
278 if (record->event.pressed) {
279 if (keymap_config.swap_lctl_lgui) {
280 register_mods(mod_config(MOD_LALT));
281 register_code(KC_RIGHT);
282 } else {
283 register_mods(mod_config(MOD_LCTL));
284 register_code(KC_RIGHT);
285 }
286 } else {
287 if (keymap_config.swap_lctl_lgui) {
288 unregister_mods(mod_config(MOD_LALT));
289 unregister_code(KC_RIGHT);
290 } else {
291 unregister_mods(mod_config(MOD_LCTL));
292 unregister_code(KC_RIGHT);
293 }
294 }
295 break;
296 case KC_LSTRT:
297 if (record->event.pressed) {
298 if (keymap_config.swap_lctl_lgui) {
299 //CMD-arrow on Mac, but we have CTL and GUI swapped
300 register_mods(mod_config(MOD_LCTL));
301 register_code(KC_LEFT);
302 } else {
303 register_code(KC_HOME);
304 }
305 } else {
306 if (keymap_config.swap_lctl_lgui) {
307 unregister_mods(mod_config(MOD_LCTL));
308 unregister_code(KC_LEFT);
309 } else {
310 unregister_code(KC_HOME);
311 }
312 }
313 break;
314 case KC_LEND:
315 if (record->event.pressed) {
316 if (keymap_config.swap_lctl_lgui) {
317 //CMD-arrow on Mac, but we have CTL and GUI swapped
318 register_mods(mod_config(MOD_LCTL));
319 register_code(KC_RIGHT);
320 } else {
321 register_code(KC_END);
322 }
323 } else {
324 if (keymap_config.swap_lctl_lgui) {
325 unregister_mods(mod_config(MOD_LCTL));
326 unregister_code(KC_RIGHT);
327 } else {
328 unregister_code(KC_END);
329 }
330 }
331 break;
332 case KC_DLINE:
333 if (record->event.pressed) {
334 register_mods(mod_config(MOD_LCTL));
335 register_code(KC_BSPC);
336 } else {
337 unregister_mods(mod_config(MOD_LCTL));
338 unregister_code(KC_BSPC);
339 }
340 break;
341 }
342 return true;
343}
344
345#ifdef ENCODER_ENABLE
346
347bool encoder_update_user(uint8_t index, bool clockwise) {
348 uint8_t temp_mod = get_mods();
349 uint8_t temp_osm = get_oneshot_mods();
350 bool is_ctrl = (temp_mod | temp_osm) & MOD_MASK_CTRL;
351 bool is_shift = (temp_mod | temp_osm) & MOD_MASK_SHIFT;
352
353 if (is_shift) {
354 if (index == 0) { /* First encoder */
355 if (clockwise) {
356 rgb_matrix_increase_hue();
357 } else {
358 rgb_matrix_decrease_hue();
359 }
360 } else if (index == 1) { /* Second encoder */
361 if (clockwise) {
362 rgb_matrix_decrease_sat();
363 } else {
364 rgb_matrix_increase_sat();
365 }
366 }
367 } else if (is_ctrl) {
368 if (index == 0) { /* First encoder */
369 if (clockwise) {
370 rgb_matrix_increase_val();
371 } else {
372 rgb_matrix_decrease_val();
373 }
374 } else if (index == 1) { /* Second encoder */
375 if (clockwise) {
376 rgb_matrix_increase_speed();
377 } else {
378 rgb_matrix_decrease_speed();
379 }
380 }
381 } else {
382 if (index == 1) { /* First encoder */
383 if (clockwise) {
384 tap_code(KC_PGUP);
385 // tap_code(KC_MS_WH_UP);
386 } else {
387 tap_code(KC_PGDOWN);
388 // tap_code(KC_MS_WH_DOWN);
389 }
390 } else if (index == 0) { /* Second encoder */
391 uint16_t mapped_code = 0;
392 if (clockwise) {
393 mapped_code = KC_VOLD;
394 } else {
395 mapped_code = KC_VOLU;
396 }
397 tap_code_delay(mapped_code, MEDIA_KEY_DELAY);
398 }
399 }
400 return true;
401}
402
403#endif
diff --git a/keyboards/sofle/keymaps/killmaster/readme.md b/keyboards/sofle/keymaps/killmaster/readme.md
new file mode 100644
index 000000000..6d6dea228
--- /dev/null
+++ b/keyboards/sofle/keymaps/killmaster/readme.md
@@ -0,0 +1,19 @@
1![SofleKeyboard default keymap](https://github.com/josefadamcik/SofleKeyboard/raw/master/Images/soflekeyboard.png)
2![SofleKeyboard adjust layer](https://github.com/josefadamcik/SofleKeyboard/raw/master/Images/soflekeyboard_layout_adjust.png)
3
4
5# Default keymap for Sofle Keyboard
6
7Layout in [Keyboard Layout Editor](http://www.keyboard-layout-editor.com/#/gists/76efb423a46cbbea75465cb468eef7ff) and [adjust layer](http://www.keyboard-layout-editor.com/#/gists/4bcf66f922cfd54da20ba04905d56bd4)
8
9
10Features:
11
12- Symmetric modifiers (CMD/Super, Alt/Opt, Ctrl, Shift)
13- Various modes, can be switched (using Adjust layer and the selected one is stored in EEPROM.
14- Modes for Qwerty and Colemak support
15- Modes for Mac vs Linux/Win support -> different order of modifiers and different action shortcuts on the "UPPER" layer (the red one in the image). Designed to simplify transtions when switching between operating systems often.
16- The OLED on master half shows selected mode and caps lock state and is rotated.
17- Left encoder controls volume up/down/mute. Right encoder PGUP/PGDOWN.
18
19
diff --git a/keyboards/sofle/keymaps/killmaster/rules.mk b/keyboards/sofle/keymaps/killmaster/rules.mk
new file mode 100644
index 000000000..38d611450
--- /dev/null
+++ b/keyboards/sofle/keymaps/killmaster/rules.mk
@@ -0,0 +1,4 @@
1EXTRAKEY_ENABLE = yes
2LTO_ENABLE = yes
3RGB_MATRIX_ENABLE = yes
4RGB_MATRIX_DRIVER = WS2812
diff --git a/keyboards/sofle/keymaps/rgb_default/config.h b/keyboards/sofle/keymaps/rgb_default/config.h
index 7d597d991..32d071735 100644
--- a/keyboards/sofle/keymaps/rgb_default/config.h
+++ b/keyboards/sofle/keymaps/rgb_default/config.h
@@ -1,18 +1,18 @@
1 /* Copyright 2021 Dane Evans 1 /* Copyright 2021 Dane Evans
2 * 2 *
3 * This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or 5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version. 6 * (at your option) any later version.
7 * 7 *
8 * This program is distributed in the hope that it will be useful, 8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details. 11 * GNU General Public License for more details.
12 * 12 *
13 * You should have received a copy of the GNU General Public License 13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/ 15*/
16 #pragma once 16 #pragma once
17 17
18 18
@@ -29,7 +29,7 @@
29 29
30#define CUSTOM_FONT 30#define CUSTOM_FONT
31 31
32#define CUSTOM_LAYER_READ //if you remove this it causes issues - needs better guarding 32#define CUSTOM_LAYER_READ //if you remove this it causes issues - needs better guarding
33 33
34 34
35#define TAPPING_FORCE_HOLD 35#define TAPPING_FORCE_HOLD
@@ -56,7 +56,7 @@
56 56
57#ifdef RGBLIGHT_ENABLE 57#ifdef RGBLIGHT_ENABLE
58 #undef RGBLED_NUM 58 #undef RGBLED_NUM
59 59
60 //#define RGBLIGHT_ANIMATIONS 60 //#define RGBLIGHT_ANIMATIONS
61 //#define RGBLIGHT_EFFECT_BREATHING 61 //#define RGBLIGHT_EFFECT_BREATHING
62 #define RGBLIGHT_EFFECT_RAINBOW_MOOD 62 #define RGBLIGHT_EFFECT_RAINBOW_MOOD
@@ -68,11 +68,11 @@
68 //#define RGBLIGHT_EFFECT_RGB_TEST 68 //#define RGBLIGHT_EFFECT_RGB_TEST
69 //#define RGBLIGHT_EFFECT_ALTERNATING 69 //#define RGBLIGHT_EFFECT_ALTERNATING
70 //#define RGBLIGHT_EFFECT_TWINKLE 70 //#define RGBLIGHT_EFFECT_TWINKLE
71 71
72 #define RGBLED_NUM 70 72 #define RGBLED_NUM 70
73 //#define RGBLED_SPLIT 73 //#define RGBLED_SPLIT
74 #define RGBLED_SPLIT { 35, 35 } // haven't figured out how to use this yet 74 #define RGBLED_SPLIT { 35, 35 } // haven't figured out how to use this yet
75 75
76 //#define RGBLED_NUM 30 76 //#define RGBLED_NUM 30
77 #define RGBLIGHT_LIMIT_VAL 120 77 #define RGBLIGHT_LIMIT_VAL 120
78 #define RGBLIGHT_HUE_STEP 10 78 #define RGBLIGHT_HUE_STEP 10
@@ -84,11 +84,11 @@
84# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 84# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
85// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 85// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
86// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 86// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
87# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 87# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
88# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 88# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
89// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 89// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
90// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 90// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
91# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash. 91# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
92 92
93#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_GRADIENT_LEFT_RIGHT 93#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_GRADIENT_LEFT_RIGHT
94 94
@@ -127,4 +127,4 @@
127// # define DISABLE_RGB_MATRIX_MULTISPLASH 127// # define DISABLE_RGB_MATRIX_MULTISPLASH
128// # define DISABLE_RGB_MATRIX_SOLID_SPLASH 128// # define DISABLE_RGB_MATRIX_SOLID_SPLASH
129// # define DISABLE_RGB_MATRIX_SOLID_MULTISPLASH 129// # define DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
130#endif \ No newline at end of file 130#endif
diff --git a/keyboards/sofle/rev1/readme.md b/keyboards/sofle/rev1/readme.md
new file mode 100644
index 000000000..629d568e6
--- /dev/null
+++ b/keyboards/sofle/rev1/readme.md
@@ -0,0 +1,27 @@
1# Sofle Keyboard
2
3![SofleKeyboard version 1](https://raw.githubusercontent.com/josefadamcik/SofleKeyboard/master/Images/IMG_20200126_114622.jpg)
4
5Sofle is 6×4+5 keys column-staggered split keyboard. Based on Lily58, Corne and Helix keyboards.
6
7More details about the keyboard on my blog: [Let me introduce you SofleKeyboard - a split keyboard based on Lily58 and Crkbd](https://josef-adamcik.cz/electronics/let-me-introduce-you-sofle-keyboard-split-keyboard-based-on-lily58.html)
8
9The current (temporary) build guide and a build log is available here: [SofleKeyboard build log/guide](https://josef-adamcik.cz/electronics/soflekeyboard-build-log-and-build-guide.html)
10
11* Keyboard Maintainer: [Josef Adamcik](https://josef-adamcik.cz) [Twitter:@josefadamcik](https://twitter.com/josefadamcik)
12* Hardware Supported: SofleKeyboard PCB, ProMicro
13* Hardware Availability: [PCB & Case Data](https://github.com/josefadamcik/SofleKeyboard)
14
15Make example for this keyboard (after setting up your build environment):
16
17 make sofle:default
18
19Flashing example for this keyboard:
20
21 make sofle:default:flash
22
23Press reset button on he keyboard when asked.
24
25Disconnect the first half, connect the second one and repeat the process.
26
27See 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/keyboards/sofle/rev1/rev1.c b/keyboards/sofle/rev1/rev1.c
index bbb014c4d..88a28e6a4 100644
--- a/keyboards/sofle/rev1/rev1.c
+++ b/keyboards/sofle/rev1/rev1.c
@@ -1 +1,87 @@
1/* Copyright 2021 Carlos Martins
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
1#include "sofle.h" 17#include "sofle.h"
18
19#ifdef RGB_MATRIX_ENABLE
20 // Physical Layout
21 // Columns
22 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
23 // ROWS
24 // 12 13 22 23 32 33 33 32 23 22 13 12 0
25 // 02 03 04 04 03 02
26 // 11 14 21 24 31 34 34 31 24 21 14 11 1
27 // 01 01
28 // 10 15 20 25 30 35 35 30 25 20 15 10 2
29 //
30 // 09 16 19 26 29 36 36 29 26 19 16 09 3
31 //
32 // 08 17 18 27 28 28 27 18 17 08 4
33 // 07 06 05 05 06 07
34
35led_config_t g_led_config = {
36 {
37 { 11, 12, 21, 22, 31, 32 },
38 { 10, 13, 20, 23, 30, 33 },
39 { 9, 14, 19, 24, 29, 34},
40 { 8, 15, 18, 25, 28, 35},
41 { 7, 16, 17, 26, 27, NO_LED },
42 { 47, 48, 57, 58, 67, 68},
43 { 46, 49, 56, 59, 66, 69},
44 { 45, 50, 55, 60, 65, 70},
45 { 44, 51, 54, 61, 64, 71},
46 { 43, 52, 53, 62, 63, NO_LED }
47 },
48 {
49 // Left side underglow
50 {96, 40}, {16, 20}, {48, 10}, {80, 18}, {88, 60}, {56, 57}, {24,60},
51 // Left side Matrix
52 {32, 57}, { 0, 48}, { 0, 36}, { 0, 24}, { 0, 12},
53 {16, 12}, {16, 24}, {16, 36}, {16, 48}, {48, 55},
54 {64, 57}, {32, 45}, {32, 33}, {32, 21}, {32, 9},
55 {48, 7}, {48, 19}, {48, 31}, {48, 43}, {80, 59},
56 {96, 64}, {64, 45}, {64, 33}, {64, 21}, {64, 9},
57 {80, 10}, {80, 22}, {80, 34}, {80, 47},
58
59
60 // Right side underglow
61 {128, 40}, {208, 20}, {176, 10}, {144, 18}, {136, 60}, {168, 57}, {200,60},
62 // Right side Matrix
63 {192, 57}, {224, 48}, {224, 36}, {224, 24}, {224, 12},
64 {208, 12}, {208, 24}, {208, 36}, {208, 48}, {176, 55},
65 {160, 57}, {192, 45}, {192, 33}, {192, 21}, {192, 9},
66 {176, 7}, {176, 19}, {176, 31}, {176, 43}, {144, 59},
67 {128, 64}, {160, 45}, {160, 33}, {160, 21}, {160, 9},
68 {144, 10}, {144, 22}, {144, 34}, {144, 47},
69 },
70 {
71 LED_FLAG_NONE, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW,
72 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
73 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
74 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
75 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
76 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
77 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
78 LED_FLAG_NONE, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW,
79 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
80 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
81 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
82 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
83 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
84 LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT
85 }
86};
87#endif
diff --git a/keyboards/terrazzo/config.h b/keyboards/terrazzo/config.h
index 985110d16..907c94ff5 100644
--- a/keyboards/terrazzo/config.h
+++ b/keyboards/terrazzo/config.h
@@ -83,13 +83,13 @@ so there is only one configuration. */
83 83
84#ifdef LED_MATRIX_ENABLE 84#ifdef LED_MATRIX_ENABLE
85 85
86#define LED_DRIVER_ADDR_1 0x74 86#define LED_DRIVER_ADDR_1 0x74
87#define LED_DRIVER_COUNT 1 87#define LED_DRIVER_COUNT 1
88#define DRIVER_LED_TOTAL 105 88#define DRIVER_LED_TOTAL 105
89#define LED_MATRIX_ROWS 15 89#define LED_MATRIX_ROWS 15
90#define LED_MATRIX_COLS 7 90#define LED_MATRIX_COLS 7
91#define LED_MATRIX_MAXIMUM_BRIGHTNESS 20 91#define LED_MATRIX_MAXIMUM_BRIGHTNESS 20
92#define LED_DISABLE_WHEN_USB_SUSPENDED true 92#define LED_DISABLE_WHEN_USB_SUSPENDED
93 93
94#define DISABLE_LED_MATRIX_ALPHAS_MODS 94#define DISABLE_LED_MATRIX_ALPHAS_MODS
95#define DISABLE_LED_MATRIX_BREATHING 95#define DISABLE_LED_MATRIX_BREATHING
diff --git a/keyboards/tkc/portico/config.h b/keyboards/tkc/portico/config.h
index 4a7da833f..ef6e46658 100644
--- a/keyboards/tkc/portico/config.h
+++ b/keyboards/tkc/portico/config.h
@@ -45,7 +45,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
45# define RGB_MATRIX_LED_FLUSH_LIMIT 26 45# define RGB_MATRIX_LED_FLUSH_LIMIT 26
46# define DEBOUNCE 3 46# define DEBOUNCE 3
47# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 47# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
48# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 48# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
49# define RGB_MATRIX_KEYPRESSES 49# define RGB_MATRIX_KEYPRESSES
50# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 50# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
51# define DISABLE_RGB_MATRIX_BAND_SAT 51# define DISABLE_RGB_MATRIX_BAND_SAT
diff --git a/keyboards/tokyo60/config.h b/keyboards/tokyokeyboard/tokyo60/config.h
index 03dee74e9..03dee74e9 100644
--- a/keyboards/tokyo60/config.h
+++ b/keyboards/tokyokeyboard/tokyo60/config.h
diff --git a/keyboards/tokyo60/info.json b/keyboards/tokyokeyboard/tokyo60/info.json
index 10d1bf093..10d1bf093 100644
--- a/keyboards/tokyo60/info.json
+++ b/keyboards/tokyokeyboard/tokyo60/info.json
diff --git a/keyboards/tokyo60/keymaps/default/config.h b/keyboards/tokyokeyboard/tokyo60/keymaps/default/config.h
index 271f48d00..271f48d00 100644
--- a/keyboards/tokyo60/keymaps/default/config.h
+++ b/keyboards/tokyokeyboard/tokyo60/keymaps/default/config.h
diff --git a/keyboards/tokyo60/keymaps/default/keymap.c b/keyboards/tokyokeyboard/tokyo60/keymaps/default/keymap.c
index 9139d15bc..9139d15bc 100644
--- a/keyboards/tokyo60/keymaps/default/keymap.c
+++ b/keyboards/tokyokeyboard/tokyo60/keymaps/default/keymap.c
diff --git a/keyboards/tokyo60/keymaps/swappedBottomRow/config.h b/keyboards/tokyokeyboard/tokyo60/keymaps/swappedBottomRow/config.h
index 271f48d00..271f48d00 100644
--- a/keyboards/tokyo60/keymaps/swappedBottomRow/config.h
+++ b/keyboards/tokyokeyboard/tokyo60/keymaps/swappedBottomRow/config.h
diff --git a/keyboards/tokyo60/keymaps/swappedBottomRow/keymap.c b/keyboards/tokyokeyboard/tokyo60/keymaps/swappedBottomRow/keymap.c
index 54b68f582..54b68f582 100644
--- a/keyboards/tokyo60/keymaps/swappedBottomRow/keymap.c
+++ b/keyboards/tokyokeyboard/tokyo60/keymaps/swappedBottomRow/keymap.c
diff --git a/keyboards/tokyo60/keymaps/via/keymap.c b/keyboards/tokyokeyboard/tokyo60/keymaps/via/keymap.c
index ffef9af79..ffef9af79 100644
--- a/keyboards/tokyo60/keymaps/via/keymap.c
+++ b/keyboards/tokyokeyboard/tokyo60/keymaps/via/keymap.c
diff --git a/keyboards/tokyo60/keymaps/via/rules.mk b/keyboards/tokyokeyboard/tokyo60/keymaps/via/rules.mk
index 1e5b99807..1e5b99807 100644
--- a/keyboards/tokyo60/keymaps/via/rules.mk
+++ b/keyboards/tokyokeyboard/tokyo60/keymaps/via/rules.mk
diff --git a/keyboards/tokyo60/readme.md b/keyboards/tokyokeyboard/tokyo60/readme.md
index 11d4d353c..4d4f53ef0 100644
--- a/keyboards/tokyo60/readme.md
+++ b/keyboards/tokyokeyboard/tokyo60/readme.md
@@ -1,15 +1,15 @@
1# Tokyo60 1# Tokyo60
2 2
3![Tokyo60](http://tokyokeyboard.com/wp-content/uploads/2018/02/AI7B4543_copy_page_20180215141449-1200x800.jpg) 3![Tokyo60](https://i2.wp.com/tokyokeyboard.com/wp-content/uploads/2018/02/AI7B4543_copy_page_20180215141449-1200x800.jpg)
4 4
5Minimal hacker style mechanical keyboard designed in Tokyo. Full aluminum hi-pro construction with integrated top-plate. Cherry MX compatible. More Info at [Tokyo Keyboard](http://tokyokeyboard.com). 5Minimal hacker style mechanical keyboard designed in Tokyo. Full aluminum hi-pro construction with integrated top-plate. Cherry MX compatible. More Info at [Tokyo Keyboard](http://tokyokeyboard.com).
6 6
7* Keyboard Maintainer: [Tokyo Keyboard](http://tokyokeyboard.com) 7* Keyboard Maintainer: [Tokyo Keyboard](https://tokyokeyboard.com)
8* Hardware Supported: Tokyo60 Rev.1 8* Hardware Supported: Tokyo60 Rev.1 - 4
9* Hardware Availability: [Drop](https://drop.com/buy/massdrop-x-tokyo-keyboard-tokyo60-keyboard-kit?mode=guest_open) 9* Hardware Availability: [Drop](https://drop.com/buy/massdrop-x-tokyo-keyboard-tokyo60-keyboard-kit?mode=guest_open)
10 10
11Make example for this keyboard (after setting up your build environment): 11Make example for this keyboard (after setting up your build environment):
12 12
13 make tokyo60:default 13 make tokyokeyboard/tokyo60:default
14 14
15See 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). 15See 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/keyboards/tokyo60/rules.mk b/keyboards/tokyokeyboard/tokyo60/rules.mk
index fa639b1ca..fa639b1ca 100644
--- a/keyboards/tokyo60/rules.mk
+++ b/keyboards/tokyokeyboard/tokyo60/rules.mk
diff --git a/keyboards/tokyo60/tokyo60.c b/keyboards/tokyokeyboard/tokyo60/tokyo60.c
index 2126bb612..2126bb612 100644
--- a/keyboards/tokyo60/tokyo60.c
+++ b/keyboards/tokyokeyboard/tokyo60/tokyo60.c
diff --git a/keyboards/tokyo60/tokyo60.h b/keyboards/tokyokeyboard/tokyo60/tokyo60.h
index 9eb5f3e62..9eb5f3e62 100644
--- a/keyboards/tokyo60/tokyo60.h
+++ b/keyboards/tokyokeyboard/tokyo60/tokyo60.h
diff --git a/keyboards/whitefox/config.h b/keyboards/whitefox/config.h
index 4d7a460d2..1cdac01d0 100644
--- a/keyboards/whitefox/config.h
+++ b/keyboards/whitefox/config.h
@@ -62,6 +62,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
62#define LED_BRIGHTNESS_LO 100 62#define LED_BRIGHTNESS_LO 100
63#define LED_BRIGHTNESS_HI 255 63#define LED_BRIGHTNESS_HI 255
64 64
65/* LED matrix driver */
66#define LED_DRIVER_ADDR_1 0x74
67#define LED_DRIVER_COUNT 1
68#define DRIVER_LED_TOTAL 71
69#define LED_DISABLE_WHEN_USB_SUSPENDED
70
71/* i2c (for LED matrix) */
72#define I2C1_CLOCK_SPEED 400000
73#define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATIVE_2
74#define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATIVE_2
75#define I2C1_BANK GPIOB
76#define I2C1_SCL 0
77#define I2C1_SDA 1
78
65/* If defined, GRAVE_ESC will always act as ESC when CTRL is held. 79/* If defined, GRAVE_ESC will always act as ESC when CTRL is held.
66 * This is useful for the Windows task manager shortcut (ctrl+shift+esc). 80 * This is useful for the Windows task manager shortcut (ctrl+shift+esc).
67 */ 81 */
diff --git a/keyboards/whitefox/rules.mk b/keyboards/whitefox/rules.mk
index 771804369..7c1d0c3de 100644
--- a/keyboards/whitefox/rules.mk
+++ b/keyboards/whitefox/rules.mk
@@ -25,16 +25,12 @@ COMMAND_ENABLE = yes # Commands for debug and configuration
25SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend 25SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
26# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work 26# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
27NKRO_ENABLE = yes # USB Nkey Rollover 27NKRO_ENABLE = yes # USB Nkey Rollover
28BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
29RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow 28RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
30BLUETOOTH_ENABLE = no # Enable Bluetooth 29BLUETOOTH_ENABLE = no # Enable Bluetooth
31AUDIO_ENABLE = no # Audio output 30AUDIO_ENABLE = no # Audio output
32BACKLIGHT_DRIVER = custom
33VISUALIZER_ENABLE = yes
34 31
35LED_DRIVER = is31fl3731c 32LED_MATRIX_ENABLE = yes
36LED_WIDTH = 16 33LED_MATRIX_DRIVER = IS31FL3731
37LED_HEIGHT = 5
38 34
39LAYOUTS = 65_ansi 65_ansi_blocker 65_ansi_blocker_split_bs 65_iso 65_iso_blocker 65_iso_blocker_split_bs 35LAYOUTS = 65_ansi 65_ansi_blocker 65_ansi_blocker_split_bs 65_iso 65_iso_blocker 65_iso_blocker_split_bs
40 36
diff --git a/keyboards/whitefox/whitefox.c b/keyboards/whitefox/whitefox.c
index ea083c6e0..f10f0fd5c 100644
--- a/keyboards/whitefox/whitefox.c
+++ b/keyboards/whitefox/whitefox.c
@@ -16,3 +16,79 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17 17
18#include "whitefox.h" 18#include "whitefox.h"
19
20#ifdef LED_MATRIX_ENABLE
21const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
22// The numbers in the comments are the led numbers DXX on the PCB
23/* Refer to IS31 manual for these locations
24 * driver
25 * | LED address
26 * | | */
27// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
28 { 0, C1_1 }, { 0, C1_2 }, { 0, C1_3 }, { 0, C1_4 }, { 0, C1_5 }, { 0, C1_6 }, { 0, C1_7 }, { 0, C1_8 }, { 0, C2_1 }, { 0, C2_2 }, { 0, C2_3 }, { 0, C2_4 }, { 0, C2_5 }, { 0, C2_6 }, { 0, C2_7 }, { 0, C2_8 },
29// 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
30 { 0, C3_1 }, { 0, C3_2 }, { 0, C3_3 }, { 0, C3_4 }, { 0, C3_5 }, { 0, C3_6 }, { 0, C3_7 }, { 0, C3_8 }, { 0, C4_1 }, { 0, C4_2 }, { 0, C4_3 }, { 0, C4_4 }, { 0, C4_5 }, { 0, C4_6 }, { 0, C4_7 },
31// 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
32 { 0, C4_8 }, { 0, C5_1 }, { 0, C5_2 }, { 0, C5_3 }, { 0, C5_4 }, { 0, C5_5 }, { 0, C5_6 }, { 0, C5_7 }, { 0, C5_8 }, { 0, C6_1 }, { 0, C6_2 }, { 0, C6_3 }, { 0, C6_4 }, { 0, C6_5 }, { 0, C6_6 },
33// 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
34 { 0, C6_7 }, { 0, C6_8 }, { 0, C7_1 }, { 0, C7_2 }, { 0, C7_3 }, { 0, C7_4 }, { 0, C7_5 }, { 0, C7_6 }, { 0, C7_7 }, { 0, C7_8 }, { 0, C8_1 }, { 0, C8_2 }, { 0, C8_3 }, { 0, C8_4 }, { 0, C8_5 },
35// 62 63 64 65 66 67 68 69 70 71
36 { 0, C8_6 }, { 0, C8_7 }, { 0, C8_8 }, { 0, C9_1 }, { 0, C9_2 }, { 0, C9_3 }, { 0, C9_4 }, { 0, C9_5 }, { 0, C9_6 }, { 0, C9_7 },
37};
38
39led_config_t g_led_config = {
40 {
41 // Key Matrix to LED Index
42 { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
43 { 9, 10, 11, 12, 13, 14, 15, 16, 17 },
44 { 18, 19, 20, 21, 22, 23, 24, 25, 26 },
45 { 27, 28, 29, 30, 31, 32, 33, 34, 35 },
46 { 36, 37, 38, 39, 40, 41, 42, 43, 44 },
47 { 45, 46, 47, 48, 49, 50, 51, 52, 53 },
48 { 54, 55, 56, 57, 58, 59, 60, 61, 62 },
49 { 63, 64, 65, 66, 67, 68, 69, 70, NO_LED },
50 }, {
51 // LED Index to Physical Position
52 { 0, 0 }, { 15, 0 }, { 30, 0 }, { 45, 0 }, { 60, 0 }, { 75, 0 }, { 90, 0 }, { 105, 0 }, { 119, 0 }, { 134, 0 }, { 149, 0 }, { 164, 0 }, { 179, 0 }, { 194, 0 }, { 209, 0 }, { 224, 0 },
53 { 4, 16 }, { 22, 16 }, { 37, 16 }, { 52, 16 }, { 67, 16 }, { 82, 16 }, { 97, 16 }, { 112, 16 }, { 127, 16 }, { 142, 16 }, { 157, 16 }, { 172, 16 }, { 187, 16 }, { 205, 16 }, { 224, 16 },
54 { 6, 32 }, { 26, 32 }, { 41, 32 }, { 56, 32 }, { 71, 32 }, { 86, 32 }, { 101, 32 }, { 116, 32 }, { 131, 32 }, { 146, 32 }, { 161, 32 }, { 175, 32 }, { 190, 32 }, { 207, 32 }, { 224, 32 },
55 { 2, 48 }, { 19, 48 }, { 34, 48 }, { 49, 48 }, { 63, 48 }, { 78, 48 }, { 93, 48 }, { 108, 48 }, { 123, 48 }, { 138, 48 }, { 153, 48 }, { 168, 48 }, { 189, 48 }, { 209, 48 }, { 224, 48 },
56 { 2, 64 }, { 21, 64 }, { 39, 64 }, { 95, 64 }, { 149, 64 }, { 164, 64 }, { 179, 64 }, { 194, 64 }, { 209, 64 }, { 224, 64 }
57 }, {
58 // LED Index to Flag
59 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
60 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1,
61 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1,
62 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1,
63 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
64 }
65};
66#endif
67
68void keyboard_pre_init_kb(void) {
69#ifdef LED_MATRIX_ENABLE
70 // Turn on LED controller
71 setPinOutput(B16);
72 writePinHigh(B16);
73#endif
74 keyboard_pre_init_user();
75}
76
77void matrix_init_kb(void) {
78 // put your keyboard start-up code here
79 // runs once when the firmware starts up
80
81#ifdef LED_MATRIX_ENABLE
82 /*
83 * Since K20x is stuck with a 32 byte EEPROM (see tmk_core/common/chibios/eeprom_teensy.c),
84 * and neither led_matrix_eeconfig.speed or .flags fit in this boundary, just force their values to default on boot.
85 */
86# if !defined(LED_MATRIX_STARTUP_SPD)
87# define LED_MATRIX_STARTUP_SPD UINT8_MAX / 2
88# endif
89 led_matrix_set_speed(LED_MATRIX_STARTUP_SPD),
90 led_matrix_set_flags(LED_FLAG_ALL);
91#endif
92
93 matrix_init_user();
94}
diff --git a/keyboards/xbows/nature/config.h b/keyboards/xbows/nature/config.h
index c1ff79335..e321f7ee1 100644
--- a/keyboards/xbows/nature/config.h
+++ b/keyboards/xbows/nature/config.h
@@ -35,7 +35,7 @@
35# define RGB_MATRIX_LED_PROCESS_LIMIT 18 35# define RGB_MATRIX_LED_PROCESS_LIMIT 18
36# define RGB_MATRIX_LED_FLUSH_LIMIT 16 36# define RGB_MATRIX_LED_FLUSH_LIMIT 16
37# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 37# define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
38# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 38# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
39# define RGB_MATRIX_KEYPRESSES 39# define RGB_MATRIX_KEYPRESSES
40# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 40# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200
41# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 41# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
diff --git a/keyboards/xbows/woody/config.h b/keyboards/xbows/woody/config.h
index 7f396d000..ea27508da 100644
--- a/keyboards/xbows/woody/config.h
+++ b/keyboards/xbows/woody/config.h
@@ -16,10 +16,10 @@
16#define RGB_MATRIX_LED_FLUSH_LIMIT 26 16#define RGB_MATRIX_LED_FLUSH_LIMIT 26
17#define DEBOUNCE 3 17#define DEBOUNCE 3
18#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 18#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
19#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 19#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
20#define RGB_MATRIX_KEYPRESSES 20#define RGB_MATRIX_KEYPRESSES
21#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 21#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200
22#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 22#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
23#define DISABLE_RGB_MATRIX_BAND_SAT 23#define DISABLE_RGB_MATRIX_BAND_SAT
24#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT 24#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
25#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT 25#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
@@ -40,4 +40,4 @@
40#define DRIVER_1_LED_TOTAL 35 40#define DRIVER_1_LED_TOTAL 35
41#define DRIVER_2_LED_TOTAL 32 41#define DRIVER_2_LED_TOTAL 32
42#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL) 42#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
43#endif \ No newline at end of file 43#endif
diff --git a/keyboards/yncognito/batpad/config.h b/keyboards/yncognito/batpad/config.h
index 02c84a514..7ca4072e0 100644
--- a/keyboards/yncognito/batpad/config.h
+++ b/keyboards/yncognito/batpad/config.h
@@ -47,13 +47,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
47 47
48#define RGB_DI_PIN B5 48#define RGB_DI_PIN B5
49#define DRIVER_LED_TOTAL 8 49#define DRIVER_LED_TOTAL 8
50#define RGB_MATRIX_KEYPRESSES 50#define RGB_MATRIX_KEYPRESSES
51#define RGB_MATRIX_KEYRELEASES 51#define RGB_MATRIX_KEYRELEASES
52#define RGB_MATRIX_FRAMEBUFFER_EFFECTS 52#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
53#define RGB_DISABLE_AFTER_TIMEOUT 0 53#define RGB_DISABLE_AFTER_TIMEOUT 0
54#define RGB_DISABLE_WHEN_USB_SUSPENDED false 54// #define RGB_DISABLE_WHEN_USB_SUSPENDED
55#define RGB_MATRIX_LED_FLUSH_LIMIT 16 55#define RGB_MATRIX_LED_FLUSH_LIMIT 16
56#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 56#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255
57#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_ALL 57#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_ALL
58
59
diff --git a/layouts/community/ergodox/drashna/config.h b/layouts/community/ergodox/drashna/config.h
index 4ccba8f04..f9daf277f 100644
--- a/layouts/community/ergodox/drashna/config.h
+++ b/layouts/community/ergodox/drashna/config.h
@@ -47,3 +47,4 @@
47 47
48#define PIMORONI_TRACKBALL_INVERT_X 48#define PIMORONI_TRACKBALL_INVERT_X
49#define PIMORONI_TRACKBALL_INVERT_Y 49#define PIMORONI_TRACKBALL_INVERT_Y
50#define PIMORONI_TRACKBALL_CLICK
diff --git a/layouts/community/ortho_4x12/bocaj/config.h b/layouts/community/ortho_4x12/bocaj/config.h
index 9a65684f3..c9d297f92 100644
--- a/layouts/community/ortho_4x12/bocaj/config.h
+++ b/layouts/community/ortho_4x12/bocaj/config.h
@@ -24,7 +24,7 @@
24# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 24# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
25// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 25// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
26// #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 26// #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
27# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 27# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
28# undef RGB_MATRIX_LED_PROCESS_LIMIT 28# undef RGB_MATRIX_LED_PROCESS_LIMIT
29# undef RGB_MATRIX_LED_FLUSH_LIMIT 29# undef RGB_MATRIX_LED_FLUSH_LIMIT
30#endif 30#endif
diff --git a/layouts/community/ortho_4x12/drashna/config.h b/layouts/community/ortho_4x12/drashna/config.h
index f4abd64f5..43143c3a3 100644
--- a/layouts/community/ortho_4x12/drashna/config.h
+++ b/layouts/community/ortho_4x12/drashna/config.h
@@ -37,7 +37,7 @@
37# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 37# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
38// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 38// #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
39// #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 39// #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
40# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 40# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
41# undef RGB_MATRIX_LED_PROCESS_LIMIT 41# undef RGB_MATRIX_LED_PROCESS_LIMIT
42# undef RGB_MATRIX_LED_FLUSH_LIMIT 42# undef RGB_MATRIX_LED_FLUSH_LIMIT
43# ifdef KEYBOARD_planck_rev6 43# ifdef KEYBOARD_planck_rev6
diff --git a/layouts/community/split_3x6_3/drashna/config.h b/layouts/community/split_3x6_3/drashna/config.h
index dd950ce7b..cc53d4c36 100644
--- a/layouts/community/split_3x6_3/drashna/config.h
+++ b/layouts/community/split_3x6_3/drashna/config.h
@@ -47,7 +47,7 @@
47# define RGB_MATRIX_KEYPRESSES // reacts to keypresses 47# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
48// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) 48// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
49// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 49// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
50# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 50# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
51// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) 51// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
52// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 52// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
53# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 120 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 53# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 120 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
diff --git a/lib/chibios b/lib/chibios
Subproject ffe54d63cb10a355add318f8e922e39f1c3d4bf Subproject 413e39c5681d181720440f2a8b7391f581788d7
diff --git a/lib/chibios-contrib b/lib/chibios-contrib
Subproject 61baa6b036138c155f7cfc5646d833d9423f324 Subproject 9c2bfa6aeba993345f5425d82807c101f8e25e6
diff --git a/lib/python/qmk/cli/doctor/__init__.py b/lib/python/qmk/cli/doctor/__init__.py
new file mode 100755
index 000000000..272e04202
--- /dev/null
+++ b/lib/python/qmk/cli/doctor/__init__.py
@@ -0,0 +1,5 @@
1"""QMK Doctor
2
3Check out the user's QMK environment and make sure it's ready to compile.
4"""
5from .main import doctor
diff --git a/lib/python/qmk/os_helpers/__init__.py b/lib/python/qmk/cli/doctor/check.py
index 3e98db3c3..a0bbb2816 100644
--- a/lib/python/qmk/os_helpers/__init__.py
+++ b/lib/python/qmk/cli/doctor/check.py
@@ -1,4 +1,4 @@
1"""OS-agnostic helper functions 1"""Check for specific programs.
2""" 2"""
3from enum import Enum 3from enum import Enum
4import re 4import re
@@ -30,7 +30,7 @@ ESSENTIAL_BINARIES = {
30} 30}
31 31
32 32
33def parse_gcc_version(version): 33def _parse_gcc_version(version):
34 m = re.match(r"(\d+)(?:\.(\d+))?(?:\.(\d+))?", version) 34 m = re.match(r"(\d+)(?:\.(\d+))?(?:\.(\d+))?", version)
35 35
36 return { 36 return {
@@ -40,7 +40,7 @@ def parse_gcc_version(version):
40 } 40 }
41 41
42 42
43def check_arm_gcc_version(): 43def _check_arm_gcc_version():
44 """Returns True if the arm-none-eabi-gcc version is not known to cause problems. 44 """Returns True if the arm-none-eabi-gcc version is not known to cause problems.
45 """ 45 """
46 if 'output' in ESSENTIAL_BINARIES['arm-none-eabi-gcc']: 46 if 'output' in ESSENTIAL_BINARIES['arm-none-eabi-gcc']:
@@ -50,7 +50,7 @@ def check_arm_gcc_version():
50 return CheckStatus.OK # Right now all known arm versions are ok 50 return CheckStatus.OK # Right now all known arm versions are ok
51 51
52 52
53def check_avr_gcc_version(): 53def _check_avr_gcc_version():
54 """Returns True if the avr-gcc version is not known to cause problems. 54 """Returns True if the avr-gcc version is not known to cause problems.
55 """ 55 """
56 rc = CheckStatus.ERROR 56 rc = CheckStatus.ERROR
@@ -60,7 +60,7 @@ def check_avr_gcc_version():
60 cli.log.info('Found avr-gcc version %s', version_number) 60 cli.log.info('Found avr-gcc version %s', version_number)
61 rc = CheckStatus.OK 61 rc = CheckStatus.OK
62 62
63 parsed_version = parse_gcc_version(version_number) 63 parsed_version = _parse_gcc_version(version_number)
64 if parsed_version['major'] > 8: 64 if parsed_version['major'] > 8:
65 cli.log.warning('{fg_yellow}We do not recommend avr-gcc newer than 8. Downgrading to 8.x is recommended.') 65 cli.log.warning('{fg_yellow}We do not recommend avr-gcc newer than 8. Downgrading to 8.x is recommended.')
66 rc = CheckStatus.WARNING 66 rc = CheckStatus.WARNING
@@ -68,7 +68,7 @@ def check_avr_gcc_version():
68 return rc 68 return rc
69 69
70 70
71def check_avrdude_version(): 71def _check_avrdude_version():
72 if 'output' in ESSENTIAL_BINARIES['avrdude']: 72 if 'output' in ESSENTIAL_BINARIES['avrdude']:
73 last_line = ESSENTIAL_BINARIES['avrdude']['output'].split('\n')[-2] 73 last_line = ESSENTIAL_BINARIES['avrdude']['output'].split('\n')[-2]
74 version_number = last_line.split()[2][:-1] 74 version_number = last_line.split()[2][:-1]
@@ -77,7 +77,7 @@ def check_avrdude_version():
77 return CheckStatus.OK 77 return CheckStatus.OK
78 78
79 79
80def check_dfu_util_version(): 80def _check_dfu_util_version():
81 if 'output' in ESSENTIAL_BINARIES['dfu-util']: 81 if 'output' in ESSENTIAL_BINARIES['dfu-util']:
82 first_line = ESSENTIAL_BINARIES['dfu-util']['output'].split('\n')[0] 82 first_line = ESSENTIAL_BINARIES['dfu-util']['output'].split('\n')[0]
83 version_number = first_line.split()[1] 83 version_number = first_line.split()[1]
@@ -86,7 +86,7 @@ def check_dfu_util_version():
86 return CheckStatus.OK 86 return CheckStatus.OK
87 87
88 88
89def check_dfu_programmer_version(): 89def _check_dfu_programmer_version():
90 if 'output' in ESSENTIAL_BINARIES['dfu-programmer']: 90 if 'output' in ESSENTIAL_BINARIES['dfu-programmer']:
91 first_line = ESSENTIAL_BINARIES['dfu-programmer']['output'].split('\n')[0] 91 first_line = ESSENTIAL_BINARIES['dfu-programmer']['output'].split('\n')[0]
92 version_number = first_line.split()[1] 92 version_number = first_line.split()[1]
@@ -111,7 +111,7 @@ def check_binary_versions():
111 """Check the versions of ESSENTIAL_BINARIES 111 """Check the versions of ESSENTIAL_BINARIES
112 """ 112 """
113 versions = [] 113 versions = []
114 for check in (check_arm_gcc_version, check_avr_gcc_version, check_avrdude_version, check_dfu_util_version, check_dfu_programmer_version): 114 for check in (_check_arm_gcc_version, _check_avr_gcc_version, _check_avrdude_version, _check_dfu_util_version, _check_dfu_programmer_version):
115 versions.append(check()) 115 versions.append(check())
116 return versions 116 return versions
117 117
diff --git a/lib/python/qmk/os_helpers/linux/__init__.py b/lib/python/qmk/cli/doctor/linux.py
index 008654ab0..c0b77216a 100644
--- a/lib/python/qmk/os_helpers/linux/__init__.py
+++ b/lib/python/qmk/cli/doctor/linux.py
@@ -1,11 +1,13 @@
1"""OS-specific functions for: Linux 1"""OS-specific functions for: Linux
2""" 2"""
3from pathlib import Path 3import platform
4import shutil 4import shutil
5from pathlib import Path
5 6
6from milc import cli 7from milc import cli
8
7from qmk.constants import QMK_FIRMWARE 9from qmk.constants import QMK_FIRMWARE
8from qmk.os_helpers import CheckStatus 10from .check import CheckStatus
9 11
10 12
11def _udev_rule(vid, pid=None, *args): 13def _udev_rule(vid, pid=None, *args):
@@ -138,3 +140,23 @@ def check_modem_manager():
138 """(TODO): Add check for non-systemd systems 140 """(TODO): Add check for non-systemd systems
139 """ 141 """
140 return False 142 return False
143
144
145def os_test_linux():
146 """Run the Linux specific tests.
147 """
148 # Don't bother with udev on WSL, for now
149 if 'microsoft' in platform.uname().release.lower():
150 cli.log.info("Detected {fg_cyan}Linux (WSL){fg_reset}.")
151
152 # https://github.com/microsoft/WSL/issues/4197
153 if QMK_FIRMWARE.as_posix().startswith("/mnt"):
154 cli.log.warning("I/O performance on /mnt may be extremely slow.")
155 return CheckStatus.WARNING
156
157 return CheckStatus.OK
158 else:
159 cli.log.info("Detected {fg_cyan}Linux{fg_reset}.")
160 from .linux import check_udev_rules
161
162 return check_udev_rules()
diff --git a/lib/python/qmk/cli/doctor/macos.py b/lib/python/qmk/cli/doctor/macos.py
new file mode 100644
index 000000000..00fb27285
--- /dev/null
+++ b/lib/python/qmk/cli/doctor/macos.py
@@ -0,0 +1,13 @@
1import platform
2
3from milc import cli
4
5from .check import CheckStatus
6
7
8def os_test_macos():
9 """Run the Mac specific tests.
10 """
11 cli.log.info("Detected {fg_cyan}macOS %s{fg_reset}.", platform.mac_ver()[0])
12
13 return CheckStatus.OK
diff --git a/lib/python/qmk/cli/doctor.py b/lib/python/qmk/cli/doctor/main.py
index 9e1057062..45b0203b6 100755
--- a/lib/python/qmk/cli/doctor.py
+++ b/lib/python/qmk/cli/doctor/main.py
@@ -7,9 +7,10 @@ from subprocess import DEVNULL
7 7
8from milc import cli 8from milc import cli
9from milc.questions import yesno 9from milc.questions import yesno
10
10from qmk import submodules 11from qmk import submodules
11from qmk.constants import QMK_FIRMWARE 12from qmk.constants import QMK_FIRMWARE
12from qmk.os_helpers import CheckStatus, check_binaries, check_binary_versions, check_submodules, check_git_repo 13from .check import CheckStatus, check_binaries, check_binary_versions, check_submodules, check_git_repo
13 14
14 15
15def os_tests(): 16def os_tests():
@@ -18,53 +19,19 @@ def os_tests():
18 platform_id = platform.platform().lower() 19 platform_id = platform.platform().lower()
19 20
20 if 'darwin' in platform_id or 'macos' in platform_id: 21 if 'darwin' in platform_id or 'macos' in platform_id:
22 from .macos import os_test_macos
21 return os_test_macos() 23 return os_test_macos()
22 elif 'linux' in platform_id: 24 elif 'linux' in platform_id:
25 from .linux import os_test_linux
23 return os_test_linux() 26 return os_test_linux()
24 elif 'windows' in platform_id: 27 elif 'windows' in platform_id:
28 from .windows import os_test_windows
25 return os_test_windows() 29 return os_test_windows()
26 else: 30 else:
27 cli.log.warning('Unsupported OS detected: %s', platform_id) 31 cli.log.warning('Unsupported OS detected: %s', platform_id)
28 return CheckStatus.WARNING 32 return CheckStatus.WARNING
29 33
30 34
31def os_test_linux():
32 """Run the Linux specific tests.
33 """
34 # Don't bother with udev on WSL, for now
35 if 'microsoft' in platform.uname().release.lower():
36 cli.log.info("Detected {fg_cyan}Linux (WSL){fg_reset}.")
37
38 # https://github.com/microsoft/WSL/issues/4197
39 if QMK_FIRMWARE.as_posix().startswith("/mnt"):
40 cli.log.warning("I/O performance on /mnt may be extremely slow.")
41 return CheckStatus.WARNING
42
43 return CheckStatus.OK
44 else:
45 cli.log.info("Detected {fg_cyan}Linux{fg_reset}.")
46 from qmk.os_helpers.linux import check_udev_rules
47
48 return check_udev_rules()
49
50
51def os_test_macos():
52 """Run the Mac specific tests.
53 """
54 cli.log.info("Detected {fg_cyan}macOS %s{fg_reset}.", platform.mac_ver()[0])
55
56 return CheckStatus.OK
57
58
59def os_test_windows():
60 """Run the Windows specific tests.
61 """
62 win32_ver = platform.win32_ver()
63 cli.log.info("Detected {fg_cyan}Windows %s (%s){fg_reset}.", win32_ver[0], win32_ver[1])
64
65 return CheckStatus.OK
66
67
68@cli.argument('-y', '--yes', action='store_true', arg_only=True, help='Answer yes to all questions.') 35@cli.argument('-y', '--yes', action='store_true', arg_only=True, help='Answer yes to all questions.')
69@cli.argument('-n', '--no', action='store_true', arg_only=True, help='Answer no to all questions.') 36@cli.argument('-n', '--no', action='store_true', arg_only=True, help='Answer no to all questions.')
70@cli.subcommand('Basic QMK environment checks') 37@cli.subcommand('Basic QMK environment checks')
diff --git a/lib/python/qmk/cli/doctor/windows.py b/lib/python/qmk/cli/doctor/windows.py
new file mode 100644
index 000000000..381ab36fd
--- /dev/null
+++ b/lib/python/qmk/cli/doctor/windows.py
@@ -0,0 +1,14 @@
1import platform
2
3from milc import cli
4
5from .check import CheckStatus
6
7
8def os_test_windows():
9 """Run the Windows specific tests.
10 """
11 win32_ver = platform.win32_ver()
12 cli.log.info("Detected {fg_cyan}Windows %s (%s){fg_reset}.", win32_ver[0], win32_ver[1])
13
14 return CheckStatus.OK
diff --git a/lib/python/qmk/cli/format/json.py b/lib/python/qmk/cli/format/json.py
index 1358c70e7..19d504491 100755
--- a/lib/python/qmk/cli/format/json.py
+++ b/lib/python/qmk/cli/format/json.py
@@ -8,7 +8,7 @@ from jsonschema import ValidationError
8from milc import cli 8from milc import cli
9 9
10from qmk.info import info_json 10from qmk.info import info_json
11from qmk.json_schema import json_load, keyboard_validate 11from qmk.json_schema import json_load, validate
12from qmk.json_encoders import InfoJSONEncoder, KeymapJSONEncoder 12from qmk.json_encoders import InfoJSONEncoder, KeymapJSONEncoder
13from qmk.path import normpath 13from qmk.path import normpath
14 14
@@ -23,14 +23,13 @@ def format_json(cli):
23 23
24 if cli.args.format == 'auto': 24 if cli.args.format == 'auto':
25 try: 25 try:
26 keyboard_validate(json_file) 26 validate(json_file, 'qmk.keyboard.v1')
27 json_encoder = InfoJSONEncoder 27 json_encoder = InfoJSONEncoder
28 28
29 except ValidationError as e: 29 except ValidationError as e:
30 cli.log.warning('File %s did not validate as a keyboard:\n\t%s', cli.args.json_file, e) 30 cli.log.warning('File %s did not validate as a keyboard:\n\t%s', cli.args.json_file, e)
31 cli.log.info('Treating %s as a keymap file.', cli.args.json_file) 31 cli.log.info('Treating %s as a keymap file.', cli.args.json_file)
32 json_encoder = KeymapJSONEncoder 32 json_encoder = KeymapJSONEncoder
33
34 elif cli.args.format == 'keyboard': 33 elif cli.args.format == 'keyboard':
35 json_encoder = InfoJSONEncoder 34 json_encoder = InfoJSONEncoder
36 elif cli.args.format == 'keymap': 35 elif cli.args.format == 'keymap':
diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py
index 47c8bff7a..5525f0fe6 100644
--- a/lib/python/qmk/info.py
+++ b/lib/python/qmk/info.py
@@ -9,7 +9,7 @@ from milc import cli
9 9
10from qmk.constants import CHIBIOS_PROCESSORS, LUFA_PROCESSORS, VUSB_PROCESSORS 10from qmk.constants import CHIBIOS_PROCESSORS, LUFA_PROCESSORS, VUSB_PROCESSORS
11from qmk.c_parse import find_layouts 11from qmk.c_parse import find_layouts
12from qmk.json_schema import deep_update, json_load, keyboard_validate, keyboard_api_validate 12from qmk.json_schema import deep_update, json_load, validate
13from qmk.keyboard import config_h, rules_mk 13from qmk.keyboard import config_h, rules_mk
14from qmk.keymap import list_keymaps 14from qmk.keymap import list_keymaps
15from qmk.makefile import parse_rules_mk_file 15from qmk.makefile import parse_rules_mk_file
@@ -66,7 +66,7 @@ def info_json(keyboard):
66 66
67 # Validate against the jsonschema 67 # Validate against the jsonschema
68 try: 68 try:
69 keyboard_api_validate(info_data) 69 validate(info_data, 'qmk.api.keyboard.v1')
70 70
71 except jsonschema.ValidationError as e: 71 except jsonschema.ValidationError as e:
72 json_path = '.'.join([str(p) for p in e.absolute_path]) 72 json_path = '.'.join([str(p) for p in e.absolute_path])
@@ -143,10 +143,7 @@ def _pin_name(pin):
143 elif pin == 'NO_PIN': 143 elif pin == 'NO_PIN':
144 return None 144 return None
145 145
146 elif pin[0] in 'ABCDEFGHIJK' and pin[1].isdigit(): 146 return pin
147 return pin
148
149 raise ValueError(f'Invalid pin: {pin}')
150 147
151 148
152def _extract_pins(pins): 149def _extract_pins(pins):
@@ -493,7 +490,7 @@ def merge_info_jsons(keyboard, info_data):
493 continue 490 continue
494 491
495 try: 492 try:
496 keyboard_validate(new_info_data) 493 validate(new_info_data, 'qmk.keyboard.v1')
497 except jsonschema.ValidationError as e: 494 except jsonschema.ValidationError as e:
498 json_path = '.'.join([str(p) for p in e.absolute_path]) 495 json_path = '.'.join([str(p) for p in e.absolute_path])
499 cli.log.error('Not including data from file: %s', info_file) 496 cli.log.error('Not including data from file: %s', info_file)
diff --git a/lib/python/qmk/json_schema.py b/lib/python/qmk/json_schema.py
index 077dfcaa9..3e5663a29 100644
--- a/lib/python/qmk/json_schema.py
+++ b/lib/python/qmk/json_schema.py
@@ -24,9 +24,10 @@ def json_load(json_file):
24 24
25def load_jsonschema(schema_name): 25def load_jsonschema(schema_name):
26 """Read a jsonschema file from disk. 26 """Read a jsonschema file from disk.
27
28 FIXME(skullydazed/anyone): Refactor to make this a public function.
29 """ 27 """
28 if Path(schema_name).exists():
29 return json_load(schema_name)
30
30 schema_path = Path(f'data/schemas/{schema_name}.jsonschema') 31 schema_path = Path(f'data/schemas/{schema_name}.jsonschema')
31 32
32 if not schema_path.exists(): 33 if not schema_path.exists():
@@ -35,28 +36,33 @@ def load_jsonschema(schema_name):
35 return json_load(schema_path) 36 return json_load(schema_path)
36 37
37 38
38def keyboard_validate(data): 39def create_validator(schema):
39 """Validates data against the keyboard jsonschema. 40 """Creates a validator for the given schema id.
40 """ 41 """
41 schema = load_jsonschema('keyboard') 42 schema_store = {}
42 validator = jsonschema.Draft7Validator(schema).validate
43 43
44 return validator(data) 44 for schema_file in Path('data/schemas').glob('*.jsonschema'):
45 schema_data = load_jsonschema(schema_file)
46 if not isinstance(schema_data, dict):
47 cli.log.debug('Skipping schema file %s', schema_file)
48 continue
49 schema_store[schema_data['$id']] = schema_data
50
51 resolver = jsonschema.RefResolver.from_schema(schema_store['qmk.keyboard.v1'], store=schema_store)
52
53 return jsonschema.Draft7Validator(schema_store[schema], resolver=resolver).validate
45 54
46 55
47def keyboard_api_validate(data): 56def validate(data, schema):
48 """Validates data against the api_keyboard jsonschema. 57 """Validates data against a schema.
49 """ 58 """
50 base = load_jsonschema('keyboard') 59 validator = create_validator(schema)
51 relative = load_jsonschema('api_keyboard')
52 resolver = jsonschema.RefResolver.from_schema(base)
53 validator = jsonschema.Draft7Validator(relative, resolver=resolver).validate
54 60
55 return validator(data) 61 return validator(data)
56 62
57 63
58def deep_update(origdict, newdict): 64def deep_update(origdict, newdict):
59 """Update a dictionary in place, recursing to do a deep copy. 65 """Update a dictionary in place, recursing to do a depth-first deep copy.
60 """ 66 """
61 for key, value in newdict.items(): 67 for key, value in newdict.items():
62 if isinstance(value, Mapping): 68 if isinstance(value, Mapping):
diff --git a/platforms/chibios/IC_TEENSY_4_1/board/board.mk b/platforms/chibios/IC_TEENSY_4_1/board/board.mk
new file mode 100644
index 000000000..bc242ac3c
--- /dev/null
+++ b/platforms/chibios/IC_TEENSY_4_1/board/board.mk
@@ -0,0 +1 @@
include $(CHIBIOS_CONTRIB)/os/hal/boards/PJRC_TEENSY_4_1/board.mk
diff --git a/platforms/chibios/IC_TEENSY_4_1/rules.mk b/platforms/chibios/IC_TEENSY_4_1/rules.mk
new file mode 100644
index 000000000..0c62d209c
--- /dev/null
+++ b/platforms/chibios/IC_TEENSY_4_1/rules.mk
@@ -0,0 +1 @@
TEENSY_LOADER_CLI_MCU = imxrt1062
diff --git a/quantum/crc.c b/quantum/crc.c
new file mode 100644
index 000000000..0d8b9d601
--- /dev/null
+++ b/quantum/crc.c
@@ -0,0 +1,59 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "crc.h"
18
19__attribute__((weak)) void crc_init(void){
20 /* Software implementation nothing todo here. */
21};
22
23#if defined(CRC8_USE_TABLE)
24/**
25 * Static table used for the table_driven implementation.
26 */
27static const crc_t crc_table[256] = {0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
28 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3};
29
30__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) {
31 const uint8_t *d = (const uint8_t *)data;
32 crc_t crc = 0xff;
33 size_t tbl_idx;
34
35 while (data_len--) {
36 tbl_idx = crc ^ *d;
37 crc = crc_table[tbl_idx] & 0xff;
38 d++;
39 }
40 return crc & 0xff;
41}
42#else
43__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) {
44 const uint8_t *d = (const uint8_t *)data;
45 crc_t crc = 0xff;
46 size_t i, j;
47
48 for (i = 0; i < data_len; i++) {
49 crc ^= d[i];
50 for (j = 0; j < 8; j++) {
51 if ((crc & 0x80) != 0)
52 crc = (crc_t)((crc << 1) ^ 0x31);
53 else
54 crc <<= 1;
55 }
56 }
57 return crc;
58}
59#endif \ No newline at end of file
diff --git a/quantum/rgb.h b/quantum/crc.h
index 2602fc0b2..c17f5888e 100644
--- a/quantum/rgb.h
+++ b/quantum/crc.h
@@ -1,4 +1,4 @@
1/* Copyright 2017 Jack Humbert 1/* Copyright 2021 QMK
2 * 2 *
3 * This program is free software: you can redistribute it and/or modify 3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
@@ -16,24 +16,29 @@
16 16
17#pragma once 17#pragma once
18 18
19__attribute__((weak)) void rgblight_toggle(void){}; 19#include "quantum.h"
20 20
21__attribute__((weak)) void rgblight_step(void){}; 21/**
22 22 * The type of the CRC values.
23__attribute__((weak)) void rgblight_step_reverse(void){}; 23 *
24 24 * This type must be big enough to contain at least 8 bits.
25__attribute__((weak)) void rgblight_increase_hue(void){}; 25 */
26 26#if defined(CRC8_OPTIMIZE_SPEED)
27__attribute__((weak)) void rgblight_decrease_hue(void){}; 27typedef uint_fast8_t crc_t;
28 28#else
29__attribute__((weak)) void rgblight_increase_sat(void){}; 29typedef uint_least8_t crc_t;
30 30#endif
31__attribute__((weak)) void rgblight_decrease_sat(void){}; 31
32 32/**
33__attribute__((weak)) void rgblight_increase_val(void){}; 33 * Initialize crc subsystem.
34 34 */
35__attribute__((weak)) void rgblight_decrease_val(void){}; 35__attribute__((weak)) void crc_init(void);
36
37__attribute__((weak)) void rgblight_increase_speed(void){};
38 36
39__attribute__((weak)) void rgblight_decrease_speed(void){}; 37/**
38 * Generate CRC8 value from given data.
39 *
40 * \param[in] data Pointer to a buffer of \a data_len bytes.
41 * \param[in] data_len Number of bytes in the \a data buffer.
42 * \return The calculated crc value.
43 */
44__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len); \ No newline at end of file
diff --git a/quantum/debounce.h b/quantum/debounce.h
index 9ca05c682..504386828 100644
--- a/quantum/debounce.h
+++ b/quantum/debounce.h
@@ -9,3 +9,5 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
9bool debounce_active(void); 9bool debounce_active(void);
10 10
11void debounce_init(uint8_t num_rows); 11void debounce_init(uint8_t num_rows);
12
13void debounce_free(void);
diff --git a/quantum/debounce/asym_eager_defer_pk.c b/quantum/debounce/asym_eager_defer_pk.c
new file mode 100644
index 000000000..24380dc5e
--- /dev/null
+++ b/quantum/debounce/asym_eager_defer_pk.c
@@ -0,0 +1,171 @@
1/*
2 * Copyright 2017 Alex Ong <the.onga@gmail.com>
3 * Copyright 2020 Andrei Purdea <andrei@purdea.ro>
4 * Copyright 2021 Simon Arlott
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21Basic symmetric per-key algorithm. Uses an 8-bit counter per key.
22When no state changes have occured for DEBOUNCE milliseconds, we push the state.
23*/
24
25#include "matrix.h"
26#include "timer.h"
27#include "quantum.h"
28#include <stdlib.h>
29
30#ifdef PROTOCOL_CHIBIOS
31# if CH_CFG_USE_MEMCORE == FALSE
32# error ChibiOS is configured without a memory allocator. Your keyboard may have set `#define CH_CFG_USE_MEMCORE FALSE`, which is incompatible with this debounce algorithm.
33# endif
34#endif
35
36#ifndef DEBOUNCE
37# define DEBOUNCE 5
38#endif
39
40// Maximum debounce: 127ms
41#if DEBOUNCE > 127
42# undef DEBOUNCE
43# define DEBOUNCE 127
44#endif
45
46#define ROW_SHIFTER ((matrix_row_t)1)
47
48typedef struct {
49 bool pressed : 1;
50 uint8_t time : 7;
51} debounce_counter_t;
52
53#if DEBOUNCE > 0
54static debounce_counter_t *debounce_counters;
55static fast_timer_t last_time;
56static bool counters_need_update;
57static bool matrix_need_update;
58
59#define DEBOUNCE_ELAPSED 0
60
61static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
62static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
63
64// we use num_rows rather than MATRIX_ROWS to support split keyboards
65void debounce_init(uint8_t num_rows) {
66 debounce_counters = malloc(num_rows * MATRIX_COLS * sizeof(debounce_counter_t));
67 int i = 0;
68 for (uint8_t r = 0; r < num_rows; r++) {
69 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
70 debounce_counters[i++].time = DEBOUNCE_ELAPSED;
71 }
72 }
73}
74
75void debounce_free(void) {
76 free(debounce_counters);
77 debounce_counters = NULL;
78}
79
80void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
81 bool updated_last = false;
82
83 if (counters_need_update) {
84 fast_timer_t now = timer_read_fast();
85 fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
86
87 last_time = now;
88 updated_last = true;
89 if (elapsed_time > UINT8_MAX) {
90 elapsed_time = UINT8_MAX;
91 }
92
93 if (elapsed_time > 0) {
94 update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time);
95 }
96 }
97
98 if (changed || matrix_need_update) {
99 if (!updated_last) {
100 last_time = timer_read_fast();
101 }
102
103 transfer_matrix_values(raw, cooked, num_rows);
104 }
105}
106
107static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) {
108 debounce_counter_t *debounce_pointer = debounce_counters;
109
110 counters_need_update = false;
111 matrix_need_update = false;
112
113 for (uint8_t row = 0; row < num_rows; row++) {
114 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
115 matrix_row_t col_mask = (ROW_SHIFTER << col);
116
117 if (debounce_pointer->time != DEBOUNCE_ELAPSED) {
118 if (debounce_pointer->time <= elapsed_time) {
119 debounce_pointer->time = DEBOUNCE_ELAPSED;
120
121 if (debounce_pointer->pressed) {
122 // key-down: eager
123 matrix_need_update = true;
124 } else {
125 // key-up: defer
126 cooked[row] = (cooked[row] & ~col_mask) | (raw[row] & col_mask);
127 }
128 } else {
129 debounce_pointer->time -= elapsed_time;
130 counters_need_update = true;
131 }
132 }
133 debounce_pointer++;
134 }
135 }
136}
137
138static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
139 debounce_counter_t *debounce_pointer = debounce_counters;
140
141 for (uint8_t row = 0; row < num_rows; row++) {
142 matrix_row_t delta = raw[row] ^ cooked[row];
143 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
144 matrix_row_t col_mask = (ROW_SHIFTER << col);
145
146 if (delta & col_mask) {
147 if (debounce_pointer->time == DEBOUNCE_ELAPSED) {
148 debounce_pointer->pressed = (raw[row] & col_mask);
149 debounce_pointer->time = DEBOUNCE;
150 counters_need_update = true;
151
152 if (debounce_pointer->pressed) {
153 // key-down: eager
154 cooked[row] ^= col_mask;
155 }
156 }
157 } else if (debounce_pointer->time != DEBOUNCE_ELAPSED) {
158 if (!debounce_pointer->pressed) {
159 // key-up: defer
160 debounce_pointer->time = DEBOUNCE_ELAPSED;
161 }
162 }
163 debounce_pointer++;
164 }
165 }
166}
167
168bool debounce_active(void) { return true; }
169#else
170# include "none.c"
171#endif
diff --git a/quantum/debounce/none.c b/quantum/debounce/none.c
new file mode 100644
index 000000000..b03892bc5
--- /dev/null
+++ b/quantum/debounce/none.c
@@ -0,0 +1,31 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "matrix.h"
18#include "quantum.h"
19#include <stdlib.h>
20
21void debounce_init(uint8_t num_rows) {}
22
23void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
24 for (int i = 0; i < num_rows; i++) {
25 cooked[i] = raw[i];
26 }
27}
28
29bool debounce_active(void) { return false; }
30
31void debounce_free(void) {}
diff --git a/quantum/debounce/sym_defer_g.c b/quantum/debounce/sym_defer_g.c
index 3ed9055d2..fbefd55ed 100644
--- a/quantum/debounce/sym_defer_g.c
+++ b/quantum/debounce/sym_defer_g.c
@@ -1,5 +1,6 @@
1/* 1/*
2Copyright 2017 Alex Ong<the.onga@gmail.com> 2Copyright 2017 Alex Ong<the.onga@gmail.com>
3Copyright 2021 Simon Arlott
3This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or 6the Free Software Foundation, either version 2 of the License, or
@@ -23,30 +24,29 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
23# define DEBOUNCE 5 24# define DEBOUNCE 5
24#endif 25#endif
25 26
26void debounce_init(uint8_t num_rows) {} 27#if DEBOUNCE > 0
27static bool debouncing = false; 28static bool debouncing = false;
29static fast_timer_t debouncing_time;
28 30
29#if DEBOUNCE > 0 31void debounce_init(uint8_t num_rows) {}
30static uint16_t debouncing_time; 32
31void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { 33void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
32 if (changed) { 34 if (changed) {
33 debouncing = true; 35 debouncing = true;
34 debouncing_time = timer_read(); 36 debouncing_time = timer_read_fast();
35 } 37 }
36 38
37 if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { 39 if (debouncing && timer_elapsed_fast(debouncing_time) >= DEBOUNCE) {
38 for (int i = 0; i < num_rows; i++) { 40 for (int i = 0; i < num_rows; i++) {
39 cooked[i] = raw[i]; 41 cooked[i] = raw[i];
40 } 42 }
41 debouncing = false; 43 debouncing = false;
42 } 44 }
43} 45}
44#else // no debouncing.
45void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
46 for (int i = 0; i < num_rows; i++) {
47 cooked[i] = raw[i];
48 }
49}
50#endif
51 46
52bool debounce_active(void) { return debouncing; } 47bool debounce_active(void) { return debouncing; }
48
49void debounce_free(void) {}
50#else // no debouncing.
51# include "none.c"
52#endif
diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c
index 60513f98e..626a9be84 100644
--- a/quantum/debounce/sym_defer_pk.c
+++ b/quantum/debounce/sym_defer_pk.c
@@ -1,6 +1,7 @@
1/* 1/*
2Copyright 2017 Alex Ong<the.onga@gmail.com> 2Copyright 2017 Alex Ong<the.onga@gmail.com>
3Copyright 2020 Andrei Purdea<andrei@purdea.ro> 3Copyright 2020 Andrei Purdea<andrei@purdea.ro>
4Copyright 2021 Simon Arlott
4This program is free software: you can redistribute it and/or modify 5This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by 6it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or 7the Free Software Foundation, either version 2 of the License, or
@@ -33,28 +34,25 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
33# define DEBOUNCE 5 34# define DEBOUNCE 5
34#endif 35#endif
35 36
37// Maximum debounce: 255ms
38#if DEBOUNCE > UINT8_MAX
39# undef DEBOUNCE
40# define DEBOUNCE UINT8_MAX
41#endif
42
36#define ROW_SHIFTER ((matrix_row_t)1) 43#define ROW_SHIFTER ((matrix_row_t)1)
37 44
38#define debounce_counter_t uint8_t 45typedef uint8_t debounce_counter_t;
39 46
47#if DEBOUNCE > 0
40static debounce_counter_t *debounce_counters; 48static debounce_counter_t *debounce_counters;
49static fast_timer_t last_time;
41static bool counters_need_update; 50static bool counters_need_update;
42 51
43#define DEBOUNCE_ELAPSED 251 52#define DEBOUNCE_ELAPSED 0
44#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1)
45
46static uint8_t wrapping_timer_read(void) {
47 static uint16_t time = 0;
48 static uint8_t last_result = 0;
49 uint16_t new_time = timer_read();
50 uint16_t diff = new_time - time;
51 time = new_time;
52 last_result = (last_result + diff) % (MAX_DEBOUNCE + 1);
53 return last_result;
54}
55 53
56void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); 54static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
57void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); 55static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
58 56
59// we use num_rows rather than MATRIX_ROWS to support split keyboards 57// we use num_rows rather than MATRIX_ROWS to support split keyboards
60void debounce_init(uint8_t num_rows) { 58void debounce_init(uint8_t num_rows) {
@@ -67,27 +65,49 @@ void debounce_init(uint8_t num_rows) {
67 } 65 }
68} 66}
69 67
68void debounce_free(void) {
69 free(debounce_counters);
70 debounce_counters = NULL;
71}
72
70void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { 73void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
71 uint8_t current_time = wrapping_timer_read(); 74 bool updated_last = false;
75
72 if (counters_need_update) { 76 if (counters_need_update) {
73 update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, current_time); 77 fast_timer_t now = timer_read_fast();
78 fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
79
80 last_time = now;
81 updated_last = true;
82 if (elapsed_time > UINT8_MAX) {
83 elapsed_time = UINT8_MAX;
84 }
85
86 if (elapsed_time > 0) {
87 update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time);
88 }
74 } 89 }
75 90
76 if (changed) { 91 if (changed) {
77 start_debounce_counters(raw, cooked, num_rows, current_time); 92 if (!updated_last) {
93 last_time = timer_read_fast();
94 }
95
96 start_debounce_counters(raw, cooked, num_rows);
78 } 97 }
79} 98}
80 99
81void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { 100static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) {
82 counters_need_update = false; 101 counters_need_update = false;
83 debounce_counter_t *debounce_pointer = debounce_counters; 102 debounce_counter_t *debounce_pointer = debounce_counters;
84 for (uint8_t row = 0; row < num_rows; row++) { 103 for (uint8_t row = 0; row < num_rows; row++) {
85 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 104 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
86 if (*debounce_pointer != DEBOUNCE_ELAPSED) { 105 if (*debounce_pointer != DEBOUNCE_ELAPSED) {
87 if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { 106 if (*debounce_pointer <= elapsed_time) {
88 *debounce_pointer = DEBOUNCE_ELAPSED; 107 *debounce_pointer = DEBOUNCE_ELAPSED;
89 cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col)); 108 cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col));
90 } else { 109 } else {
110 *debounce_pointer -= elapsed_time;
91 counters_need_update = true; 111 counters_need_update = true;
92 } 112 }
93 } 113 }
@@ -96,14 +116,14 @@ void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix
96 } 116 }
97} 117}
98 118
99void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { 119static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
100 debounce_counter_t *debounce_pointer = debounce_counters; 120 debounce_counter_t *debounce_pointer = debounce_counters;
101 for (uint8_t row = 0; row < num_rows; row++) { 121 for (uint8_t row = 0; row < num_rows; row++) {
102 matrix_row_t delta = raw[row] ^ cooked[row]; 122 matrix_row_t delta = raw[row] ^ cooked[row];
103 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 123 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
104 if (delta & (ROW_SHIFTER << col)) { 124 if (delta & (ROW_SHIFTER << col)) {
105 if (*debounce_pointer == DEBOUNCE_ELAPSED) { 125 if (*debounce_pointer == DEBOUNCE_ELAPSED) {
106 *debounce_pointer = current_time; 126 *debounce_pointer = DEBOUNCE;
107 counters_need_update = true; 127 counters_need_update = true;
108 } 128 }
109 } else { 129 } else {
@@ -115,3 +135,6 @@ void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t
115} 135}
116 136
117bool debounce_active(void) { return true; } 137bool debounce_active(void) { return true; }
138#else
139# include "none.c"
140#endif
diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c
index e66cf92d7..15a3242e6 100644
--- a/quantum/debounce/sym_eager_pk.c
+++ b/quantum/debounce/sym_eager_pk.c
@@ -1,5 +1,6 @@
1/* 1/*
2Copyright 2017 Alex Ong<the.onga@gmail.com> 2Copyright 2017 Alex Ong<the.onga@gmail.com>
3Copyright 2021 Simon Arlott
3This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or 6the Free Software Foundation, either version 2 of the License, or
@@ -33,29 +34,26 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.
33# define DEBOUNCE 5 34# define DEBOUNCE 5
34#endif 35#endif
35 36
37// Maximum debounce: 255ms
38#if DEBOUNCE > UINT8_MAX
39# undef DEBOUNCE
40# define DEBOUNCE UINT8_MAX
41#endif
42
36#define ROW_SHIFTER ((matrix_row_t)1) 43#define ROW_SHIFTER ((matrix_row_t)1)
37 44
38#define debounce_counter_t uint8_t 45typedef uint8_t debounce_counter_t;
39 46
47#if DEBOUNCE > 0
40static debounce_counter_t *debounce_counters; 48static debounce_counter_t *debounce_counters;
49static fast_timer_t last_time;
41static bool counters_need_update; 50static bool counters_need_update;
42static bool matrix_need_update; 51static bool matrix_need_update;
43 52
44#define DEBOUNCE_ELAPSED 251 53#define DEBOUNCE_ELAPSED 0
45#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1)
46
47static uint8_t wrapping_timer_read(void) {
48 static uint16_t time = 0;
49 static uint8_t last_result = 0;
50 uint16_t new_time = timer_read();
51 uint16_t diff = new_time - time;
52 time = new_time;
53 last_result = (last_result + diff) % (MAX_DEBOUNCE + 1);
54 return last_result;
55}
56 54
57void update_debounce_counters(uint8_t num_rows, uint8_t current_time); 55static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
58void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); 56static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
59 57
60// we use num_rows rather than MATRIX_ROWS to support split keyboards 58// we use num_rows rather than MATRIX_ROWS to support split keyboards
61void debounce_init(uint8_t num_rows) { 59void debounce_init(uint8_t num_rows) {
@@ -68,27 +66,51 @@ void debounce_init(uint8_t num_rows) {
68 } 66 }
69} 67}
70 68
69void debounce_free(void) {
70 free(debounce_counters);
71 debounce_counters = NULL;
72}
73
71void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { 74void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
72 uint8_t current_time = wrapping_timer_read(); 75 bool updated_last = false;
76
73 if (counters_need_update) { 77 if (counters_need_update) {
74 update_debounce_counters(num_rows, current_time); 78 fast_timer_t now = timer_read_fast();
79 fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
80
81 last_time = now;
82 updated_last = true;
83 if (elapsed_time > UINT8_MAX) {
84 elapsed_time = UINT8_MAX;
85 }
86
87 if (elapsed_time > 0) {
88 update_debounce_counters(num_rows, elapsed_time);
89 }
75 } 90 }
76 91
77 if (changed || matrix_need_update) { 92 if (changed || matrix_need_update) {
78 transfer_matrix_values(raw, cooked, num_rows, current_time); 93 if (!updated_last) {
94 last_time = timer_read_fast();
95 }
96
97 transfer_matrix_values(raw, cooked, num_rows);
79 } 98 }
80} 99}
81 100
82// If the current time is > debounce counter, set the counter to enable input. 101// If the current time is > debounce counter, set the counter to enable input.
83void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { 102static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
84 counters_need_update = false; 103 counters_need_update = false;
104 matrix_need_update = false;
85 debounce_counter_t *debounce_pointer = debounce_counters; 105 debounce_counter_t *debounce_pointer = debounce_counters;
86 for (uint8_t row = 0; row < num_rows; row++) { 106 for (uint8_t row = 0; row < num_rows; row++) {
87 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 107 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
88 if (*debounce_pointer != DEBOUNCE_ELAPSED) { 108 if (*debounce_pointer != DEBOUNCE_ELAPSED) {
89 if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { 109 if (*debounce_pointer <= elapsed_time) {
90 *debounce_pointer = DEBOUNCE_ELAPSED; 110 *debounce_pointer = DEBOUNCE_ELAPSED;
111 matrix_need_update = true;
91 } else { 112 } else {
113 *debounce_pointer -= elapsed_time;
92 counters_need_update = true; 114 counters_need_update = true;
93 } 115 }
94 } 116 }
@@ -98,8 +120,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) {
98} 120}
99 121
100// upload from raw_matrix to final matrix; 122// upload from raw_matrix to final matrix;
101void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { 123static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
102 matrix_need_update = false;
103 debounce_counter_t *debounce_pointer = debounce_counters; 124 debounce_counter_t *debounce_pointer = debounce_counters;
104 for (uint8_t row = 0; row < num_rows; row++) { 125 for (uint8_t row = 0; row < num_rows; row++) {
105 matrix_row_t delta = raw[row] ^ cooked[row]; 126 matrix_row_t delta = raw[row] ^ cooked[row];
@@ -108,11 +129,9 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n
108 matrix_row_t col_mask = (ROW_SHIFTER << col); 129 matrix_row_t col_mask = (ROW_SHIFTER << col);
109 if (delta & col_mask) { 130 if (delta & col_mask) {
110 if (*debounce_pointer == DEBOUNCE_ELAPSED) { 131 if (*debounce_pointer == DEBOUNCE_ELAPSED) {
111 *debounce_pointer = current_time; 132 *debounce_pointer = DEBOUNCE;
112 counters_need_update = true; 133 counters_need_update = true;
113 existing_row ^= col_mask; // flip the bit. 134 existing_row ^= col_mask; // flip the bit.
114 } else {
115 matrix_need_update = true;
116 } 135 }
117 } 136 }
118 debounce_pointer++; 137 debounce_pointer++;
@@ -122,3 +141,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n
122} 141}
123 142
124bool debounce_active(void) { return true; } 143bool debounce_active(void) { return true; }
144#else
145# include "none.c"
146#endif
diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c
index 20ccb46f1..2ad592c5a 100644
--- a/quantum/debounce/sym_eager_pr.c
+++ b/quantum/debounce/sym_eager_pr.c
@@ -1,5 +1,6 @@
1/* 1/*
2Copyright 2019 Alex Ong<the.onga@gmail.com> 2Copyright 2019 Alex Ong<the.onga@gmail.com>
3Copyright 2021 Simon Arlott
3This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or 6the Free Software Foundation, either version 2 of the License, or
@@ -33,27 +34,25 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.
33# define DEBOUNCE 5 34# define DEBOUNCE 5
34#endif 35#endif
35 36
36#define debounce_counter_t uint8_t 37// Maximum debounce: 255ms
38#if DEBOUNCE > UINT8_MAX
39# undef DEBOUNCE
40# define DEBOUNCE UINT8_MAX
41#endif
42
43typedef uint8_t debounce_counter_t;
44
45#if DEBOUNCE > 0
37static bool matrix_need_update; 46static bool matrix_need_update;
38 47
39static debounce_counter_t *debounce_counters; 48static debounce_counter_t *debounce_counters;
49static fast_timer_t last_time;
40static bool counters_need_update; 50static bool counters_need_update;
41 51
42#define DEBOUNCE_ELAPSED 251 52#define DEBOUNCE_ELAPSED 0
43#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1)
44
45static uint8_t wrapping_timer_read(void) {
46 static uint16_t time = 0;
47 static uint8_t last_result = 0;
48 uint16_t new_time = timer_read();
49 uint16_t diff = new_time - time;
50 time = new_time;
51 last_result = (last_result + diff) % (MAX_DEBOUNCE + 1);
52 return last_result;
53}
54 53
55void update_debounce_counters(uint8_t num_rows, uint8_t current_time); 54static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
56void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); 55static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
57 56
58// we use num_rows rather than MATRIX_ROWS to support split keyboards 57// we use num_rows rather than MATRIX_ROWS to support split keyboards
59void debounce_init(uint8_t num_rows) { 58void debounce_init(uint8_t num_rows) {
@@ -63,27 +62,50 @@ void debounce_init(uint8_t num_rows) {
63 } 62 }
64} 63}
65 64
65void debounce_free(void) {
66 free(debounce_counters);
67 debounce_counters = NULL;
68}
69
66void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { 70void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
67 uint8_t current_time = wrapping_timer_read(); 71 bool updated_last = false;
68 bool needed_update = counters_need_update; 72
69 if (counters_need_update) { 73 if (counters_need_update) {
70 update_debounce_counters(num_rows, current_time); 74 fast_timer_t now = timer_read_fast();
75 fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
76
77 last_time = now;
78 updated_last = true;
79 if (elapsed_time > UINT8_MAX) {
80 elapsed_time = UINT8_MAX;
81 }
82
83 if (elapsed_time > 0) {
84 update_debounce_counters(num_rows, elapsed_time);
85 }
71 } 86 }
72 87
73 if (changed || (needed_update && !counters_need_update) || matrix_need_update) { 88 if (changed || matrix_need_update) {
74 transfer_matrix_values(raw, cooked, num_rows, current_time); 89 if (!updated_last) {
90 last_time = timer_read_fast();
91 }
92
93 transfer_matrix_values(raw, cooked, num_rows);
75 } 94 }
76} 95}
77 96
78// If the current time is > debounce counter, set the counter to enable input. 97// If the current time is > debounce counter, set the counter to enable input.
79void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { 98static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
80 counters_need_update = false; 99 counters_need_update = false;
100 matrix_need_update = false;
81 debounce_counter_t *debounce_pointer = debounce_counters; 101 debounce_counter_t *debounce_pointer = debounce_counters;
82 for (uint8_t row = 0; row < num_rows; row++) { 102 for (uint8_t row = 0; row < num_rows; row++) {
83 if (*debounce_pointer != DEBOUNCE_ELAPSED) { 103 if (*debounce_pointer != DEBOUNCE_ELAPSED) {
84 if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { 104 if (*debounce_pointer <= elapsed_time) {
85 *debounce_pointer = DEBOUNCE_ELAPSED; 105 *debounce_pointer = DEBOUNCE_ELAPSED;
106 matrix_need_update = true;
86 } else { 107 } else {
108 *debounce_pointer -= elapsed_time;
87 counters_need_update = true; 109 counters_need_update = true;
88 } 110 }
89 } 111 }
@@ -92,8 +114,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) {
92} 114}
93 115
94// upload from raw_matrix to final matrix; 116// upload from raw_matrix to final matrix;
95void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { 117static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
96 matrix_need_update = false;
97 debounce_counter_t *debounce_pointer = debounce_counters; 118 debounce_counter_t *debounce_pointer = debounce_counters;
98 for (uint8_t row = 0; row < num_rows; row++) { 119 for (uint8_t row = 0; row < num_rows; row++) {
99 matrix_row_t existing_row = cooked[row]; 120 matrix_row_t existing_row = cooked[row];
@@ -102,11 +123,9 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n
102 // determine new value basd on debounce pointer + raw value 123 // determine new value basd on debounce pointer + raw value
103 if (existing_row != raw_row) { 124 if (existing_row != raw_row) {
104 if (*debounce_pointer == DEBOUNCE_ELAPSED) { 125 if (*debounce_pointer == DEBOUNCE_ELAPSED) {
105 *debounce_pointer = current_time; 126 *debounce_pointer = DEBOUNCE;
106 cooked[row] = raw_row; 127 cooked[row] = raw_row;
107 counters_need_update = true; 128 counters_need_update = true;
108 } else {
109 matrix_need_update = true;
110 } 129 }
111 } 130 }
112 debounce_pointer++; 131 debounce_pointer++;
@@ -114,3 +133,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n
114} 133}
115 134
116bool debounce_active(void) { return true; } 135bool debounce_active(void) { return true; }
136#else
137# include "none.c"
138#endif
diff --git a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
new file mode 100644
index 000000000..fe374c3df
--- /dev/null
+++ b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
@@ -0,0 +1,374 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
24 /* Release key after 1ms delay */
25 {1, {{0, 1, UP}}, {}},
26
27 /*
28 * Until the eager timer on DOWN is observed to finish, the defer timer
29 * on UP can't start. There's no workaround for this because it's not
30 * possible to debounce an event that isn't being tracked.
31 *
32 * sym_defer_pk has the same problem but the test has to track that the
33 * key changed state so the DOWN timer is always allowed to finish
34 * before starting the UP timer.
35 */
36 {5, {}, {}},
37
38 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
39 /* Press key again after 1ms delay */
40 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
41 });
42 runEvents();
43}
44
45TEST_F(DebounceTest, OneKeyShort2) {
46 addEvents({ /* Time, Inputs, Outputs */
47 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
48 /* Release key after 2ms delay */
49 {2, {{0, 1, UP}}, {}},
50
51 {5, {}, {}}, /* See OneKeyShort1 */
52
53 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
54 /* Press key again after 1ms delay */
55 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyShort3) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
63 /* Release key after 3ms delay */
64 {3, {{0, 1, UP}}, {}},
65
66 {5, {}, {}}, /* See OneKeyShort1 */
67
68 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
69 /* Press key again after 1ms delay */
70 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
71 });
72 runEvents();
73}
74
75TEST_F(DebounceTest, OneKeyShort4) {
76 addEvents({ /* Time, Inputs, Outputs */
77 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
78 /* Release key after 4ms delay */
79 {4, {{0, 1, UP}}, {}},
80
81 {5, {}, {}}, /* See OneKeyShort1 */
82
83 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
84 /* Press key again after 1ms delay */
85 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
86 });
87 runEvents();
88}
89
90TEST_F(DebounceTest, OneKeyShort5) {
91 addEvents({ /* Time, Inputs, Outputs */
92 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
93
94 /* Release key after 5ms delay */
95 {5, {{0, 1, UP}}, {}},
96
97 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
98 /* Press key again after 1ms delay */
99 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
100 });
101 runEvents();
102}
103
104TEST_F(DebounceTest, OneKeyShort6) {
105 addEvents({ /* Time, Inputs, Outputs */
106 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
107
108 /* Release key after 6ms delay */
109 {6, {{0, 1, UP}}, {}},
110
111 {11, {}, {{0, 1, UP}}}, /* 5ms after UP at time 6 */
112 /* Press key again after 1ms delay */
113 {12, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
114 });
115 runEvents();
116}
117
118TEST_F(DebounceTest, OneKeyShort7) {
119 addEvents({ /* Time, Inputs, Outputs */
120 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
121
122 /* Release key after 7ms delay */
123 {7, {{0, 1, UP}}, {}},
124
125 {12, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */
126 /* Press key again after 1ms delay */
127 {13, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
128 });
129 runEvents();
130}
131
132TEST_F(DebounceTest, OneKeyShort8) {
133 addEvents({ /* Time, Inputs, Outputs */
134 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
135 /* Release key after 1ms delay */
136 {1, {{0, 1, UP}}, {}},
137
138 {5, {}, {}}, /* See OneKeyShort1 */
139
140 {10, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */
141 /* Press key again after 0ms delay (scan 2) */
142 {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
143 });
144 runEvents();
145}
146
147TEST_F(DebounceTest, OneKeyShort9) {
148 addEvents({ /* Time, Inputs, Outputs */
149 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
150 /* Release key after 1ms delay */
151 {1, {{0, 1, UP}}, {}},
152
153 {5, {}, {}}, /* See OneKeyShort1 */
154
155 /* Press key again after 0ms delay (same scan) before debounce finishes */
156 {10, {{0, 1, DOWN}}, {}},
157 });
158 runEvents();
159}
160
161TEST_F(DebounceTest, OneKeyBouncing1) {
162 addEvents({ /* Time, Inputs, Outputs */
163 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
164 {1, {{0, 1, UP}}, {}},
165 {2, {{0, 1, DOWN}}, {}},
166 {3, {{0, 1, UP}}, {}},
167 {4, {{0, 1, DOWN}}, {}},
168 {5, {{0, 1, UP}}, {}},
169 {6, {{0, 1, DOWN}}, {}},
170 {7, {{0, 1, UP}}, {}},
171 {8, {{0, 1, DOWN}}, {}},
172 {9, {{0, 1, UP}}, {}},
173 {10, {{0, 1, DOWN}}, {}},
174 {11, {{0, 1, UP}}, {}},
175 {12, {{0, 1, DOWN}}, {}},
176 {13, {{0, 1, UP}}, {}},
177 {14, {{0, 1, DOWN}}, {}},
178 {15, {{0, 1, UP}}, {}},
179
180 {20, {}, {{0, 1, UP}}},
181 /* Press key again after 1ms delay */
182 {21, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
183 });
184 runEvents();
185}
186
187TEST_F(DebounceTest, OneKeyBouncing2) {
188 addEvents({ /* Time, Inputs, Outputs */
189 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
190 /* Change twice in the same time period */
191 {1, {{0, 1, UP}}, {}},
192 {1, {{0, 1, DOWN}}, {}},
193 /* Change three times in the same time period */
194 {2, {{0, 1, UP}}, {}},
195 {2, {{0, 1, DOWN}}, {}},
196 {2, {{0, 1, UP}}, {}},
197 /* Change twice in the same time period */
198 {6, {{0, 1, DOWN}}, {}},
199 {6, {{0, 1, UP}}, {}},
200 /* Change three times in the same time period */
201 {7, {{0, 1, DOWN}}, {}},
202 {7, {{0, 1, UP}}, {}},
203 {7, {{0, 1, DOWN}}, {}},
204 /* Change twice in the same time period */
205 {8, {{0, 1, UP}}, {}},
206 {8, {{0, 1, DOWN}}, {}},
207 /* Change three times in the same time period */
208 {9, {{0, 1, UP}}, {}},
209 {9, {{0, 1, DOWN}}, {}},
210 {9, {{0, 1, UP}}, {}},
211
212 {14, {}, {{0, 1, UP}}},
213 /* Press key again after 1ms delay */
214 {15, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
215 });
216 runEvents();
217}
218
219TEST_F(DebounceTest, OneKeyLong) {
220 addEvents({ /* Time, Inputs, Outputs */
221 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
222
223 {25, {{0, 1, UP}}, {}},
224
225 {30, {}, {{0, 1, UP}}},
226
227 {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
228
229 {75, {{0, 1, UP}}, {}},
230
231 {80, {}, {{0, 1, UP}}},
232
233 {100, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
234 });
235 runEvents();
236}
237
238TEST_F(DebounceTest, TwoKeysShort) {
239 addEvents({ /* Time, Inputs, Outputs */
240 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
241 {1, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
242 /* Release key after 2ms delay */
243 {2, {{0, 1, UP}}, {}},
244 {3, {{0, 2, UP}}, {}},
245
246 {5, {}, {}}, /* See OneKeyShort1 */
247 {6, {}, {}}, /* See OneKeyShort1 */
248
249 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
250 /* Press key again after 1ms delay */
251 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}, {0, 2, UP}}}, /* 5ms+5ms after DOWN at time 0 */
252 {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */
253 });
254 runEvents();
255}
256
257
258TEST_F(DebounceTest, OneKeyDelayedScan1) {
259 addEvents({ /* Time, Inputs, Outputs */
260 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
261
262 /* Processing is very late, immediately release key */
263 {300, {{0, 1, UP}}, {}},
264
265 {305, {}, {{0, 1, UP}}},
266 });
267 time_jumps_ = true;
268 runEvents();
269}
270
271TEST_F(DebounceTest, OneKeyDelayedScan2) {
272 addEvents({ /* Time, Inputs, Outputs */
273 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
274
275 /* Processing is very late, immediately release key */
276 {300, {{0, 1, UP}}, {}},
277
278 /* Processing is very late again */
279 {600, {}, {{0, 1, UP}}},
280 });
281 time_jumps_ = true;
282 runEvents();
283}
284
285TEST_F(DebounceTest, OneKeyDelayedScan3) {
286 addEvents({ /* Time, Inputs, Outputs */
287 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
288
289 /* Processing is very late */
290 {300, {}, {}},
291 /* Release key after 1ms */
292 {301, {{0, 1, UP}}, {}},
293
294 {306, {}, {{0, 1, UP}}},
295 });
296 time_jumps_ = true;
297 runEvents();
298}
299
300TEST_F(DebounceTest, OneKeyDelayedScan4) {
301 addEvents({ /* Time, Inputs, Outputs */
302 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
303
304 /* Processing is very late */
305 {300, {}, {}},
306 /* Release key after 1ms */
307 {301, {{0, 1, UP}}, {}},
308
309 /* Processing is very late again */
310 {600, {}, {{0, 1, UP}}},
311 });
312 time_jumps_ = true;
313 runEvents();
314}
315
316TEST_F(DebounceTest, OneKeyDelayedScan5) {
317 addEvents({ /* Time, Inputs, Outputs */
318 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
319
320 {5, {{0, 1, UP}}, {}},
321
322 /* Processing is very late */
323 {300, {}, {{0, 1, UP}}},
324 /* Immediately press key again */
325 {300, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
326 });
327 time_jumps_ = true;
328 runEvents();
329}
330
331TEST_F(DebounceTest, OneKeyDelayedScan6) {
332 addEvents({ /* Time, Inputs, Outputs */
333 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
334
335 {5, {{0, 1, UP}}, {}},
336
337 /* Processing is very late */
338 {300, {}, {{0, 1, UP}}},
339
340 /* Press key again after 1ms */
341 {301, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
342 });
343 time_jumps_ = true;
344 runEvents();
345}
346
347TEST_F(DebounceTest, OneKeyDelayedScan7) {
348 addEvents({ /* Time, Inputs, Outputs */
349 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
350
351 {5, {{0, 1, UP}}, {}},
352
353 /* Press key again before debounce expires */
354 {300, {{0, 1, DOWN}}, {}},
355 });
356 time_jumps_ = true;
357 runEvents();
358}
359
360TEST_F(DebounceTest, OneKeyDelayedScan8) {
361 addEvents({ /* Time, Inputs, Outputs */
362 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
363
364 /* Processing is a bit late */
365 {50, {}, {}},
366 /* Release key after 1ms */
367 {51, {{0, 1, UP}}, {}},
368
369 /* Processing is a bit late again */
370 {100, {}, {{0, 1, UP}}},
371 });
372 time_jumps_ = true;
373 runEvents();
374}
diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp
new file mode 100644
index 000000000..1c5e7c9f4
--- /dev/null
+++ b/quantum/debounce/tests/debounce_test_common.cpp
@@ -0,0 +1,229 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21#include <algorithm>
22#include <iomanip>
23#include <sstream>
24
25extern "C" {
26#include "quantum.h"
27#include "timer.h"
28#include "debounce.h"
29
30void set_time(uint32_t t);
31void advance_time(uint32_t ms);
32}
33
34void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) {
35 events_.insert(events_.end(), events.begin(), events.end());
36}
37
38void DebounceTest::runEvents() {
39 /* Run the test multiple times, from 1kHz to 10kHz scan rate */
40 for (extra_iterations_ = 0; extra_iterations_ < 10; extra_iterations_++) {
41 if (time_jumps_) {
42 /* Don't advance time smoothly, jump to the next event (some tests require this) */
43 auto_advance_time_ = false;
44 runEventsInternal();
45 } else {
46 /* Run the test with both smooth and irregular time; it must produce the same result */
47 auto_advance_time_ = true;
48 runEventsInternal();
49 auto_advance_time_ = false;
50 runEventsInternal();
51 }
52 }
53}
54
55void DebounceTest::runEventsInternal() {
56 fast_timer_t previous = 0;
57 bool first = true;
58
59 /* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */
60 debounce_init(MATRIX_ROWS);
61 set_time(time_offset_);
62 std::fill(std::begin(input_matrix_), std::end(input_matrix_), 0);
63 std::fill(std::begin(output_matrix_), std::end(output_matrix_), 0);
64
65 for (auto &event : events_) {
66 if (!auto_advance_time_) {
67 /* Jump to the next event */
68 set_time(time_offset_ + event.time_);
69 } else if (!first && event.time_ == previous + 1) {
70 /* This event immediately follows the previous one, don't make extra debounce() calls */
71 advance_time(1);
72 } else {
73 /* Fast forward to the time for this event, calling debounce() with no changes */
74 ASSERT_LT((time_offset_ + event.time_) - timer_read_fast(), 60000) << "Test tries to advance more than 1 minute of time";
75
76 while (timer_read_fast() != time_offset_ + event.time_) {
77 runDebounce(false);
78 checkCookedMatrix(false, "debounce() modified cooked matrix");
79 advance_time(1);
80 }
81 }
82
83 first = false;
84 previous = event.time_;
85
86 /* Prepare input matrix */
87 for (auto &input : event.inputs_) {
88 matrixUpdate(input_matrix_, "input", input);
89 }
90
91 /* Call debounce */
92 runDebounce(!event.inputs_.empty());
93
94 /* Prepare output matrix */
95 for (auto &output : event.outputs_) {
96 matrixUpdate(output_matrix_, "output", output);
97 }
98
99 /* Check output matrix has expected change events */
100 for (auto &output : event.outputs_) {
101 EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_))
102 << "Missing event at " << strTime()
103 << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_)
104 << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_)
105 << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
106 << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
107 }
108
109 /* Check output matrix has no other changes */
110 checkCookedMatrix(!event.inputs_.empty(), "debounce() cooked matrix does not match expected output matrix");
111
112 /* Perform some extra iterations of the matrix scan with no changes */
113 for (int i = 0; i < extra_iterations_; i++) {
114 runDebounce(false);
115 checkCookedMatrix(false, "debounce() modified cooked matrix");
116 }
117 }
118
119 /* Check that no further changes happen for 1 minute */
120 for (int i = 0; i < 60000; i++) {
121 runDebounce(false);
122 checkCookedMatrix(false, "debounce() modified cooked matrix");
123 advance_time(1);
124 }
125
126 debounce_free();
127}
128
129void DebounceTest::runDebounce(bool changed) {
130 std::copy(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_));
131 std::copy(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_));
132
133 debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed);
134
135 if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) {
136 FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime()
137 << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
138 << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
139 }
140}
141
142void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) {
143 if (!std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_))) {
144 FAIL() << "Unexpected event: " << error_message << " at " << strTime()
145 << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
146 << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
147 << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
148 }
149}
150
151std::string DebounceTest::strTime() {
152 std::stringstream text;
153
154 text << "time " << (timer_read_fast() - time_offset_)
155 << " (extra_iterations=" << extra_iterations_
156 << ", auto_advance_time=" << auto_advance_time_ << ")";
157
158 return text.str();
159}
160
161std::string DebounceTest::strMatrix(matrix_row_t matrix[]) {
162 std::stringstream text;
163
164 text << "\t" << std::setw(3) << "";
165 for (int col = 0; col < MATRIX_COLS; col++) {
166 text << " " << std::setw(2) << col;
167 }
168 text << "\n";
169
170 for (int row = 0; row < MATRIX_ROWS; row++) {
171 text << "\t" << std::setw(2) << row << ":";
172 for (int col = 0; col < MATRIX_COLS; col++) {
173 text << ((matrix[row] & (1U << col)) ? " XX" : " __");
174 }
175
176 text << "\n";
177 }
178
179 return text.str();
180}
181
182bool DebounceTest::directionValue(Direction direction) {
183 switch (direction) {
184 case DOWN:
185 return true;
186
187 case UP:
188 return false;
189 }
190}
191
192std::string DebounceTest::directionLabel(Direction direction) {
193 switch (direction) {
194 case DOWN:
195 return "DOWN";
196
197 case UP:
198 return "UP";
199 }
200}
201
202/* Modify a matrix and verify that events always specify a change */
203void DebounceTest::matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event) {
204 ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_))
205 << "Test " << name << " at " << strTime()
206 << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_)
207 << " but it is already " << directionLabel(event.direction_)
208 << "\n" << name << "_matrix:\n" << strMatrix(matrix);
209
210 switch (event.direction_) {
211 case DOWN:
212 matrix[event.row_] |= (1U << event.col_);
213 break;
214
215 case UP:
216 matrix[event.row_] &= ~(1U << event.col_);
217 break;
218 }
219}
220
221DebounceTestEvent::DebounceTestEvent(fast_timer_t time,
222 std::initializer_list<MatrixTestEvent> inputs,
223 std::initializer_list<MatrixTestEvent> outputs)
224 : time_(time), inputs_(inputs), outputs_(outputs) {
225}
226
227MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction)
228 : row_(row), col_(col), direction_(direction) {
229}
diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h
new file mode 100644
index 000000000..d87e31059
--- /dev/null
+++ b/quantum/debounce/tests/debounce_test_common.h
@@ -0,0 +1,83 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include <initializer_list>
20#include <list>
21#include <string>
22
23extern "C" {
24#include "quantum.h"
25#include "timer.h"
26}
27
28enum Direction {
29 DOWN,
30 UP,
31};
32
33class MatrixTestEvent {
34public:
35 MatrixTestEvent(int row, int col, Direction direction);
36
37 const int row_;
38 const int col_;
39 const Direction direction_;
40};
41
42class DebounceTestEvent {
43public:
44 // 0, {{0, 1, DOWN}}, {{0, 1, DOWN}})
45 DebounceTestEvent(fast_timer_t time,
46 std::initializer_list<MatrixTestEvent> inputs,
47 std::initializer_list<MatrixTestEvent> outputs);
48
49 const fast_timer_t time_;
50 const std::list<MatrixTestEvent> inputs_;
51 const std::list<MatrixTestEvent> outputs_;
52};
53
54class DebounceTest : public ::testing::Test {
55protected:
56 void addEvents(std::initializer_list<DebounceTestEvent> events);
57 void runEvents();
58
59 fast_timer_t time_offset_ = 7777;
60 bool time_jumps_ = false;
61
62private:
63 static bool directionValue(Direction direction);
64 static std::string directionLabel(Direction direction);
65
66 void runEventsInternal();
67 void runDebounce(bool changed);
68 void checkCookedMatrix(bool changed, const std::string &error_message);
69 void matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event);
70
71 std::string strTime();
72 std::string strMatrix(matrix_row_t matrix[]);
73
74 std::list<DebounceTestEvent> events_;
75
76 matrix_row_t input_matrix_[MATRIX_ROWS];
77 matrix_row_t raw_matrix_[MATRIX_ROWS];
78 matrix_row_t cooked_matrix_[MATRIX_ROWS];
79 matrix_row_t output_matrix_[MATRIX_ROWS];
80
81 int extra_iterations_;
82 bool auto_advance_time_;
83};
diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk
new file mode 100644
index 000000000..66928d7eb
--- /dev/null
+++ b/quantum/debounce/tests/rules.mk
@@ -0,0 +1,44 @@
1# Copyright 2021 Simon Arlott
2#
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation, either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5
17
18DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \
19 $(TMK_PATH)/common/test/timer.c
20
21debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS)
22debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \
23 $(QUANTUM_PATH)/debounce/sym_defer_g.c \
24 $(QUANTUM_PATH)/debounce/tests/sym_defer_g_tests.cpp
25
26debounce_sym_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
27debounce_sym_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
28 $(QUANTUM_PATH)/debounce/sym_defer_pk.c \
29 $(QUANTUM_PATH)/debounce/tests/sym_defer_pk_tests.cpp
30
31debounce_sym_eager_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
32debounce_sym_eager_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
33 $(QUANTUM_PATH)/debounce/sym_eager_pk.c \
34 $(QUANTUM_PATH)/debounce/tests/sym_eager_pk_tests.cpp
35
36debounce_sym_eager_pr_DEFS := $(DEBOUNCE_COMMON_DEFS)
37debounce_sym_eager_pr_SRC := $(DEBOUNCE_COMMON_SRC) \
38 $(QUANTUM_PATH)/debounce/sym_eager_pr.c \
39 $(QUANTUM_PATH)/debounce/tests/sym_eager_pr_tests.cpp
40
41debounce_asym_eager_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
42debounce_asym_eager_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
43 $(QUANTUM_PATH)/debounce/asym_eager_defer_pk.c \
44 $(QUANTUM_PATH)/debounce/tests/asym_eager_defer_pk_tests.cpp
diff --git a/quantum/debounce/tests/sym_defer_g_tests.cpp b/quantum/debounce/tests/sym_defer_g_tests.cpp
new file mode 100644
index 000000000..a56aecd8f
--- /dev/null
+++ b/quantum/debounce/tests/sym_defer_g_tests.cpp
@@ -0,0 +1,223 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {}},
24
25 {5, {}, {{0, 1, DOWN}}},
26 /* 0ms delay (fast scan rate) */
27 {5, {{0, 1, UP}}, {}},
28
29 {10, {}, {{0, 1, UP}}},
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {}},
37
38 {5, {}, {{0, 1, DOWN}}},
39 /* 1ms delay */
40 {6, {{0, 1, UP}}, {}},
41
42 {11, {}, {{0, 1, UP}}},
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {}},
50
51 {5, {}, {{0, 1, DOWN}}},
52 /* 2ms delay */
53 {7, {{0, 1, UP}}, {}},
54
55 {12, {}, {{0, 1, UP}}},
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyTooQuick1) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {}},
63 /* Release key exactly on the debounce time */
64 {5, {{0, 1, UP}}, {}},
65 });
66 runEvents();
67}
68
69TEST_F(DebounceTest, OneKeyTooQuick2) {
70 addEvents({ /* Time, Inputs, Outputs */
71 {0, {{0, 1, DOWN}}, {}},
72
73 {5, {}, {{0, 1, DOWN}}},
74 {6, {{0, 1, UP}}, {}},
75
76 /* Press key exactly on the debounce time */
77 {11, {{0, 1, DOWN}}, {}},
78 });
79 runEvents();
80}
81
82TEST_F(DebounceTest, OneKeyBouncing1) {
83 addEvents({ /* Time, Inputs, Outputs */
84 {0, {{0, 1, DOWN}}, {}},
85 {1, {{0, 1, UP}}, {}},
86 {2, {{0, 1, DOWN}}, {}},
87 {3, {{0, 1, UP}}, {}},
88 {4, {{0, 1, DOWN}}, {}},
89 {5, {{0, 1, UP}}, {}},
90 {6, {{0, 1, DOWN}}, {}},
91 {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */
92 });
93 runEvents();
94}
95
96TEST_F(DebounceTest, OneKeyBouncing2) {
97 addEvents({ /* Time, Inputs, Outputs */
98 {0, {{0, 1, DOWN}}, {}},
99 {5, {}, {{0, 1, DOWN}}},
100 {6, {{0, 1, UP}}, {}},
101 {7, {{0, 1, DOWN}}, {}},
102 {8, {{0, 1, UP}}, {}},
103 {9, {{0, 1, DOWN}}, {}},
104 {10, {{0, 1, UP}}, {}},
105 {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */
106 });
107 runEvents();
108}
109
110TEST_F(DebounceTest, OneKeyLong) {
111 addEvents({ /* Time, Inputs, Outputs */
112 {0, {{0, 1, DOWN}}, {}},
113
114 {5, {}, {{0, 1, DOWN}}},
115
116 {25, {{0, 1, UP}}, {}},
117
118 {30, {}, {{0, 1, UP}}},
119
120 {50, {{0, 1, DOWN}}, {}},
121
122 {55, {}, {{0, 1, DOWN}}},
123 });
124 runEvents();
125}
126
127TEST_F(DebounceTest, TwoKeysShort) {
128 addEvents({ /* Time, Inputs, Outputs */
129 {0, {{0, 1, DOWN}}, {}},
130 {1, {{0, 2, DOWN}}, {}},
131
132 {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
133
134 {7, {{0, 1, UP}}, {}},
135 {8, {{0, 2, UP}}, {}},
136
137 {13, {}, {{0, 1, UP}, {0, 2, UP}}},
138 });
139 runEvents();
140}
141
142TEST_F(DebounceTest, TwoKeysSimultaneous1) {
143 addEvents({ /* Time, Inputs, Outputs */
144 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
145
146 {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
147 {6, {{0, 1, UP}, {0, 2, UP}}, {}},
148
149 {11, {}, {{0, 1, UP}, {0, 2, UP}}},
150 });
151 runEvents();
152}
153
154TEST_F(DebounceTest, TwoKeysSimultaneous2) {
155 addEvents({ /* Time, Inputs, Outputs */
156 {0, {{0, 1, DOWN}}, {}},
157 {1, {{0, 2, DOWN}}, {}},
158
159 {5, {}, {}},
160 {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
161 {7, {{0, 1, UP}}, {}},
162 {8, {{0, 2, UP}}, {}},
163
164 {13, {}, {{0, 1, UP}, {0, 2, UP}}},
165 });
166 runEvents();
167}
168
169TEST_F(DebounceTest, OneKeyDelayedScan1) {
170 addEvents({ /* Time, Inputs, Outputs */
171 {0, {{0, 1, DOWN}}, {}},
172
173 /* Processing is very late */
174 {300, {}, {{0, 1, DOWN}}},
175 /* Immediately release key */
176 {300, {{0, 1, UP}}, {}},
177
178 {305, {}, {{0, 1, UP}}},
179 });
180 time_jumps_ = true;
181 runEvents();
182}
183
184TEST_F(DebounceTest, OneKeyDelayedScan2) {
185 addEvents({ /* Time, Inputs, Outputs */
186 {0, {{0, 1, DOWN}}, {}},
187
188 /* Processing is very late */
189 {300, {}, {{0, 1, DOWN}}},
190 /* Release key after 1ms */
191 {301, {{0, 1, UP}}, {}},
192
193 {306, {}, {{0, 1, UP}}},
194 });
195 time_jumps_ = true;
196 runEvents();
197}
198
199TEST_F(DebounceTest, OneKeyDelayedScan3) {
200 addEvents({ /* Time, Inputs, Outputs */
201 {0, {{0, 1, DOWN}}, {}},
202
203 /* Release key before debounce expires */
204 {300, {{0, 1, UP}}, {}},
205 });
206 time_jumps_ = true;
207 runEvents();
208}
209
210TEST_F(DebounceTest, OneKeyDelayedScan4) {
211 addEvents({ /* Time, Inputs, Outputs */
212 {0, {{0, 1, DOWN}}, {}},
213
214 /* Processing is a bit late */
215 {50, {}, {{0, 1, DOWN}}},
216 /* Release key after 1ms */
217 {51, {{0, 1, UP}}, {}},
218
219 {56, {}, {{0, 1, UP}}},
220 });
221 time_jumps_ = true;
222 runEvents();
223}
diff --git a/quantum/debounce/tests/sym_defer_pk_tests.cpp b/quantum/debounce/tests/sym_defer_pk_tests.cpp
new file mode 100644
index 000000000..1f3061e59
--- /dev/null
+++ b/quantum/debounce/tests/sym_defer_pk_tests.cpp
@@ -0,0 +1,225 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {}},
24
25 {5, {}, {{0, 1, DOWN}}},
26 /* 0ms delay (fast scan rate) */
27 {5, {{0, 1, UP}}, {}},
28
29 {10, {}, {{0, 1, UP}}},
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {}},
37
38 {5, {}, {{0, 1, DOWN}}},
39 /* 1ms delay */
40 {6, {{0, 1, UP}}, {}},
41
42 {11, {}, {{0, 1, UP}}},
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {}},
50
51 {5, {}, {{0, 1, DOWN}}},
52 /* 2ms delay */
53 {7, {{0, 1, UP}}, {}},
54
55 {12, {}, {{0, 1, UP}}},
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyTooQuick1) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {}},
63 /* Release key exactly on the debounce time */
64 {5, {{0, 1, UP}}, {}},
65 });
66 runEvents();
67}
68
69TEST_F(DebounceTest, OneKeyTooQuick2) {
70 addEvents({ /* Time, Inputs, Outputs */
71 {0, {{0, 1, DOWN}}, {}},
72
73 {5, {}, {{0, 1, DOWN}}},
74 {6, {{0, 1, UP}}, {}},
75
76 /* Press key exactly on the debounce time */
77 {11, {{0, 1, DOWN}}, {}},
78 });
79 runEvents();
80}
81
82TEST_F(DebounceTest, OneKeyBouncing1) {
83 addEvents({ /* Time, Inputs, Outputs */
84 {0, {{0, 1, DOWN}}, {}},
85 {1, {{0, 1, UP}}, {}},
86 {2, {{0, 1, DOWN}}, {}},
87 {3, {{0, 1, UP}}, {}},
88 {4, {{0, 1, DOWN}}, {}},
89 {5, {{0, 1, UP}}, {}},
90 {6, {{0, 1, DOWN}}, {}},
91 {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */
92 });
93 runEvents();
94}
95
96TEST_F(DebounceTest, OneKeyBouncing2) {
97 addEvents({ /* Time, Inputs, Outputs */
98 {0, {{0, 1, DOWN}}, {}},
99 {5, {}, {{0, 1, DOWN}}},
100 {6, {{0, 1, UP}}, {}},
101 {7, {{0, 1, DOWN}}, {}},
102 {8, {{0, 1, UP}}, {}},
103 {9, {{0, 1, DOWN}}, {}},
104 {10, {{0, 1, UP}}, {}},
105 {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */
106 });
107 runEvents();
108}
109
110TEST_F(DebounceTest, OneKeyLong) {
111 addEvents({ /* Time, Inputs, Outputs */
112 {0, {{0, 1, DOWN}}, {}},
113
114 {5, {}, {{0, 1, DOWN}}},
115
116 {25, {{0, 1, UP}}, {}},
117
118 {30, {}, {{0, 1, UP}}},
119
120 {50, {{0, 1, DOWN}}, {}},
121
122 {55, {}, {{0, 1, DOWN}}},
123 });
124 runEvents();
125}
126
127TEST_F(DebounceTest, TwoKeysShort) {
128 addEvents({ /* Time, Inputs, Outputs */
129 {0, {{0, 1, DOWN}}, {}},
130 {1, {{0, 2, DOWN}}, {}},
131
132 {5, {}, {{0, 1, DOWN}}},
133 {6, {}, {{0, 2, DOWN}}},
134
135 {7, {{0, 1, UP}}, {}},
136 {8, {{0, 2, UP}}, {}},
137
138 {12, {}, {{0, 1, UP}}},
139 {13, {}, {{0, 2, UP}}},
140 });
141 runEvents();
142}
143
144TEST_F(DebounceTest, TwoKeysSimultaneous1) {
145 addEvents({ /* Time, Inputs, Outputs */
146 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
147
148 {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
149 {6, {{0, 1, UP}, {0, 2, UP}}, {}},
150
151 {11, {}, {{0, 1, UP}, {0, 2, UP}}},
152 });
153 runEvents();
154}
155
156TEST_F(DebounceTest, TwoKeysSimultaneous2) {
157 addEvents({ /* Time, Inputs, Outputs */
158 {0, {{0, 1, DOWN}}, {}},
159 {1, {{0, 2, DOWN}}, {}},
160
161 {5, {}, {{0, 1, DOWN}}},
162 {6, {{0, 1, UP}}, {{0, 2, DOWN}}},
163 {7, {{0, 2, UP}}, {}},
164
165 {11, {}, {{0, 1, UP}}},
166 {12, {}, {{0, 2, UP}}},
167 });
168 runEvents();
169}
170
171TEST_F(DebounceTest, OneKeyDelayedScan1) {
172 addEvents({ /* Time, Inputs, Outputs */
173 {0, {{0, 1, DOWN}}, {}},
174
175 /* Processing is very late */
176 {300, {}, {{0, 1, DOWN}}},
177 /* Immediately release key */
178 {300, {{0, 1, UP}}, {}},
179
180 {305, {}, {{0, 1, UP}}},
181 });
182 time_jumps_ = true;
183 runEvents();
184}
185
186TEST_F(DebounceTest, OneKeyDelayedScan2) {
187 addEvents({ /* Time, Inputs, Outputs */
188 {0, {{0, 1, DOWN}}, {}},
189
190 /* Processing is very late */
191 {300, {}, {{0, 1, DOWN}}},
192 /* Release key after 1ms */
193 {301, {{0, 1, UP}}, {}},
194
195 {306, {}, {{0, 1, UP}}},
196 });
197 time_jumps_ = true;
198 runEvents();
199}
200
201TEST_F(DebounceTest, OneKeyDelayedScan3) {
202 addEvents({ /* Time, Inputs, Outputs */
203 {0, {{0, 1, DOWN}}, {}},
204
205 /* Release key before debounce expires */
206 {300, {{0, 1, UP}}, {}},
207 });
208 time_jumps_ = true;
209 runEvents();
210}
211
212TEST_F(DebounceTest, OneKeyDelayedScan4) {
213 addEvents({ /* Time, Inputs, Outputs */
214 {0, {{0, 1, DOWN}}, {}},
215
216 /* Processing is a bit late */
217 {50, {}, {{0, 1, DOWN}}},
218 /* Release key after 1ms */
219 {51, {{0, 1, UP}}, {}},
220
221 {56, {}, {{0, 1, UP}}},
222 });
223 time_jumps_ = true;
224 runEvents();
225}
diff --git a/quantum/debounce/tests/sym_eager_pk_tests.cpp b/quantum/debounce/tests/sym_eager_pk_tests.cpp
new file mode 100644
index 000000000..e0fc205e3
--- /dev/null
+++ b/quantum/debounce/tests/sym_eager_pk_tests.cpp
@@ -0,0 +1,237 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
24 {1, {{0, 1, UP}}, {}},
25
26 {5, {}, {{0, 1, UP}}},
27 /* Press key again after 1ms delay (debounce has not yet finished) */
28 {6, {{0, 1, DOWN}}, {}},
29 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
37 {1, {{0, 1, UP}}, {}},
38
39 {5, {}, {{0, 1, UP}}},
40 /* Press key again after 2ms delay (debounce has not yet finished) */
41 {7, {{0, 1, DOWN}}, {}},
42 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
50 {1, {{0, 1, UP}}, {}},
51
52 {5, {}, {{0, 1, UP}}},
53 /* Press key again after 3ms delay (debounce has not yet finished) */
54 {8, {{0, 1, DOWN}}, {}},
55 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyShort4) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
63 {1, {{0, 1, UP}}, {}},
64
65 {5, {}, {{0, 1, UP}}},
66 /* Press key again after 4ms delay (debounce has not yet finished) */
67 {9, {{0, 1, DOWN}}, {}},
68 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
69 });
70 runEvents();
71}
72
73TEST_F(DebounceTest, OneKeyShort5) {
74 addEvents({ /* Time, Inputs, Outputs */
75 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
76 {1, {{0, 1, UP}}, {}},
77
78 {5, {}, {{0, 1, UP}}},
79 /* Press key again after 5ms delay (debounce has finished) */
80 {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
81 });
82 runEvents();
83}
84
85TEST_F(DebounceTest, OneKeyShort6) {
86 addEvents({ /* Time, Inputs, Outputs */
87 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
88 {1, {{0, 1, UP}}, {}},
89
90 {5, {}, {{0, 1, UP}}},
91 /* Press key after after 6ms delay (debounce has finished) */
92 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
93 });
94 runEvents();
95}
96
97TEST_F(DebounceTest, OneKeyBouncing1) {
98 addEvents({ /* Time, Inputs, Outputs */
99 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
100 {1, {{0, 1, UP}}, {}},
101 {2, {{0, 1, DOWN}}, {}},
102 {3, {{0, 1, UP}}, {}},
103 {4, {{0, 1, DOWN}}, {}},
104 {5, {{0, 1, UP}}, {{0, 1, UP}}},
105 /* Press key again after 1ms delay (debounce has not yet finished) */
106 {6, {{0, 1, DOWN}}, {}},
107 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
108 });
109 runEvents();
110}
111
112TEST_F(DebounceTest, OneKeyBouncing2) {
113 addEvents({ /* Time, Inputs, Outputs */
114 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
115 /* Change twice in the same time period */
116 {1, {{0, 1, UP}}, {}},
117 {1, {{0, 1, DOWN}}, {}},
118 /* Change three times in the same time period */
119 {2, {{0, 1, UP}}, {}},
120 {2, {{0, 1, DOWN}}, {}},
121 {2, {{0, 1, UP}}, {}},
122 /* Change three times in the same time period */
123 {3, {{0, 1, DOWN}}, {}},
124 {3, {{0, 1, UP}}, {}},
125 {3, {{0, 1, DOWN}}, {}},
126 /* Change twice in the same time period */
127 {4, {{0, 1, UP}}, {}},
128 {4, {{0, 1, DOWN}}, {}},
129 {5, {{0, 1, UP}}, {{0, 1, UP}}},
130 /* Press key again after 1ms delay (debounce has not yet finished) */
131 {6, {{0, 1, DOWN}}, {}},
132 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
133 });
134 runEvents();
135}
136
137TEST_F(DebounceTest, OneKeyLong) {
138 addEvents({ /* Time, Inputs, Outputs */
139 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
140
141 {25, {{0, 1, UP}}, {{0, 1, UP}}},
142
143 {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
144 });
145 runEvents();
146}
147
148TEST_F(DebounceTest, TwoKeysShort) {
149 addEvents({ /* Time, Inputs, Outputs */
150 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
151 {1, {{0, 1, UP}}, {}},
152 {2, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
153 {3, {{0, 2, UP}}, {}},
154
155 {5, {}, {{0, 1, UP}}},
156 /* Press key again after 1ms delay (debounce has not yet finished) */
157 {6, {{0, 1, DOWN}}, {}},
158 {7, {}, {{0, 2, UP}}},
159
160 /* Press key again after 1ms delay (debounce has not yet finished) */
161 {9, {{0, 2, DOWN}}, {}},
162 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
163
164 {12, {}, {{0, 2, DOWN}}}, /* 5ms after UP at time 7 */
165 });
166 runEvents();
167}
168
169TEST_F(DebounceTest, OneKeyDelayedScan1) {
170 addEvents({ /* Time, Inputs, Outputs */
171 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
172
173 /* Processing is very late but the change will now be accepted */
174 {300, {{0, 1, UP}}, {{0, 1, UP}}},
175 });
176 time_jumps_ = true;
177 runEvents();
178}
179
180TEST_F(DebounceTest, OneKeyDelayedScan2) {
181 addEvents({ /* Time, Inputs, Outputs */
182 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
183
184 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
185 {300, {}, {}},
186 {300, {{0, 1, UP}}, {{0, 1, UP}}},
187 });
188 time_jumps_ = true;
189 runEvents();
190}
191
192TEST_F(DebounceTest, OneKeyDelayedScan3) {
193 addEvents({ /* Time, Inputs, Outputs */
194 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
195
196 /* Processing is very late but the change will now be accepted even with a 1ms delay */
197 {300, {}, {}},
198 {301, {{0, 1, UP}}, {{0, 1, UP}}},
199 });
200 time_jumps_ = true;
201 runEvents();
202}
203
204TEST_F(DebounceTest, OneKeyDelayedScan4) {
205 addEvents({ /* Time, Inputs, Outputs */
206 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
207
208 /* Processing is a bit late but the change will now be accepted */
209 {50, {{0, 1, UP}}, {{0, 1, UP}}},
210 });
211 time_jumps_ = true;
212 runEvents();
213}
214
215TEST_F(DebounceTest, OneKeyDelayedScan5) {
216 addEvents({ /* Time, Inputs, Outputs */
217 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
218
219 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
220 {50, {}, {}},
221 {50, {{0, 1, UP}}, {{0, 1, UP}}},
222 });
223 time_jumps_ = true;
224 runEvents();
225}
226
227TEST_F(DebounceTest, OneKeyDelayedScan6) {
228 addEvents({ /* Time, Inputs, Outputs */
229 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
230
231 /* Processing is very late but the change will now be accepted even with a 1ms delay */
232 {50, {}, {}},
233 {51, {{0, 1, UP}}, {{0, 1, UP}}},
234 });
235 time_jumps_ = true;
236 runEvents();
237}
diff --git a/quantum/debounce/tests/sym_eager_pr_tests.cpp b/quantum/debounce/tests/sym_eager_pr_tests.cpp
new file mode 100644
index 000000000..2c4bca127
--- /dev/null
+++ b/quantum/debounce/tests/sym_eager_pr_tests.cpp
@@ -0,0 +1,280 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
24 {1, {{0, 1, UP}}, {}},
25
26 {5, {}, {{0, 1, UP}}},
27 /* Press key again after 1ms delay (debounce has not yet finished) */
28 {6, {{0, 1, DOWN}}, {}},
29 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
37 {1, {{0, 1, UP}}, {}},
38
39 {5, {}, {{0, 1, UP}}},
40 /* Press key again after 2ms delay (debounce has not yet finished) */
41 {7, {{0, 1, DOWN}}, {}},
42 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
50 {1, {{0, 1, UP}}, {}},
51
52 {5, {}, {{0, 1, UP}}},
53 /* Press key again after 3ms delay (debounce has not yet finished) */
54 {8, {{0, 1, DOWN}}, {}},
55 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyShort4) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
63 {1, {{0, 1, UP}}, {}},
64
65 {5, {}, {{0, 1, UP}}},
66 /* Press key again after 4ms delay (debounce has not yet finished) */
67 {9, {{0, 1, DOWN}}, {}},
68 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
69 });
70 runEvents();
71}
72
73TEST_F(DebounceTest, OneKeyShort5) {
74 addEvents({ /* Time, Inputs, Outputs */
75 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
76 {1, {{0, 1, UP}}, {}},
77
78 {5, {}, {{0, 1, UP}}},
79 /* Press key again after 5ms delay (debounce has finished) */
80 {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
81 });
82 runEvents();
83}
84
85TEST_F(DebounceTest, OneKeyShort6) {
86 addEvents({ /* Time, Inputs, Outputs */
87 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
88 {1, {{0, 1, UP}}, {}},
89
90 {5, {}, {{0, 1, UP}}},
91 /* Press key after after 6ms delay (debounce has finished) */
92 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
93 });
94 runEvents();
95}
96
97TEST_F(DebounceTest, OneKeyBouncing1) {
98 addEvents({ /* Time, Inputs, Outputs */
99 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
100 {1, {{0, 1, UP}}, {}},
101 {2, {{0, 1, DOWN}}, {}},
102 {3, {{0, 1, UP}}, {}},
103 {4, {{0, 1, DOWN}}, {}},
104 {5, {{0, 1, UP}}, {{0, 1, UP}}},
105 /* Press key again after 1ms delay (debounce has not yet finished) */
106 {6, {{0, 1, DOWN}}, {}},
107 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
108 });
109 runEvents();
110}
111
112TEST_F(DebounceTest, OneKeyBouncing2) {
113 addEvents({ /* Time, Inputs, Outputs */
114 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
115 /* Change twice in the same time period */
116 {1, {{0, 1, UP}}, {}},
117 {1, {{0, 1, DOWN}}, {}},
118 /* Change three times in the same time period */
119 {2, {{0, 1, UP}}, {}},
120 {2, {{0, 1, DOWN}}, {}},
121 {2, {{0, 1, UP}}, {}},
122 /* Change three times in the same time period */
123 {3, {{0, 1, DOWN}}, {}},
124 {3, {{0, 1, UP}}, {}},
125 {3, {{0, 1, DOWN}}, {}},
126 /* Change twice in the same time period */
127 {4, {{0, 1, UP}}, {}},
128 {4, {{0, 1, DOWN}}, {}},
129 {5, {{0, 1, UP}}, {{0, 1, UP}}},
130 /* Press key again after 1ms delay (debounce has not yet finished) */
131 {6, {{0, 1, DOWN}}, {}},
132 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
133 });
134 runEvents();
135}
136
137TEST_F(DebounceTest, OneKeyLong) {
138 addEvents({ /* Time, Inputs, Outputs */
139 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
140
141 {25, {{0, 1, UP}}, {{0, 1, UP}}},
142
143 {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
144 });
145 runEvents();
146}
147
148TEST_F(DebounceTest, TwoRowsShort) {
149 addEvents({ /* Time, Inputs, Outputs */
150 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
151 {1, {{0, 1, UP}}, {}},
152 {2, {{2, 0, DOWN}}, {{2, 0, DOWN}}},
153 {3, {{2, 0, UP}}, {}},
154
155 {5, {}, {{0, 1, UP}}},
156 /* Press key again after 1ms delay (debounce has not yet finished) */
157 {6, {{0, 1, DOWN}}, {}},
158 {7, {}, {{2, 0, UP}}},
159
160 /* Press key again after 1ms delay (debounce has not yet finished) */
161 {9, {{2, 0, DOWN}}, {}},
162 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
163
164 {12, {}, {{2, 0, DOWN}}}, /* 5ms after UP at time 7 */
165 });
166 runEvents();
167}
168
169TEST_F(DebounceTest, TwoKeysOverlap) {
170 addEvents({ /* Time, Inputs, Outputs */
171 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
172 {1, {{0, 1, UP}}, {}},
173 /* Press a second key during the first debounce */
174 {2, {{0, 2, DOWN}}, {}},
175
176 /* Key registers as soon as debounce finishes, 5ms after time 0 */
177 {5, {}, {{0, 1, UP}, {0, 2, DOWN}}},
178 {6, {{0, 1, DOWN}}, {}},
179
180 /* Key registers as soon as debounce finishes, 5ms after time 5 */
181 {10, {}, {{0, 1, DOWN}}},
182 /* Release both keys */
183 {11, {{0, 1, UP}}, {}},
184 {12, {{0, 2, UP}}, {}},
185
186 /* Keys register as soon as debounce finishes, 5ms after time 10 */
187 {15, {}, {{0, 1, UP}, {0, 2, UP}}},
188 });
189 runEvents();
190}
191
192TEST_F(DebounceTest, TwoKeysSimultaneous1) {
193 addEvents({ /* Time, Inputs, Outputs */
194 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
195 {20, {{0, 1, UP}}, {{0, 1, UP}}},
196 {21, {{0, 2, UP}}, {}},
197
198 /* Key registers as soon as debounce finishes, 5ms after time 20 */
199 {25, {}, {{0, 2, UP}}},
200 });
201 runEvents();
202}
203
204TEST_F(DebounceTest, TwoKeysSimultaneous2) {
205 addEvents({ /* Time, Inputs, Outputs */
206 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
207 {20, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}},
208 });
209 runEvents();
210}
211
212TEST_F(DebounceTest, OneKeyDelayedScan1) {
213 addEvents({ /* Time, Inputs, Outputs */
214 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
215
216 /* Processing is very late but the change will now be accepted */
217 {300, {{0, 1, UP}}, {{0, 1, UP}}},
218 });
219 time_jumps_ = true;
220 runEvents();
221}
222
223TEST_F(DebounceTest, OneKeyDelayedScan2) {
224 addEvents({ /* Time, Inputs, Outputs */
225 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
226
227 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
228 {300, {}, {}},
229 {300, {{0, 1, UP}}, {{0, 1, UP}}},
230 });
231 time_jumps_ = true;
232 runEvents();
233}
234
235TEST_F(DebounceTest, OneKeyDelayedScan3) {
236 addEvents({ /* Time, Inputs, Outputs */
237 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
238
239 /* Processing is very late but the change will now be accepted even with a 1ms delay */
240 {300, {}, {}},
241 {301, {{0, 1, UP}}, {{0, 1, UP}}},
242 });
243 time_jumps_ = true;
244 runEvents();
245}
246
247TEST_F(DebounceTest, OneKeyDelayedScan4) {
248 addEvents({ /* Time, Inputs, Outputs */
249 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
250
251 /* Processing is a bit late but the change will now be accepted */
252 {50, {{0, 1, UP}}, {{0, 1, UP}}},
253 });
254 time_jumps_ = true;
255 runEvents();
256}
257
258TEST_F(DebounceTest, OneKeyDelayedScan5) {
259 addEvents({ /* Time, Inputs, Outputs */
260 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
261
262 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
263 {50, {}, {}},
264 {50, {{0, 1, UP}}, {{0, 1, UP}}},
265 });
266 time_jumps_ = true;
267 runEvents();
268}
269
270TEST_F(DebounceTest, OneKeyDelayedScan6) {
271 addEvents({ /* Time, Inputs, Outputs */
272 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
273
274 /* Processing is very late but the change will now be accepted even with a 1ms delay */
275 {50, {}, {}},
276 {51, {{0, 1, UP}}, {{0, 1, UP}}},
277 });
278 time_jumps_ = true;
279 runEvents();
280}
diff --git a/quantum/debounce/tests/testlist.mk b/quantum/debounce/tests/testlist.mk
new file mode 100644
index 000000000..c54c45aa6
--- /dev/null
+++ b/quantum/debounce/tests/testlist.mk
@@ -0,0 +1,6 @@
1TEST_LIST += \
2 debounce_sym_defer_g \
3 debounce_sym_defer_pk \
4 debounce_sym_eager_pk \
5 debounce_sym_eager_pr \
6 debounce_asym_eager_defer_pk
diff --git a/quantum/led_matrix_animations/alpha_mods_anim.h b/quantum/led_matrix/animations/alpha_mods_anim.h
index 6f69f6892..a4638fde6 100644
--- a/quantum/led_matrix_animations/alpha_mods_anim.h
+++ b/quantum/led_matrix/animations/alpha_mods_anim.h
@@ -21,4 +21,4 @@ bool ALPHAS_MODS(effect_params_t* params) {
21} 21}
22 22
23# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 23# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
24#endif // DISABLE_LED_MATRIX_ALPHAS_MODS 24#endif // DISABLE_LED_MATRIX_ALPHAS_MODS
diff --git a/quantum/led_matrix_animations/band_anim.h b/quantum/led_matrix/animations/band_anim.h
index 523dba1b7..f9cb85dc4 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) {
10bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); } 10bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); }
11 11
12# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 12# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
13#endif // DISABLE_LED_MATRIX_BAND 13#endif // DISABLE_LED_MATRIX_BAND
diff --git a/quantum/led_matrix_animations/band_pinwheel_anim.h b/quantum/led_matrix/animations/band_pinwheel_anim.h
index fb3b835ca..d3144bffb 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
7bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); } 7bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_BAND_PINWHEEL 10#endif // DISABLE_LED_MATRIX_BAND_PINWHEEL
diff --git a/quantum/led_matrix_animations/band_spiral_anim.h b/quantum/led_matrix/animations/band_spiral_anim.h
index fca22aad9..defbe6967 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
7bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); } 7bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_BAND_SPIRAL 10#endif // DISABLE_LED_MATRIX_BAND_SPIRAL
diff --git a/quantum/led_matrix_animations/breathing_anim.h b/quantum/led_matrix/animations/breathing_anim.h
index 00310e3f6..4f49f5069 100644
--- a/quantum/led_matrix_animations/breathing_anim.h
+++ b/quantum/led_matrix/animations/breathing_anim.h
@@ -16,4 +16,4 @@ bool BREATHING(effect_params_t* params) {
16} 16}
17 17
18# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 18# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
19#endif // DISABLE_LED_MATRIX_BREATHING 19#endif // DISABLE_LED_MATRIX_BREATHING
diff --git a/quantum/led_matrix_animations/cycle_left_right_anim.h b/quantum/led_matrix/animations/cycle_left_right_anim.h
index 51e81d57c..c426d02fd 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
7bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); } 7bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT 10#endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
diff --git a/quantum/led_matrix_animations/cycle_out_in_anim.h b/quantum/led_matrix/animations/cycle_out_in_anim.h
index f62061552..55527556f 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
7bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); } 7bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN 10#endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN
diff --git a/quantum/led_matrix_animations/cycle_up_down_anim.h b/quantum/led_matrix/animations/cycle_up_down_anim.h
index bd1d12567..d97de0d1e 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
7bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); } 7bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN 10#endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN
diff --git a/quantum/led_matrix_animations/dual_beacon_anim.h b/quantum/led_matrix/animations/dual_beacon_anim.h
index 9b8a7877c..e1bc5ae46 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,
7bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); } 7bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_DUAL_BEACON 10#endif // DISABLE_LED_MATRIX_DUAL_BEACON
diff --git a/quantum/led_matrix/animations/led_matrix_effects.inc b/quantum/led_matrix/animations/led_matrix_effects.inc
new file mode 100644
index 000000000..ad1f46b24
--- /dev/null
+++ b/quantum/led_matrix/animations/led_matrix_effects.inc
@@ -0,0 +1,18 @@
1// Add your new core led matrix effect here, order determines enum order
2#include "solid_anim.h"
3#include "alpha_mods_anim.h"
4#include "breathing_anim.h"
5#include "band_anim.h"
6#include "band_pinwheel_anim.h"
7#include "band_spiral_anim.h"
8#include "cycle_left_right_anim.h"
9#include "cycle_up_down_anim.h"
10#include "cycle_out_in_anim.h"
11#include "dual_beacon_anim.h"
12#include "solid_reactive_simple_anim.h"
13#include "solid_reactive_wide.h"
14#include "solid_reactive_cross.h"
15#include "solid_reactive_nexus.h"
16#include "solid_splash_anim.h"
17#include "wave_left_right_anim.h"
18#include "wave_up_down_anim.h"
diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
index ef97631b9..ef97631b9 100644
--- a/quantum/led_matrix_runners/effect_runner_dx_dy.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
index 5ef5938be..5ef5938be 100644
--- a/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
diff --git a/quantum/led_matrix_runners/effect_runner_i.h b/quantum/led_matrix/animations/runners/effect_runner_i.h
index b3015759b..b3015759b 100644
--- a/quantum/led_matrix_runners/effect_runner_i.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_i.h
diff --git a/quantum/led_matrix_runners/effect_runner_reactive.h b/quantum/led_matrix/animations/runners/effect_runner_reactive.h
index 4369ea8c4..4369ea8c4 100644
--- a/quantum/led_matrix_runners/effect_runner_reactive.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_reactive.h
diff --git a/quantum/led_matrix_runners/effect_runner_reactive_splash.h b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
index d6eb9731e..d6eb9731e 100644
--- a/quantum/led_matrix_runners/effect_runner_reactive_splash.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
diff --git a/quantum/led_matrix_runners/effect_runner_sin_cos_i.h b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
index 4a5219abd..4a5219abd 100644
--- a/quantum/led_matrix_runners/effect_runner_sin_cos_i.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
diff --git a/quantum/led_matrix/animations/runners/led_matrix_runners.inc b/quantum/led_matrix/animations/runners/led_matrix_runners.inc
new file mode 100644
index 000000000..c09022bb0
--- /dev/null
+++ b/quantum/led_matrix/animations/runners/led_matrix_runners.inc
@@ -0,0 +1,6 @@
1#include "effect_runner_dx_dy_dist.h"
2#include "effect_runner_dx_dy.h"
3#include "effect_runner_i.h"
4#include "effect_runner_sin_cos_i.h"
5#include "effect_runner_reactive.h"
6#include "effect_runner_reactive_splash.h"
diff --git a/quantum/led_matrix_animations/solid_anim.h b/quantum/led_matrix/animations/solid_anim.h
index 4c9e43c58..4c9e43c58 100644
--- a/quantum/led_matrix_animations/solid_anim.h
+++ b/quantum/led_matrix/animations/solid_anim.h
diff --git a/quantum/led_matrix_animations/solid_reactive_cross.h b/quantum/led_matrix/animations/solid_reactive_cross.h
index f402d99b3..94425c959 100644
--- a/quantum/led_matrix_animations/solid_reactive_cross.h
+++ b/quantum/led_matrix/animations/solid_reactive_cross.h
@@ -31,5 +31,5 @@ bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_r
31# endif 31# endif
32 32
33# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 33# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
34# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) 34# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
35#endif // LED_MATRIX_KEYREACTIVE_ENABLED 35#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 4d0d25226..504b1104f 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
28# endif 28# endif
29 29
30# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 30# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
31# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) 31# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
32#endif // LED_MATRIX_KEYREACTIVE_ENABLED 32#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 30e2527f6..4752a8416 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
8bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); } 8bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); }
9 9
10# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 10# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
11# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE 11# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
12#endif // LED_MATRIX_KEYREACTIVE_ENABLED 12#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 34a230c25..922e32fe5 100644
--- a/quantum/led_matrix_animations/solid_reactive_wide.h
+++ b/quantum/led_matrix/animations/solid_reactive_wide.h
@@ -26,5 +26,5 @@ bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_re
26# endif 26# endif
27 27
28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
29# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) 29# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
30#endif // LED_MATRIX_KEYREACTIVE_ENABLED 30#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 4f6ba3d34..d95889b81 100644
--- a/quantum/led_matrix_animations/solid_splash_anim.h
+++ b/quantum/led_matrix/animations/solid_splash_anim.h
@@ -26,5 +26,5 @@ bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_
26# endif 26# endif
27 27
28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
29# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) 29# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH)
30#endif // LED_MATRIX_KEYREACTIVE_ENABLED 30#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 736f22ddc..8579f1b45 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
7bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); } 7bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT 10#endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT
diff --git a/quantum/led_matrix_animations/wave_up_down_anim.h b/quantum/led_matrix/animations/wave_up_down_anim.h
index 3cab0597d..635c60841 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
7bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); } 7bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN 10#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN
diff --git a/quantum/led_matrix.c b/quantum/led_matrix/led_matrix.c
index 7e0fdf896..32788866c 100644
--- a/quantum/led_matrix.c
+++ b/quantum/led_matrix/led_matrix.c
@@ -33,20 +33,23 @@ const led_point_t k_led_matrix_center = {112, 32};
33const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; 33const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
34#endif 34#endif
35 35
36// clang-format off
37#ifndef LED_MATRIX_IMMEDIATE_EEPROM
38# define led_eeconfig_update(v) led_update_eeprom |= v
39#else
40# define led_eeconfig_update(v) if (v) eeconfig_update_led_matrix()
41#endif
42// clang-format on
43
36// Generic effect runners 44// Generic effect runners
37#include "led_matrix_runners/effect_runner_dx_dy_dist.h" 45#include "led_matrix_runners.inc"
38#include "led_matrix_runners/effect_runner_dx_dy.h"
39#include "led_matrix_runners/effect_runner_i.h"
40#include "led_matrix_runners/effect_runner_sin_cos_i.h"
41#include "led_matrix_runners/effect_runner_reactive.h"
42#include "led_matrix_runners/effect_runner_reactive_splash.h"
43 46
44// ------------------------------------------ 47// ------------------------------------------
45// -----Begin led effect includes macros----- 48// -----Begin led effect includes macros-----
46#define LED_MATRIX_EFFECT(name) 49#define LED_MATRIX_EFFECT(name)
47#define LED_MATRIX_CUSTOM_EFFECT_IMPLS 50#define LED_MATRIX_CUSTOM_EFFECT_IMPLS
48 51
49#include "led_matrix_animations/led_matrix_effects.inc" 52#include "led_matrix_effects.inc"
50#ifdef LED_MATRIX_CUSTOM_KB 53#ifdef LED_MATRIX_CUSTOM_KB
51# include "led_matrix_kb.inc" 54# include "led_matrix_kb.inc"
52#endif 55#endif
@@ -67,10 +70,6 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
67# define LED_DISABLE_TIMEOUT 0 70# define LED_DISABLE_TIMEOUT 0
68#endif 71#endif
69 72
70#if LED_DISABLE_WHEN_USB_SUSPENDED != 1
71# undef LED_DISABLE_WHEN_USB_SUSPENDED
72#endif
73
74#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX 73#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
75# undef LED_MATRIX_MAXIMUM_BRIGHTNESS 74# undef LED_MATRIX_MAXIMUM_BRIGHTNESS
76# define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX 75# define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
@@ -108,6 +107,7 @@ last_hit_t g_last_hit_tracker;
108 107
109// internals 108// internals
110static bool suspend_state = false; 109static bool suspend_state = false;
110static bool led_update_eeprom = false;
111static uint8_t led_last_enable = UINT8_MAX; 111static uint8_t led_last_enable = UINT8_MAX;
112static uint8_t led_last_effect = UINT8_MAX; 112static uint8_t led_last_effect = UINT8_MAX;
113static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; 113static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false};
@@ -280,6 +280,8 @@ static void led_task_timers(void) {
280 280
281static void led_task_sync(void) { 281static void led_task_sync(void) {
282 // next task 282 // next task
283 if (led_update_eeprom) eeconfig_update_led_matrix();
284 led_update_eeprom = false;
283 if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING; 285 if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING;
284} 286}
285 287
@@ -318,7 +320,7 @@ static void led_task_render(uint8_t effect) {
318 case LED_MATRIX_##name: \ 320 case LED_MATRIX_##name: \
319 rendering = name(&led_effect_params); \ 321 rendering = name(&led_effect_params); \
320 break; 322 break;
321#include "led_matrix_animations/led_matrix_effects.inc" 323#include "led_matrix_effects.inc"
322#undef LED_MATRIX_EFFECT 324#undef LED_MATRIX_EFFECT
323 325
324#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) 326#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
@@ -469,9 +471,7 @@ bool led_matrix_get_suspend_state(void) { return suspend_state; }
469void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { 471void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
470 led_matrix_eeconfig.enable ^= 1; 472 led_matrix_eeconfig.enable ^= 1;
471 led_task_state = STARTING; 473 led_task_state = STARTING;
472 if (write_to_eeprom) { 474 led_eeconfig_update(write_to_eeprom);
473 eeconfig_update_led_matrix();
474 }
475 dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable); 475 dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable);
476} 476}
477void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); } 477void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); }
@@ -479,7 +479,7 @@ void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); }
479 479
480void led_matrix_enable(void) { 480void led_matrix_enable(void) {
481 led_matrix_enable_noeeprom(); 481 led_matrix_enable_noeeprom();
482 eeconfig_update_led_matrix(); 482 led_eeconfig_update(true);
483} 483}
484 484
485void led_matrix_enable_noeeprom(void) { 485void led_matrix_enable_noeeprom(void) {
@@ -489,7 +489,7 @@ void led_matrix_enable_noeeprom(void) {
489 489
490void led_matrix_disable(void) { 490void led_matrix_disable(void) {
491 led_matrix_disable_noeeprom(); 491 led_matrix_disable_noeeprom();
492 eeconfig_update_led_matrix(); 492 led_eeconfig_update(true);
493} 493}
494 494
495void led_matrix_disable_noeeprom(void) { 495void led_matrix_disable_noeeprom(void) {
@@ -511,9 +511,7 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
511 led_matrix_eeconfig.mode = mode; 511 led_matrix_eeconfig.mode = mode;
512 } 512 }
513 led_task_state = STARTING; 513 led_task_state = STARTING;
514 if (write_to_eeprom) { 514 led_eeconfig_update(write_to_eeprom);
515 eeconfig_update_led_matrix();
516 }
517 dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode); 515 dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode);
518} 516}
519void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); } 517void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); }
@@ -540,9 +538,7 @@ void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) {
540 return; 538 return;
541 } 539 }
542 led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; 540 led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val;
543 if (write_to_eeprom) { 541 led_eeconfig_update(write_to_eeprom);
544 eeconfig_update_led_matrix();
545 }
546 dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val); 542 dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val);
547} 543}
548void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); } 544void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); }
@@ -560,9 +556,7 @@ void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); }
560 556
561void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { 557void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
562 led_matrix_eeconfig.speed = speed; 558 led_matrix_eeconfig.speed = speed;
563 if (write_to_eeprom) { 559 led_eeconfig_update(write_to_eeprom);
564 eeconfig_update_led_matrix();
565 }
566 dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed); 560 dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed);
567} 561}
568void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); } 562void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); }
diff --git a/quantum/led_matrix.h b/quantum/led_matrix/led_matrix.h
index 0984de73b..6f85854fb 100644
--- a/quantum/led_matrix.h
+++ b/quantum/led_matrix/led_matrix.h
@@ -56,7 +56,7 @@ enum led_matrix_effects {
56// -------------------------------------- 56// --------------------------------------
57// -----Begin led effect enum macros----- 57// -----Begin led effect enum macros-----
58#define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name, 58#define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name,
59#include "led_matrix_animations/led_matrix_effects.inc" 59#include "led_matrix_effects.inc"
60#undef LED_MATRIX_EFFECT 60#undef LED_MATRIX_EFFECT
61 61
62#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) 62#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c
index 1d46b2c50..1d46b2c50 100644
--- a/quantum/led_matrix_drivers.c
+++ b/quantum/led_matrix/led_matrix_drivers.c
diff --git a/quantum/led_matrix_types.h b/quantum/led_matrix/led_matrix_types.h
index 61cdbd9b8..61cdbd9b8 100644
--- a/quantum/led_matrix_types.h
+++ b/quantum/led_matrix/led_matrix_types.h
diff --git a/quantum/led_matrix_animations/led_matrix_effects.inc b/quantum/led_matrix_animations/led_matrix_effects.inc
deleted file mode 100644
index 67237c568..000000000
--- a/quantum/led_matrix_animations/led_matrix_effects.inc
+++ /dev/null
@@ -1,18 +0,0 @@
1// Add your new core led matrix effect here, order determins enum order, requires "led_matrix_animations/ directory
2#include "led_matrix_animations/solid_anim.h"
3#include "led_matrix_animations/alpha_mods_anim.h"
4#include "led_matrix_animations/breathing_anim.h"
5#include "led_matrix_animations/band_anim.h"
6#include "led_matrix_animations/band_pinwheel_anim.h"
7#include "led_matrix_animations/band_spiral_anim.h"
8#include "led_matrix_animations/cycle_left_right_anim.h"
9#include "led_matrix_animations/cycle_up_down_anim.h"
10#include "led_matrix_animations/cycle_out_in_anim.h"
11#include "led_matrix_animations/dual_beacon_anim.h"
12#include "led_matrix_animations/solid_reactive_simple_anim.h"
13#include "led_matrix_animations/solid_reactive_wide.h"
14#include "led_matrix_animations/solid_reactive_cross.h"
15#include "led_matrix_animations/solid_reactive_nexus.h"
16#include "led_matrix_animations/solid_splash_anim.h"
17#include "led_matrix_animations/wave_left_right_anim.h"
18#include "led_matrix_animations/wave_up_down_anim.h"
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 34d6af2e6..71ef27089 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -16,6 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17#include <stdint.h> 17#include <stdint.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <string.h>
19#include "util.h" 20#include "util.h"
20#include "matrix.h" 21#include "matrix.h"
21#include "debounce.h" 22#include "debounce.h"
@@ -24,14 +25,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
24#ifdef DIRECT_PINS 25#ifdef DIRECT_PINS
25static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; 26static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
26#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) 27#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
28# ifdef MATRIX_ROW_PINS
27static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 29static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
30# endif // MATRIX_ROW_PINS
31# ifdef MATRIX_COL_PINS
28static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 32static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
33# endif // MATRIX_COL_PINS
29#endif 34#endif
30 35
31/* matrix state(1:on, 0:off) */ 36/* matrix state(1:on, 0:off) */
32extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values 37extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
33extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values 38extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
34 39
40// user-defined overridable functions
41__attribute__((weak)) void matrix_init_pins(void);
42__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
43__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
44
35static inline void setPinOutput_writeLow(pin_t pin) { 45static inline void setPinOutput_writeLow(pin_t pin) {
36 ATOMIC_BLOCK_FORCEON { 46 ATOMIC_BLOCK_FORCEON {
37 setPinOutput(pin); 47 setPinOutput(pin);
@@ -47,7 +57,7 @@ static inline void setPinInputHigh_atomic(pin_t pin) {
47 57
48#ifdef DIRECT_PINS 58#ifdef DIRECT_PINS
49 59
50static void init_pins(void) { 60__attribute__((weak)) void matrix_init_pins(void) {
51 for (int row = 0; row < MATRIX_ROWS; row++) { 61 for (int row = 0; row < MATRIX_ROWS; row++) {
52 for (int col = 0; col < MATRIX_COLS; col++) { 62 for (int col = 0; col < MATRIX_COLS; col++) {
53 pin_t pin = direct_pins[row][col]; 63 pin_t pin = direct_pins[row][col];
@@ -58,7 +68,7 @@ static void init_pins(void) {
58 } 68 }
59} 69}
60 70
61static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 71__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
62 // Start with a clear matrix row 72 // Start with a clear matrix row
63 matrix_row_t current_row_value = 0; 73 matrix_row_t current_row_value = 0;
64 74
@@ -69,16 +79,13 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
69 } 79 }
70 } 80 }
71 81
72 // If the row has changed, store the row and return the changed flag. 82 // Update the matrix
73 if (current_matrix[current_row] != current_row_value) { 83 current_matrix[current_row] = current_row_value;
74 current_matrix[current_row] = current_row_value;
75 return true;
76 }
77 return false;
78} 84}
79 85
80#elif defined(DIODE_DIRECTION) 86#elif defined(DIODE_DIRECTION)
81# if (DIODE_DIRECTION == COL2ROW) 87# if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
88# if (DIODE_DIRECTION == COL2ROW)
82 89
83static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } 90static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); }
84 91
@@ -90,14 +97,14 @@ static void unselect_rows(void) {
90 } 97 }
91} 98}
92 99
93static void init_pins(void) { 100__attribute__((weak)) void matrix_init_pins(void) {
94 unselect_rows(); 101 unselect_rows();
95 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 102 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
96 setPinInputHigh_atomic(col_pins[x]); 103 setPinInputHigh_atomic(col_pins[x]);
97 } 104 }
98} 105}
99 106
100static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 107__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
101 // Start with a clear matrix row 108 // Start with a clear matrix row
102 matrix_row_t current_row_value = 0; 109 matrix_row_t current_row_value = 0;
103 110
@@ -118,15 +125,11 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
118 unselect_row(current_row); 125 unselect_row(current_row);
119 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH 126 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH
120 127
121 // If the row has changed, store the row and return the changed flag. 128 // Update the matrix
122 if (current_matrix[current_row] != current_row_value) { 129 current_matrix[current_row] = current_row_value;
123 current_matrix[current_row] = current_row_value;
124 return true;
125 }
126 return false;
127} 130}
128 131
129# elif (DIODE_DIRECTION == ROW2COL) 132# elif (DIODE_DIRECTION == ROW2COL)
130 133
131static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } 134static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); }
132 135
@@ -138,59 +141,46 @@ static void unselect_cols(void) {
138 } 141 }
139} 142}
140 143
141static void init_pins(void) { 144__attribute__((weak)) void matrix_init_pins(void) {
142 unselect_cols(); 145 unselect_cols();
143 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 146 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
144 setPinInputHigh_atomic(row_pins[x]); 147 setPinInputHigh_atomic(row_pins[x]);
145 } 148 }
146} 149}
147 150
148static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 151__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
149 bool matrix_changed = false;
150
151 // Select col 152 // Select col
152 select_col(current_col); 153 select_col(current_col);
153 matrix_output_select_delay(); 154 matrix_output_select_delay();
154 155
155 // For each row... 156 // For each row...
156 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 157 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
157 // Store last value of row prior to reading
158 matrix_row_t last_row_value = current_matrix[row_index];
159 matrix_row_t current_row_value = last_row_value;
160
161 // Check row pin state 158 // Check row pin state
162 if (readPin(row_pins[row_index]) == 0) { 159 if (readPin(row_pins[row_index]) == 0) {
163 // Pin LO, set col bit 160 // Pin LO, set col bit
164 current_row_value |= (MATRIX_ROW_SHIFTER << current_col); 161 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
165 } else { 162 } else {
166 // Pin HI, clear col bit 163 // Pin HI, clear col bit
167 current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); 164 current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
168 }
169
170 // Determine if the matrix changed state
171 if ((last_row_value != current_row_value)) {
172 matrix_changed |= true;
173 current_matrix[row_index] = current_row_value;
174 } 165 }
175 } 166 }
176 167
177 // Unselect col 168 // Unselect col
178 unselect_col(current_col); 169 unselect_col(current_col);
179 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH 170 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH
180
181 return matrix_changed;
182} 171}
183 172
184# else 173# else
185# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! 174# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
186# endif 175# endif
176# endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
187#else 177#else
188# error DIODE_DIRECTION is not defined! 178# error DIODE_DIRECTION is not defined!
189#endif 179#endif
190 180
191void matrix_init(void) { 181void matrix_init(void) {
192 // initialize key pins 182 // initialize key pins
193 init_pins(); 183 matrix_init_pins();
194 184
195 // initialize matrix state: all keys off 185 // initialize matrix state: all keys off
196 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 186 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
@@ -204,20 +194,23 @@ void matrix_init(void) {
204} 194}
205 195
206uint8_t matrix_scan(void) { 196uint8_t matrix_scan(void) {
207 bool changed = false; 197 matrix_row_t curr_matrix[MATRIX_ROWS] = {0};
208 198
209#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 199#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
210 // Set row, read cols 200 // Set row, read cols
211 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 201 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
212 changed |= read_cols_on_row(raw_matrix, current_row); 202 matrix_read_cols_on_row(curr_matrix, current_row);
213 } 203 }
214#elif (DIODE_DIRECTION == ROW2COL) 204#elif (DIODE_DIRECTION == ROW2COL)
215 // Set col, read rows 205 // Set col, read rows
216 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 206 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
217 changed |= read_rows_on_col(raw_matrix, current_col); 207 matrix_read_rows_on_col(curr_matrix, current_col);
218 } 208 }
219#endif 209#endif
220 210
211 bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0;
212 if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix));
213
221 debounce(raw_matrix, matrix, MATRIX_ROWS, changed); 214 debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
222 215
223 matrix_scan_quantum(); 216 matrix_scan_quantum();
diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk
index 9268c4522..f8def7f67 100644
--- a/quantum/mcu_selection.mk
+++ b/quantum/mcu_selection.mk
@@ -136,10 +136,6 @@ ifneq ($(findstring STM32F042, $(MCU)),)
136 136
137 USE_FPU ?= no 137 USE_FPU ?= no
138 138
139 # Options to pass to dfu-util when flashing
140 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
141 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
142
143 # UF2 settings 139 # UF2 settings
144 UF2_FAMILY ?= STM32F0 140 UF2_FAMILY ?= STM32F0
145endif 141endif
@@ -172,10 +168,6 @@ ifneq ($(findstring STM32F072, $(MCU)),)
172 168
173 USE_FPU ?= no 169 USE_FPU ?= no
174 170
175 # Options to pass to dfu-util when flashing
176 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
177 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
178
179 # UF2 settings 171 # UF2 settings
180 UF2_FAMILY ?= STM32F0 172 UF2_FAMILY ?= STM32F0
181endif 173endif
@@ -208,10 +200,6 @@ ifneq ($(findstring STM32F103, $(MCU)),)
208 200
209 USE_FPU ?= no 201 USE_FPU ?= no
210 202
211 # Options to pass to dfu-util when flashing
212 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
213 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
214
215 # UF2 settings 203 # UF2 settings
216 UF2_FAMILY ?= STM32F1 204 UF2_FAMILY ?= STM32F1
217endif 205endif
@@ -244,10 +232,6 @@ ifneq ($(findstring STM32F303, $(MCU)),)
244 232
245 USE_FPU ?= yes 233 USE_FPU ?= yes
246 234
247 # Options to pass to dfu-util when flashing
248 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
249 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
250
251 # UF2 settings 235 # UF2 settings
252 UF2_FAMILY ?= STM32F3 236 UF2_FAMILY ?= STM32F3
253endif 237endif
@@ -280,10 +264,6 @@ ifneq ($(findstring STM32F401, $(MCU)),)
280 264
281 USE_FPU ?= yes 265 USE_FPU ?= yes
282 266
283 # Options to pass to dfu-util when flashing
284 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
285 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
286
287 # UF2 settings 267 # UF2 settings
288 UF2_FAMILY ?= STM32F4 268 UF2_FAMILY ?= STM32F4
289endif 269endif
@@ -321,10 +301,6 @@ ifneq ($(findstring STM32F411, $(MCU)),)
321 301
322 USE_FPU ?= yes 302 USE_FPU ?= yes
323 303
324 # Options to pass to dfu-util when flashing
325 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
326 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
327
328 # UF2 settings 304 # UF2 settings
329 UF2_FAMILY ?= STM32F4 305 UF2_FAMILY ?= STM32F4
330endif 306endif
@@ -357,10 +333,6 @@ ifneq ($(findstring STM32F446, $(MCU)),)
357 BOARD ?= GENERIC_STM32_F446XE 333 BOARD ?= GENERIC_STM32_F446XE
358 334
359 USE_FPU ?= yes 335 USE_FPU ?= yes
360
361 # Options to pass to dfu-util when flashing
362 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
363 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
364endif 336endif
365 337
366ifneq ($(findstring STM32G431, $(MCU)),) 338ifneq ($(findstring STM32G431, $(MCU)),)
@@ -391,10 +363,6 @@ ifneq ($(findstring STM32G431, $(MCU)),)
391 363
392 USE_FPU ?= yes 364 USE_FPU ?= yes
393 365
394 # Options to pass to dfu-util when flashing
395 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
396 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
397
398 # UF2 settings 366 # UF2 settings
399 UF2_FAMILY ?= STM32G4 367 UF2_FAMILY ?= STM32G4
400endif 368endif
@@ -427,10 +395,6 @@ ifneq ($(findstring STM32G474, $(MCU)),)
427 395
428 USE_FPU ?= yes 396 USE_FPU ?= yes
429 397
430 # Options to pass to dfu-util when flashing
431 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
432 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
433
434 # UF2 settings 398 # UF2 settings
435 UF2_FAMILY ?= STM32G4 399 UF2_FAMILY ?= STM32G4
436endif 400endif
@@ -465,10 +429,6 @@ ifneq (,$(filter $(MCU),STM32L433 STM32L443))
465 429
466 USE_FPU ?= yes 430 USE_FPU ?= yes
467 431
468 # Options to pass to dfu-util when flashing
469 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
470 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
471
472 # UF2 settings 432 # UF2 settings
473 UF2_FAMILY ?= STM32L4 433 UF2_FAMILY ?= STM32L4
474endif 434endif
diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c
index 167c0c03c..b9fee1ca5 100644
--- a/quantum/process_keycode/process_rgb.c
+++ b/quantum/process_keycode/process_rgb.c
@@ -14,7 +14,6 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 15 */
16#include "process_rgb.h" 16#include "process_rgb.h"
17#include "rgb.h"
18 17
19typedef void (*rgb_func_pointer)(void); 18typedef void (*rgb_func_pointer)(void);
20 19
diff --git a/quantum/quantum.h b/quantum/quantum.h
index e4a7c5723..66ba96fde 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -176,6 +176,10 @@ extern layer_state_t layer_state;
176# include "oled_driver.h" 176# include "oled_driver.h"
177#endif 177#endif
178 178
179#ifdef ST7565_ENABLE
180# include "st7565.h"
181#endif
182
179#ifdef DIP_SWITCH_ENABLE 183#ifdef DIP_SWITCH_ENABLE
180# include "dip_switch.h" 184# include "dip_switch.h"
181#endif 185#endif
diff --git a/quantum/rgb_matrix_animations/alpha_mods_anim.h b/quantum/rgb_matrix/animations/alpha_mods_anim.h
index 426d88ef3..426d88ef3 100644
--- a/quantum/rgb_matrix_animations/alpha_mods_anim.h
+++ b/quantum/rgb_matrix/animations/alpha_mods_anim.h
diff --git a/quantum/rgb_matrix_animations/breathing_anim.h b/quantum/rgb_matrix/animations/breathing_anim.h
index 340bd93e5..340bd93e5 100644
--- a/quantum/rgb_matrix_animations/breathing_anim.h
+++ b/quantum/rgb_matrix/animations/breathing_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_pinwheel_sat_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
index 3df3cfda7..3df3cfda7 100644
--- a/quantum/rgb_matrix_animations/colorband_pinwheel_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_pinwheel_val_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
index 7d80074fd..7d80074fd 100644
--- a/quantum/rgb_matrix_animations/colorband_pinwheel_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_sat_anim.h b/quantum/rgb_matrix/animations/colorband_sat_anim.h
index 35b830af6..35b830af6 100644
--- a/quantum/rgb_matrix_animations/colorband_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_sat_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_spiral_sat_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
index 048157aa1..048157aa1 100644
--- a/quantum/rgb_matrix_animations/colorband_spiral_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_spiral_val_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
index bff2da161..bff2da161 100644
--- a/quantum/rgb_matrix_animations/colorband_spiral_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_val_anim.h b/quantum/rgb_matrix/animations/colorband_val_anim.h
index f1aaf1d06..f1aaf1d06 100644
--- a/quantum/rgb_matrix_animations/colorband_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_val_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_all_anim.h b/quantum/rgb_matrix/animations/cycle_all_anim.h
index faf8598a3..faf8598a3 100644
--- a/quantum/rgb_matrix_animations/cycle_all_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_all_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_left_right_anim.h b/quantum/rgb_matrix/animations/cycle_left_right_anim.h
index cf911eb93..cf911eb93 100644
--- a/quantum/rgb_matrix_animations/cycle_left_right_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_left_right_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_out_in_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_anim.h
index d66acd4b2..d66acd4b2 100644
--- a/quantum/rgb_matrix_animations/cycle_out_in_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_out_in_anim.h
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 fe8396140..fe8396140 100644
--- a/quantum/rgb_matrix_animations/cycle_out_in_dual_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_pinwheel_anim.h b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
index 779988709..779988709 100644
--- a/quantum/rgb_matrix_animations/cycle_pinwheel_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_spiral_anim.h b/quantum/rgb_matrix/animations/cycle_spiral_anim.h
index 80cfb0dbc..80cfb0dbc 100644
--- a/quantum/rgb_matrix_animations/cycle_spiral_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_spiral_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_up_down_anim.h b/quantum/rgb_matrix/animations/cycle_up_down_anim.h
index 5016f739d..5016f739d 100644
--- a/quantum/rgb_matrix_animations/cycle_up_down_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_up_down_anim.h
diff --git a/quantum/rgb_matrix_animations/digital_rain_anim.h b/quantum/rgb_matrix/animations/digital_rain_anim.h
index 1de45f8e8..1de45f8e8 100644
--- a/quantum/rgb_matrix_animations/digital_rain_anim.h
+++ b/quantum/rgb_matrix/animations/digital_rain_anim.h
diff --git a/quantum/rgb_matrix_animations/dual_beacon_anim.h b/quantum/rgb_matrix/animations/dual_beacon_anim.h
index ce9487168..ce9487168 100644
--- a/quantum/rgb_matrix_animations/dual_beacon_anim.h
+++ b/quantum/rgb_matrix/animations/dual_beacon_anim.h
diff --git a/quantum/rgb_matrix_animations/gradient_left_right_anim.h b/quantum/rgb_matrix/animations/gradient_left_right_anim.h
index 53dfd04e2..53dfd04e2 100644
--- a/quantum/rgb_matrix_animations/gradient_left_right_anim.h
+++ b/quantum/rgb_matrix/animations/gradient_left_right_anim.h
diff --git a/quantum/rgb_matrix_animations/gradient_up_down_anim.h b/quantum/rgb_matrix/animations/gradient_up_down_anim.h
index 7e0d2898c..7e0d2898c 100644
--- a/quantum/rgb_matrix_animations/gradient_up_down_anim.h
+++ b/quantum/rgb_matrix/animations/gradient_up_down_anim.h
diff --git a/quantum/rgb_matrix_animations/hue_breathing_anim.h b/quantum/rgb_matrix/animations/hue_breathing_anim.h
index 54dea958a..54dea958a 100644
--- a/quantum/rgb_matrix_animations/hue_breathing_anim.h
+++ b/quantum/rgb_matrix/animations/hue_breathing_anim.h
diff --git a/quantum/rgb_matrix_animations/hue_pendulum_anim.h b/quantum/rgb_matrix/animations/hue_pendulum_anim.h
index 2d8d36174..2d8d36174 100644
--- a/quantum/rgb_matrix_animations/hue_pendulum_anim.h
+++ b/quantum/rgb_matrix/animations/hue_pendulum_anim.h
diff --git a/quantum/rgb_matrix_animations/hue_wave_anim.h b/quantum/rgb_matrix/animations/hue_wave_anim.h
index fd9026fc9..fd9026fc9 100644
--- a/quantum/rgb_matrix_animations/hue_wave_anim.h
+++ b/quantum/rgb_matrix/animations/hue_wave_anim.h
diff --git a/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
index 9493b3850..a17e954b1 100644
--- a/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h
+++ b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
@@ -4,7 +4,7 @@ RGB_MATRIX_EFFECT(JELLYBEAN_RAINDROPS)
4 4
5static void jellybean_raindrops_set_color(int i, effect_params_t* params) { 5static void jellybean_raindrops_set_color(int i, effect_params_t* params) {
6 if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) return; 6 if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) return;
7 HSV hsv = {rand() & 0xFF, rand() & 0xFF, rgb_matrix_config.hsv.v}; 7 HSV hsv = {rand() & 0xFF, qadd8(rand() & 0x7F, 0x80), rgb_matrix_config.hsv.v};
8 RGB rgb = rgb_matrix_hsv_to_rgb(hsv); 8 RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
9 rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); 9 rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
10} 10}
diff --git a/quantum/rgb_matrix_animations/rainbow_beacon_anim.h b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
index 977261182..977261182 100644
--- a/quantum/rgb_matrix_animations/rainbow_beacon_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
diff --git a/quantum/rgb_matrix_animations/rainbow_moving_chevron_anim.h b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
index e51e7b251..e51e7b251 100644
--- a/quantum/rgb_matrix_animations/rainbow_moving_chevron_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
diff --git a/quantum/rgb_matrix_animations/rainbow_pinwheels_anim.h b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
index 1cd4ed2ac..1cd4ed2ac 100644
--- a/quantum/rgb_matrix_animations/rainbow_pinwheels_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
diff --git a/quantum/rgb_matrix_animations/raindrops_anim.h b/quantum/rgb_matrix/animations/raindrops_anim.h
index 38359cdca..38359cdca 100644
--- a/quantum/rgb_matrix_animations/raindrops_anim.h
+++ b/quantum/rgb_matrix/animations/raindrops_anim.h
diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
new file mode 100644
index 000000000..302ad79c0
--- /dev/null
+++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
@@ -0,0 +1,37 @@
1// Add your new core rgb matrix effect here, order determines enum order
2#include "solid_color_anim.h"
3#include "alpha_mods_anim.h"
4#include "gradient_up_down_anim.h"
5#include "gradient_left_right_anim.h"
6#include "breathing_anim.h"
7#include "colorband_sat_anim.h"
8#include "colorband_val_anim.h"
9#include "colorband_pinwheel_sat_anim.h"
10#include "colorband_pinwheel_val_anim.h"
11#include "colorband_spiral_sat_anim.h"
12#include "colorband_spiral_val_anim.h"
13#include "cycle_all_anim.h"
14#include "cycle_left_right_anim.h"
15#include "cycle_up_down_anim.h"
16#include "rainbow_moving_chevron_anim.h"
17#include "cycle_out_in_anim.h"
18#include "cycle_out_in_dual_anim.h"
19#include "cycle_pinwheel_anim.h"
20#include "cycle_spiral_anim.h"
21#include "dual_beacon_anim.h"
22#include "rainbow_beacon_anim.h"
23#include "rainbow_pinwheels_anim.h"
24#include "raindrops_anim.h"
25#include "jellybean_raindrops_anim.h"
26#include "hue_breathing_anim.h"
27#include "hue_pendulum_anim.h"
28#include "hue_wave_anim.h"
29#include "typing_heatmap_anim.h"
30#include "digital_rain_anim.h"
31#include "solid_reactive_simple_anim.h"
32#include "solid_reactive_anim.h"
33#include "solid_reactive_wide.h"
34#include "solid_reactive_cross.h"
35#include "solid_reactive_nexus.h"
36#include "splash_anim.h"
37#include "solid_splash_anim.h"
diff --git a/quantum/rgb_matrix_runners/effect_runner_dx_dy.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
index 4867609c8..4867609c8 100644
--- a/quantum/rgb_matrix_runners/effect_runner_dx_dy.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
index 9545b418d..9545b418d 100644
--- a/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_i.h
index 1881cd6c6..1881cd6c6 100644
--- a/quantum/rgb_matrix_runners/effect_runner_i.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_i.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_reactive.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
index 75b7c0df4..75b7c0df4 100644
--- a/quantum/rgb_matrix_runners/effect_runner_reactive.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
index 2e46ffb35..2e46ffb35 100644
--- a/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
index 02351de51..02351de51 100644
--- a/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
diff --git a/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc b/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc
new file mode 100644
index 000000000..c09022bb0
--- /dev/null
+++ b/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc
@@ -0,0 +1,6 @@
1#include "effect_runner_dx_dy_dist.h"
2#include "effect_runner_dx_dy.h"
3#include "effect_runner_i.h"
4#include "effect_runner_sin_cos_i.h"
5#include "effect_runner_reactive.h"
6#include "effect_runner_reactive_splash.h"
diff --git a/quantum/rgb_matrix_animations/solid_color_anim.h b/quantum/rgb_matrix/animations/solid_color_anim.h
index 79d63cf13..79d63cf13 100644
--- a/quantum/rgb_matrix_animations/solid_color_anim.h
+++ b/quantum/rgb_matrix/animations/solid_color_anim.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_anim.h b/quantum/rgb_matrix/animations/solid_reactive_anim.h
index d45bb961b..d45bb961b 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_anim.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_anim.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_cross.h b/quantum/rgb_matrix/animations/solid_reactive_cross.h
index f76c68e8c..f76c68e8c 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_cross.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_cross.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_nexus.h b/quantum/rgb_matrix/animations/solid_reactive_nexus.h
index 17f94e3c1..17f94e3c1 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_nexus.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_nexus.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_simple_anim.h b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
index 12eb248cc..12eb248cc 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_simple_anim.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_wide.h b/quantum/rgb_matrix/animations/solid_reactive_wide.h
index 1cc4dca72..1cc4dca72 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_wide.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_wide.h
diff --git a/quantum/rgb_matrix_animations/solid_splash_anim.h b/quantum/rgb_matrix/animations/solid_splash_anim.h
index 99efb4996..99efb4996 100644
--- a/quantum/rgb_matrix_animations/solid_splash_anim.h
+++ b/quantum/rgb_matrix/animations/solid_splash_anim.h
diff --git a/quantum/rgb_matrix_animations/splash_anim.h b/quantum/rgb_matrix/animations/splash_anim.h
index 1415bcc0f..1415bcc0f 100644
--- a/quantum/rgb_matrix_animations/splash_anim.h
+++ b/quantum/rgb_matrix/animations/splash_anim.h
diff --git a/quantum/rgb_matrix_animations/typing_heatmap_anim.h b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
index e7dda11a2..e7dda11a2 100644
--- a/quantum/rgb_matrix_animations/typing_heatmap_anim.h
+++ b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c
index ab8dbd849..789cd2860 100644
--- a/quantum/rgb_matrix.c
+++ b/quantum/rgb_matrix/rgb_matrix.c
@@ -31,22 +31,25 @@ const led_point_t k_rgb_matrix_center = {112, 32};
31const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; 31const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER;
32#endif 32#endif
33 33
34// clang-format off
35#ifndef RGB_MATRIX_IMMEDIATE_EEPROM
36# define rgb_eeconfig_update(v) rgb_update_eeprom |= v
37#else
38# define rgb_eeconfig_update(v) if (v) eeconfig_update_rgb_matrix()
39#endif
40// clang-format on
41
34__attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } 42__attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); }
35 43
36// Generic effect runners 44// Generic effect runners
37#include "rgb_matrix_runners/effect_runner_dx_dy_dist.h" 45#include "rgb_matrix_runners.inc"
38#include "rgb_matrix_runners/effect_runner_dx_dy.h"
39#include "rgb_matrix_runners/effect_runner_i.h"
40#include "rgb_matrix_runners/effect_runner_sin_cos_i.h"
41#include "rgb_matrix_runners/effect_runner_reactive.h"
42#include "rgb_matrix_runners/effect_runner_reactive_splash.h"
43 46
44// ------------------------------------------ 47// ------------------------------------------
45// -----Begin rgb effect includes macros----- 48// -----Begin rgb effect includes macros-----
46#define RGB_MATRIX_EFFECT(name) 49#define RGB_MATRIX_EFFECT(name)
47#define RGB_MATRIX_CUSTOM_EFFECT_IMPLS 50#define RGB_MATRIX_CUSTOM_EFFECT_IMPLS
48 51
49#include "rgb_matrix_animations/rgb_matrix_effects.inc" 52#include "rgb_matrix_effects.inc"
50#ifdef RGB_MATRIX_CUSTOM_KB 53#ifdef RGB_MATRIX_CUSTOM_KB
51# include "rgb_matrix_kb.inc" 54# include "rgb_matrix_kb.inc"
52#endif 55#endif
@@ -67,10 +70,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv
67# define RGB_DISABLE_TIMEOUT 0 70# define RGB_DISABLE_TIMEOUT 0
68#endif 71#endif
69 72
70#if RGB_DISABLE_WHEN_USB_SUSPENDED != 1
71# undef RGB_DISABLE_WHEN_USB_SUSPENDED
72#endif
73
74#if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX 73#if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
75# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS 74# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS
76# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX 75# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
@@ -129,6 +128,7 @@ last_hit_t g_last_hit_tracker;
129 128
130// internals 129// internals
131static bool suspend_state = false; 130static bool suspend_state = false;
131static bool rgb_update_eeprom = false;
132static uint8_t rgb_last_enable = UINT8_MAX; 132static uint8_t rgb_last_enable = UINT8_MAX;
133static uint8_t rgb_last_effect = UINT8_MAX; 133static uint8_t rgb_last_effect = UINT8_MAX;
134static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; 134static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false};
@@ -315,6 +315,8 @@ static void rgb_task_timers(void) {
315 315
316static void rgb_task_sync(void) { 316static void rgb_task_sync(void) {
317 // next task 317 // next task
318 if (rgb_update_eeprom) eeconfig_update_rgb_matrix();
319 rgb_update_eeprom = false;
318 if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING; 320 if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING;
319} 321}
320 322
@@ -353,7 +355,7 @@ static void rgb_task_render(uint8_t effect) {
353 case RGB_MATRIX_##name: \ 355 case RGB_MATRIX_##name: \
354 rendering = name(&rgb_effect_params); \ 356 rendering = name(&rgb_effect_params); \
355 break; 357 break;
356#include "rgb_matrix_animations/rgb_matrix_effects.inc" 358#include "rgb_matrix_effects.inc"
357#undef RGB_MATRIX_EFFECT 359#undef RGB_MATRIX_EFFECT
358 360
359#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) 361#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
@@ -511,9 +513,7 @@ bool rgb_matrix_get_suspend_state(void) { return suspend_state; }
511void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) { 513void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
512 rgb_matrix_config.enable ^= 1; 514 rgb_matrix_config.enable ^= 1;
513 rgb_task_state = STARTING; 515 rgb_task_state = STARTING;
514 if (write_to_eeprom) { 516 rgb_eeconfig_update(write_to_eeprom);
515 eeconfig_update_rgb_matrix();
516 }
517 dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable); 517 dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable);
518} 518}
519void rgb_matrix_toggle_noeeprom(void) { rgb_matrix_toggle_eeprom_helper(false); } 519void rgb_matrix_toggle_noeeprom(void) { rgb_matrix_toggle_eeprom_helper(false); }
@@ -521,7 +521,7 @@ void rgb_matrix_toggle(void) { rgb_matrix_toggle_eeprom_helper(true); }
521 521
522void rgb_matrix_enable(void) { 522void rgb_matrix_enable(void) {
523 rgb_matrix_enable_noeeprom(); 523 rgb_matrix_enable_noeeprom();
524 eeconfig_update_rgb_matrix(); 524 rgb_eeconfig_update(true);
525} 525}
526 526
527void rgb_matrix_enable_noeeprom(void) { 527void rgb_matrix_enable_noeeprom(void) {
@@ -531,7 +531,7 @@ void rgb_matrix_enable_noeeprom(void) {
531 531
532void rgb_matrix_disable(void) { 532void rgb_matrix_disable(void) {
533 rgb_matrix_disable_noeeprom(); 533 rgb_matrix_disable_noeeprom();
534 eeconfig_update_rgb_matrix(); 534 rgb_eeconfig_update(true);
535} 535}
536 536
537void rgb_matrix_disable_noeeprom(void) { 537void rgb_matrix_disable_noeeprom(void) {
@@ -553,9 +553,7 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
553 rgb_matrix_config.mode = mode; 553 rgb_matrix_config.mode = mode;
554 } 554 }
555 rgb_task_state = STARTING; 555 rgb_task_state = STARTING;
556 if (write_to_eeprom) { 556 rgb_eeconfig_update(write_to_eeprom);
557 eeconfig_update_rgb_matrix();
558 }
559 dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode); 557 dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode);
560} 558}
561void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); } 559void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); }
@@ -584,9 +582,7 @@ void rgb_matrix_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, boo
584 rgb_matrix_config.hsv.h = hue; 582 rgb_matrix_config.hsv.h = hue;
585 rgb_matrix_config.hsv.s = sat; 583 rgb_matrix_config.hsv.s = sat;
586 rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val; 584 rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val;
587 if (write_to_eeprom) { 585 rgb_eeconfig_update(write_to_eeprom);
588 eeconfig_update_rgb_matrix();
589 }
590 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); 586 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);
591} 587}
592void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); } 588void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); }
@@ -623,9 +619,7 @@ void rgb_matrix_decrease_val(void) { rgb_matrix_decrease_val_helper(true); }
623 619
624void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { 620void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
625 rgb_matrix_config.speed = speed; 621 rgb_matrix_config.speed = speed;
626 if (write_to_eeprom) { 622 rgb_eeconfig_update(write_to_eeprom);
627 eeconfig_update_rgb_matrix();
628 }
629 dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed); 623 dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed);
630} 624}
631void rgb_matrix_set_speed_noeeprom(uint8_t speed) { rgb_matrix_set_speed_eeprom_helper(speed, false); } 625void rgb_matrix_set_speed_noeeprom(uint8_t speed) { rgb_matrix_set_speed_eeprom_helper(speed, false); }
diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h
index a615b8422..28f07c84d 100644
--- a/quantum/rgb_matrix.h
+++ b/quantum/rgb_matrix/rgb_matrix.h
@@ -33,6 +33,8 @@
33# include "is31fl3737.h" 33# include "is31fl3737.h"
34#elif defined(IS31FL3741) 34#elif defined(IS31FL3741)
35# include "is31fl3741.h" 35# include "is31fl3741.h"
36#elif defined(AW20216)
37# include "aw20216.h"
36#elif defined(WS2812) 38#elif defined(WS2812)
37# include "ws2812.h" 39# include "ws2812.h"
38#endif 40#endif
@@ -70,7 +72,7 @@ enum rgb_matrix_effects {
70// -------------------------------------- 72// --------------------------------------
71// -----Begin rgb effect enum macros----- 73// -----Begin rgb effect enum macros-----
72#define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_##name, 74#define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_##name,
73#include "rgb_matrix_animations/rgb_matrix_effects.inc" 75#include "rgb_matrix_effects.inc"
74#undef RGB_MATRIX_EFFECT 76#undef RGB_MATRIX_EFFECT
75 77
76#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) 78#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
diff --git a/quantum/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c
index 896fa6d0e..6a11d4791 100644
--- a/quantum/rgb_matrix_drivers.c
+++ b/quantum/rgb_matrix/rgb_matrix_drivers.c
@@ -171,6 +171,22 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
171}; 171};
172# endif 172# endif
173 173
174#elif defined(AW20216)
175# include "spi_master.h"
176static void init(void) {
177 spi_init();
178 AW20216_init();
179}
180
181static void flush(void) { AW20216_update_pwm_buffers(); }
182
183const rgb_matrix_driver_t rgb_matrix_driver = {
184 .init = init,
185 .flush = flush,
186 .set_color = AW20216_set_color,
187 .set_color_all = AW20216_set_color_all,
188};
189
174#elif defined(WS2812) 190#elif defined(WS2812)
175# if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_CUSTOM_DRIVER) 191# if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_CUSTOM_DRIVER)
176# pragma message "Cannot use RGBLIGHT and RGB Matrix using WS2812 at the same time." 192# pragma message "Cannot use RGBLIGHT and RGB Matrix using WS2812 at the same time."
diff --git a/quantum/rgb_matrix_types.h b/quantum/rgb_matrix/rgb_matrix_types.h
index df575d657..df575d657 100644
--- a/quantum/rgb_matrix_types.h
+++ b/quantum/rgb_matrix/rgb_matrix_types.h
diff --git a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc b/quantum/rgb_matrix_animations/rgb_matrix_effects.inc
deleted file mode 100644
index 053d44150..000000000
--- a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc
+++ /dev/null
@@ -1,37 +0,0 @@
1// Add your new core rgb matrix effect here, order determins enum order, requires "rgb_matrix_animations/ directory
2#include "rgb_matrix_animations/solid_color_anim.h"
3#include "rgb_matrix_animations/alpha_mods_anim.h"
4#include "rgb_matrix_animations/gradient_up_down_anim.h"
5#include "rgb_matrix_animations/gradient_left_right_anim.h"
6#include "rgb_matrix_animations/breathing_anim.h"
7#include "rgb_matrix_animations/colorband_sat_anim.h"
8#include "rgb_matrix_animations/colorband_val_anim.h"
9#include "rgb_matrix_animations/colorband_pinwheel_sat_anim.h"
10#include "rgb_matrix_animations/colorband_pinwheel_val_anim.h"
11#include "rgb_matrix_animations/colorband_spiral_sat_anim.h"
12#include "rgb_matrix_animations/colorband_spiral_val_anim.h"
13#include "rgb_matrix_animations/cycle_all_anim.h"
14#include "rgb_matrix_animations/cycle_left_right_anim.h"
15#include "rgb_matrix_animations/cycle_up_down_anim.h"
16#include "rgb_matrix_animations/rainbow_moving_chevron_anim.h"
17#include "rgb_matrix_animations/cycle_out_in_anim.h"
18#include "rgb_matrix_animations/cycle_out_in_dual_anim.h"
19#include "rgb_matrix_animations/cycle_pinwheel_anim.h"
20#include "rgb_matrix_animations/cycle_spiral_anim.h"
21#include "rgb_matrix_animations/dual_beacon_anim.h"
22#include "rgb_matrix_animations/rainbow_beacon_anim.h"
23#include "rgb_matrix_animations/rainbow_pinwheels_anim.h"
24#include "rgb_matrix_animations/raindrops_anim.h"
25#include "rgb_matrix_animations/jellybean_raindrops_anim.h"
26#include "rgb_matrix_animations/hue_breathing_anim.h"
27#include "rgb_matrix_animations/hue_pendulum_anim.h"
28#include "rgb_matrix_animations/hue_wave_anim.h"
29#include "rgb_matrix_animations/typing_heatmap_anim.h"
30#include "rgb_matrix_animations/digital_rain_anim.h"
31#include "rgb_matrix_animations/solid_reactive_simple_anim.h"
32#include "rgb_matrix_animations/solid_reactive_anim.h"
33#include "rgb_matrix_animations/solid_reactive_wide.h"
34#include "rgb_matrix_animations/solid_reactive_cross.h"
35#include "rgb_matrix_animations/solid_reactive_nexus.h"
36#include "rgb_matrix_animations/splash_anim.h"
37#include "rgb_matrix_animations/solid_splash_anim.h"
diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c
index f77483ad8..6363f8ff3 100644
--- a/quantum/serial_link/system/serial_link.c
+++ b/quantum/serial_link/system/serial_link.c
@@ -29,10 +29,13 @@ SOFTWARE.
29#include "serial_link/protocol/transport.h" 29#include "serial_link/protocol/transport.h"
30#include "serial_link/protocol/frame_router.h" 30#include "serial_link/protocol/frame_router.h"
31#include "matrix.h" 31#include "matrix.h"
32#include "sync_timer.h"
32#include <stdbool.h> 33#include <stdbool.h>
33#include "print.h" 34#include "print.h"
34#include "config.h" 35#include "config.h"
35 36
37#define SYNC_TIMER_OFFSET 2
38
36static event_source_t new_data_event; 39static event_source_t new_data_event;
37static bool serial_link_connected; 40static bool serial_link_connected;
38static bool is_master = false; 41static bool is_master = false;
@@ -159,10 +162,16 @@ static matrix_object_t last_matrix = {};
159 162
160SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t); 163SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t);
161MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool); 164MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool);
165#ifndef DISABLE_SYNC_TIMER
166MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t);
167#endif
162 168
163static remote_object_t* remote_objects[] = { 169static remote_object_t* remote_objects[] = {
164 REMOTE_OBJECT(serial_link_connected), 170 REMOTE_OBJECT(serial_link_connected),
165 REMOTE_OBJECT(keyboard_matrix), 171 REMOTE_OBJECT(keyboard_matrix),
172#ifndef DISABLE_SYNC_TIMER
173 REMOTE_OBJECT(sync_timer),
174#endif
166}; 175};
167 176
168void init_serial_link(void) { 177void init_serial_link(void) {
@@ -200,14 +209,27 @@ void serial_link_update(void) {
200 m->rows[i] = matrix.rows[i]; 209 m->rows[i] = matrix.rows[i];
201 } 210 }
202 end_write_keyboard_matrix(); 211 end_write_keyboard_matrix();
212
203 *begin_write_serial_link_connected() = true; 213 *begin_write_serial_link_connected() = true;
204 end_write_serial_link_connected(); 214 end_write_serial_link_connected();
215
216#ifndef DISABLE_SYNC_TIMER
217 *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET;
218 end_write_sync_timer();
219#endif
205 } 220 }
206 221
207 matrix_object_t* m = read_keyboard_matrix(0); 222 matrix_object_t* m = read_keyboard_matrix(0);
208 if (m) { 223 if (m) {
209 matrix_set_remote(m->rows, 0); 224 matrix_set_remote(m->rows, 0);
210 } 225 }
226
227#ifndef DISABLE_SYNC_TIMER
228 uint32_t* t = read_sync_timer();
229 if (t) {
230 sync_timer_update(*t);
231 }
232#endif
211} 233}
212 234
213void signal_data_written(void) { chEvtBroadcast(&new_data_event); } 235void signal_data_written(void) { chEvtBroadcast(&new_data_event); }
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
index 039e7d977..56d91b07f 100644
--- a/quantum/split_common/matrix.c
+++ b/quantum/split_common/matrix.c
@@ -16,23 +16,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17#include <stdint.h> 17#include <stdint.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <string.h>
19#include "util.h" 20#include "util.h"
20#include "matrix.h" 21#include "matrix.h"
21#include "debounce.h" 22#include "debounce.h"
22#include "quantum.h" 23#include "quantum.h"
23#include "split_util.h" 24#include "split_util.h"
24#include "config.h" 25#include "config.h"
25#include "transport.h" 26#include "transactions.h"
26 27
27#define ERROR_DISCONNECT_COUNT 5 28#ifndef ERROR_DISCONNECT_COUNT
29# define ERROR_DISCONNECT_COUNT 5
30#endif // ERROR_DISCONNECT_COUNT
28 31
29#define ROWS_PER_HAND (MATRIX_ROWS / 2) 32#define ROWS_PER_HAND (MATRIX_ROWS / 2)
30 33
31#ifdef DIRECT_PINS 34#ifdef DIRECT_PINS
32static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; 35static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
33#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) 36#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
37# ifdef MATRIX_ROW_PINS
34static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 38static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
39# endif // MATRIX_ROW_PINS
40# ifdef MATRIX_COL_PINS
35static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 41static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
42# endif // MATRIX_COL_PINS
36#endif 43#endif
37 44
38/* matrix state(1:on, 0:off) */ 45/* matrix state(1:on, 0:off) */
@@ -45,6 +52,9 @@ uint8_t thisHand, thatHand;
45// user-defined overridable functions 52// user-defined overridable functions
46__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); } 53__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }
47__attribute__((weak)) void matrix_slave_scan_user(void) {} 54__attribute__((weak)) void matrix_slave_scan_user(void) {}
55__attribute__((weak)) void matrix_init_pins(void);
56__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
57__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
48 58
49static inline void setPinOutput_writeLow(pin_t pin) { 59static inline void setPinOutput_writeLow(pin_t pin) {
50 ATOMIC_BLOCK_FORCEON { 60 ATOMIC_BLOCK_FORCEON {
@@ -61,7 +71,7 @@ static inline void setPinInputHigh_atomic(pin_t pin) {
61 71
62#ifdef DIRECT_PINS 72#ifdef DIRECT_PINS
63 73
64static void init_pins(void) { 74__attribute__((weak)) void matrix_init_pins(void) {
65 for (int row = 0; row < MATRIX_ROWS; row++) { 75 for (int row = 0; row < MATRIX_ROWS; row++) {
66 for (int col = 0; col < MATRIX_COLS; col++) { 76 for (int col = 0; col < MATRIX_COLS; col++) {
67 pin_t pin = direct_pins[row][col]; 77 pin_t pin = direct_pins[row][col];
@@ -72,7 +82,7 @@ static void init_pins(void) {
72 } 82 }
73} 83}
74 84
75static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 85__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
76 // Start with a clear matrix row 86 // Start with a clear matrix row
77 matrix_row_t current_row_value = 0; 87 matrix_row_t current_row_value = 0;
78 88
@@ -83,16 +93,13 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
83 } 93 }
84 } 94 }
85 95
86 // If the row has changed, store the row and return the changed flag. 96 // Update the matrix
87 if (current_matrix[current_row] != current_row_value) { 97 current_matrix[current_row] = current_row_value;
88 current_matrix[current_row] = current_row_value;
89 return true;
90 }
91 return false;
92} 98}
93 99
94#elif defined(DIODE_DIRECTION) 100#elif defined(DIODE_DIRECTION)
95# if (DIODE_DIRECTION == COL2ROW) 101# if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
102# if (DIODE_DIRECTION == COL2ROW)
96 103
97static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } 104static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); }
98 105
@@ -104,14 +111,14 @@ static void unselect_rows(void) {
104 } 111 }
105} 112}
106 113
107static void init_pins(void) { 114__attribute__((weak)) void matrix_init_pins(void) {
108 unselect_rows(); 115 unselect_rows();
109 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 116 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
110 setPinInputHigh_atomic(col_pins[x]); 117 setPinInputHigh_atomic(col_pins[x]);
111 } 118 }
112} 119}
113 120
114static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 121__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
115 // Start with a clear matrix row 122 // Start with a clear matrix row
116 matrix_row_t current_row_value = 0; 123 matrix_row_t current_row_value = 0;
117 124
@@ -132,15 +139,11 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
132 unselect_row(current_row); 139 unselect_row(current_row);
133 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH 140 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH
134 141
135 // If the row has changed, store the row and return the changed flag. 142 // Update the matrix
136 if (current_matrix[current_row] != current_row_value) { 143 current_matrix[current_row] = current_row_value;
137 current_matrix[current_row] = current_row_value;
138 return true;
139 }
140 return false;
141} 144}
142 145
143# elif (DIODE_DIRECTION == ROW2COL) 146# elif (DIODE_DIRECTION == ROW2COL)
144 147
145static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } 148static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); }
146 149
@@ -152,52 +155,39 @@ static void unselect_cols(void) {
152 } 155 }
153} 156}
154 157
155static void init_pins(void) { 158__attribute__((weak)) void matrix_init_pins(void) {
156 unselect_cols(); 159 unselect_cols();
157 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { 160 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
158 setPinInputHigh_atomic(row_pins[x]); 161 setPinInputHigh_atomic(row_pins[x]);
159 } 162 }
160} 163}
161 164
162static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 165__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
163 bool matrix_changed = false;
164
165 // Select col 166 // Select col
166 select_col(current_col); 167 select_col(current_col);
167 matrix_output_select_delay(); 168 matrix_output_select_delay();
168 169
169 // For each row... 170 // For each row...
170 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { 171 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {
171 // Store last value of row prior to reading
172 matrix_row_t last_row_value = current_matrix[row_index];
173 matrix_row_t current_row_value = last_row_value;
174
175 // Check row pin state 172 // Check row pin state
176 if (readPin(row_pins[row_index]) == 0) { 173 if (readPin(row_pins[row_index]) == 0) {
177 // Pin LO, set col bit 174 // Pin LO, set col bit
178 current_row_value |= (MATRIX_ROW_SHIFTER << current_col); 175 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
179 } else { 176 } else {
180 // Pin HI, clear col bit 177 // Pin HI, clear col bit
181 current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); 178 current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
182 }
183
184 // Determine if the matrix changed state
185 if ((last_row_value != current_row_value)) {
186 matrix_changed |= true;
187 current_matrix[row_index] = current_row_value;
188 } 179 }
189 } 180 }
190 181
191 // Unselect col 182 // Unselect col
192 unselect_col(current_col); 183 unselect_col(current_col);
193 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH 184 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH
194
195 return matrix_changed;
196} 185}
197 186
198# else 187# else
199# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! 188# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
200# endif 189# endif
190# endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
201#else 191#else
202# error DIODE_DIRECTION is not defined! 192# error DIODE_DIRECTION is not defined!
203#endif 193#endif
@@ -233,7 +223,7 @@ void matrix_init(void) {
233 thatHand = ROWS_PER_HAND - thisHand; 223 thatHand = ROWS_PER_HAND - thisHand;
234 224
235 // initialize key pins 225 // initialize key pins
236 init_pins(); 226 matrix_init_pins();
237 227
238 // initialize matrix state: all keys off 228 // initialize matrix state: all keys off
239 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 229 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
@@ -288,20 +278,23 @@ bool matrix_post_scan(void) {
288} 278}
289 279
290uint8_t matrix_scan(void) { 280uint8_t matrix_scan(void) {
291 bool local_changed = false; 281 matrix_row_t curr_matrix[MATRIX_ROWS] = {0};
292 282
293#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 283#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
294 // Set row, read cols 284 // Set row, read cols
295 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { 285 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
296 local_changed |= read_cols_on_row(raw_matrix, current_row); 286 matrix_read_cols_on_row(curr_matrix, current_row);
297 } 287 }
298#elif (DIODE_DIRECTION == ROW2COL) 288#elif (DIODE_DIRECTION == ROW2COL)
299 // Set col, read rows 289 // Set col, read rows
300 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 290 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
301 local_changed |= read_rows_on_col(raw_matrix, current_col); 291 matrix_read_rows_on_col(curr_matrix, current_col);
302 } 292 }
303#endif 293#endif
304 294
295 bool local_changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0;
296 if (local_changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix));
297
305 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed); 298 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed);
306 299
307 bool remote_changed = matrix_post_scan(); 300 bool remote_changed = matrix_post_scan();
diff --git a/quantum/split_common/post_config.h b/quantum/split_common/post_config.h
index 4ae1d5273..a4c0a1956 100644
--- a/quantum/split_common/post_config.h
+++ b/quantum/split_common/post_config.h
@@ -7,13 +7,4 @@
7# ifndef F_SCL 7# ifndef F_SCL
8# define F_SCL 100000UL // SCL frequency 8# define F_SCL 100000UL // SCL frequency
9# endif 9# endif
10
11#else // use serial
12// When using serial, the user must define RGBLIGHT_SPLIT explicitly
13// in config.h as needed.
14// see quantum/rgblight_post_config.h
15# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
16// When using serial and RGBLIGHT_SPLIT need separate transaction
17# define SERIAL_USE_MULTI_TRANSACTION
18# endif
19#endif 10#endif
diff --git a/quantum/split_common/transaction_id_define.h b/quantum/split_common/transaction_id_define.h
new file mode 100644
index 000000000..464c73478
--- /dev/null
+++ b/quantum/split_common/transaction_id_define.h
@@ -0,0 +1,94 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19enum serial_transaction_id {
20#ifdef USE_I2C
21 I2C_EXECUTE_CALLBACK,
22#endif // USE_I2C
23
24 GET_SLAVE_MATRIX_CHECKSUM,
25 GET_SLAVE_MATRIX_DATA,
26
27#ifdef SPLIT_TRANSPORT_MIRROR
28 PUT_MASTER_MATRIX,
29#endif // SPLIT_TRANSPORT_MIRROR
30
31#ifdef ENCODER_ENABLE
32 GET_ENCODERS_CHECKSUM,
33 GET_ENCODERS_DATA,
34#endif // ENCODER_ENABLE
35
36#ifndef DISABLE_SYNC_TIMER
37 PUT_SYNC_TIMER,
38#endif // DISABLE_SYNC_TIMER
39
40#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
41 PUT_LAYER_STATE,
42 PUT_DEFAULT_LAYER_STATE,
43#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
44
45#ifdef SPLIT_LED_STATE_ENABLE
46 PUT_LED_STATE,
47#endif // SPLIT_LED_STATE_ENABLE
48
49#ifdef SPLIT_MODS_ENABLE
50 PUT_MODS,
51#endif // SPLIT_MODS_ENABLE
52
53#ifdef BACKLIGHT_ENABLE
54 PUT_BACKLIGHT,
55#endif // BACKLIGHT_ENABLE
56
57#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
58 PUT_RGBLIGHT,
59#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
60
61#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
62 PUT_LED_MATRIX,
63#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
64
65#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
66 PUT_RGB_MATRIX,
67#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
68
69#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
70 PUT_WPM,
71#endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
72
73#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
74 PUT_RPC_INFO,
75 PUT_RPC_REQ_DATA,
76 EXECUTE_RPC,
77 GET_RPC_RESP_DATA,
78#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
79
80// keyboard-specific
81#ifdef SPLIT_TRANSACTION_IDS_KB
82 SPLIT_TRANSACTION_IDS_KB,
83#endif // SPLIT_TRANSACTION_IDS_KB
84
85// user/keymap-specific
86#ifdef SPLIT_TRANSACTION_IDS_USER
87 SPLIT_TRANSACTION_IDS_USER,
88#endif // SPLIT_TRANSACTION_IDS_USER
89
90 NUM_TOTAL_TRANSACTIONS
91};
92
93// Ensure we only use 5 bits for transaction
94_Static_assert(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded");
diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c
new file mode 100644
index 000000000..99a8623b3
--- /dev/null
+++ b/quantum/split_common/transactions.c
@@ -0,0 +1,670 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <string.h>
18#include <stddef.h>
19
20#include "debug.h"
21#include "matrix.h"
22#include "quantum.h"
23#include "transactions.h"
24#include "transport.h"
25#include "transaction_id_define.h"
26
27#define SYNC_TIMER_OFFSET 2
28
29#ifndef FORCED_SYNC_THROTTLE_MS
30# define FORCED_SYNC_THROTTLE_MS 100
31#endif // FORCED_SYNC_THROTTLE_MS
32
33#define sizeof_member(type, member) sizeof(((type *)NULL)->member)
34
35#define trans_initiator2target_initializer_cb(member, cb) \
36 { &dummy, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), 0, 0, cb }
37#define trans_initiator2target_initializer(member) trans_initiator2target_initializer_cb(member, NULL)
38
39#define trans_target2initiator_initializer_cb(member, cb) \
40 { &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb }
41#define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL)
42
43#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0)
44#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length)
45
46static uint8_t crc8(const void *data, size_t len) {
47 const uint8_t *p = (const uint8_t *)data;
48 uint8_t crc = 0xff;
49 size_t i, j;
50 for (i = 0; i < len; i++) {
51 crc ^= p[i];
52 for (j = 0; j < 8; j++) {
53 if ((crc & 0x80) != 0)
54 crc = (uint8_t)((crc << 1) ^ 0x31);
55 else
56 crc <<= 1;
57 }
58 }
59 return crc;
60}
61
62#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
63// Forward-declare the RPC callback handlers
64void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
65void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
66#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
67
68////////////////////////////////////////////////////
69// Helpers
70
71bool transaction_handler_master(bool okay, matrix_row_t master_matrix[], matrix_row_t slave_matrix[], const char *prefix, bool (*handler)(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])) {
72 if (okay) {
73 bool this_okay = true;
74 for (int iter = 1; iter <= 10; ++iter) {
75 if (!this_okay) {
76 for (int i = 0; i < iter * iter; ++i) {
77 wait_us(10);
78 }
79 }
80 ATOMIC_BLOCK_FORCEON { this_okay = handler(master_matrix, slave_matrix); };
81 if (this_okay) break;
82 }
83 okay &= this_okay;
84 if (!okay) {
85 dprintf("Failed to execute %s\n", prefix);
86 }
87 }
88 return okay;
89}
90
91#define TRANSACTION_HANDLER_MASTER(prefix) \
92 do { \
93 okay &= transaction_handler_master(okay, master_matrix, slave_matrix, #prefix, &prefix##_master); \
94 } while (0)
95
96#define TRANSACTION_HANDLER_SLAVE(prefix) \
97 do { \
98 ATOMIC_BLOCK_FORCEON { prefix##_slave(master_matrix, slave_matrix); }; \
99 } while (0)
100
101inline static bool read_if_checksum_mismatch(int8_t trans_id_checksum, int8_t trans_id_retrieve, uint32_t *last_update, void *destination, const void *equiv_shmem, size_t length) {
102 uint8_t curr_checksum;
103 bool okay = transport_read(trans_id_checksum, &curr_checksum, sizeof(curr_checksum));
104 if (okay && (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || curr_checksum != crc8(equiv_shmem, length))) {
105 okay &= transport_read(trans_id_retrieve, destination, length);
106 okay &= curr_checksum == crc8(equiv_shmem, length);
107 if (okay) {
108 *last_update = timer_read32();
109 }
110 } else {
111 memcpy(destination, equiv_shmem, length);
112 }
113 return okay;
114}
115
116inline static bool send_if_condition(int8_t trans_id, uint32_t *last_update, bool condition, void *source, size_t length) {
117 bool okay = true;
118 if (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || condition) {
119 okay &= transport_write(trans_id, source, length);
120 if (okay) {
121 *last_update = timer_read32();
122 }
123 }
124 return okay;
125}
126
127inline static bool send_if_data_mismatch(int8_t trans_id, uint32_t *last_update, void *source, const void *equiv_shmem, size_t length) {
128 // Just run a memcmp to compare the source and equivalent shmem location
129 return send_if_condition(trans_id, last_update, (memcmp(source, equiv_shmem, length) != 0), source, length);
130}
131
132////////////////////////////////////////////////////
133// Slave matrix
134
135static bool slave_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
136 static uint32_t last_update = 0;
137 static matrix_row_t last_matrix[(MATRIX_ROWS) / 2] = {0}; // last successfully-read matrix, so we can replicate if there are checksum errors
138 matrix_row_t temp_matrix[(MATRIX_ROWS) / 2]; // holding area while we test whether or not checksum is correct
139
140 bool okay = read_if_checksum_mismatch(GET_SLAVE_MATRIX_CHECKSUM, GET_SLAVE_MATRIX_DATA, &last_update, temp_matrix, split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix));
141 if (okay) {
142 // Checksum matches the received data, save as the last matrix state
143 memcpy(last_matrix, temp_matrix, sizeof(temp_matrix));
144 }
145 // Copy out the last-known-good matrix state to the slave matrix
146 memcpy(slave_matrix, last_matrix, sizeof(last_matrix));
147 return okay;
148}
149
150static void slave_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
151 memcpy(split_shmem->smatrix.matrix, slave_matrix, sizeof(split_shmem->smatrix.matrix));
152 split_shmem->smatrix.checksum = crc8(split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix));
153}
154
155// clang-format off
156#define TRANSACTIONS_SLAVE_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(slave_matrix_handlers)
157#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(slave_matrix_handlers)
158#define TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS \
159 [GET_SLAVE_MATRIX_CHECKSUM] = trans_target2initiator_initializer(smatrix.checksum), \
160 [GET_SLAVE_MATRIX_DATA] = trans_target2initiator_initializer(smatrix.matrix),
161// clang-format on
162
163////////////////////////////////////////////////////
164// Master matrix
165
166#ifdef SPLIT_TRANSPORT_MIRROR
167
168static bool master_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
169 static uint32_t last_update = 0;
170 return send_if_data_mismatch(PUT_MASTER_MATRIX, &last_update, master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix));
171}
172
173static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
174 // Always copy to the master matrix
175 memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix));
176}
177
178# define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix_handlers)
179# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix_handlers)
180# define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix),
181
182#else // SPLIT_TRANSPORT_MIRROR
183
184# define TRANSACTIONS_MASTER_MATRIX_MASTER()
185# define TRANSACTIONS_MASTER_MATRIX_SLAVE()
186# define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS
187
188#endif // SPLIT_TRANSPORT_MIRROR
189
190////////////////////////////////////////////////////
191// Encoders
192
193#ifdef ENCODER_ENABLE
194
195static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
196 static uint32_t last_update = 0;
197 uint8_t temp_state[NUMBER_OF_ENCODERS];
198
199 bool okay = read_if_checksum_mismatch(GET_ENCODERS_CHECKSUM, GET_ENCODERS_DATA, &last_update, temp_state, split_shmem->encoders.state, sizeof(temp_state));
200 if (okay) encoder_update_raw(temp_state);
201 return okay;
202}
203
204static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
205 uint8_t encoder_state[NUMBER_OF_ENCODERS];
206 encoder_state_raw(encoder_state);
207 // Always prepare the encoder state for read.
208 memcpy(split_shmem->encoders.state, encoder_state, sizeof(encoder_state));
209 // Now update the checksum given that the encoders has been written to
210 split_shmem->encoders.checksum = crc8(encoder_state, sizeof(encoder_state));
211}
212
213// clang-format off
214# define TRANSACTIONS_ENCODERS_MASTER() TRANSACTION_HANDLER_MASTER(encoder_handlers)
215# define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder_handlers)
216# define TRANSACTIONS_ENCODERS_REGISTRATIONS \
217 [GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \
218 [GET_ENCODERS_DATA] = trans_target2initiator_initializer(encoders.state),
219// clang-format on
220
221#else // ENCODER_ENABLE
222
223# define TRANSACTIONS_ENCODERS_MASTER()
224# define TRANSACTIONS_ENCODERS_SLAVE()
225# define TRANSACTIONS_ENCODERS_REGISTRATIONS
226
227#endif // ENCODER_ENABLE
228
229////////////////////////////////////////////////////
230// Sync timer
231
232#ifndef DISABLE_SYNC_TIMER
233
234static bool sync_timer_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
235 static uint32_t last_update = 0;
236
237 bool okay = true;
238 if (timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS) {
239 uint32_t sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
240 okay &= transport_write(PUT_SYNC_TIMER, &sync_timer, sizeof(sync_timer));
241 if (okay) {
242 last_update = timer_read32();
243 }
244 }
245 return okay;
246}
247
248static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
249 static uint32_t last_sync_timer = 0;
250 if (last_sync_timer != split_shmem->sync_timer) {
251 last_sync_timer = split_shmem->sync_timer;
252 sync_timer_update(last_sync_timer);
253 }
254}
255
256# define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer_handlers)
257# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer_handlers)
258# define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer),
259
260#else // DISABLE_SYNC_TIMER
261
262# define TRANSACTIONS_SYNC_TIMER_MASTER()
263# define TRANSACTIONS_SYNC_TIMER_SLAVE()
264# define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS
265
266#endif // DISABLE_SYNC_TIMER
267
268////////////////////////////////////////////////////
269// Layer state
270
271#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
272
273static bool layer_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
274 static uint32_t last_layer_state_update = 0;
275 static uint32_t last_default_layer_state_update = 0;
276
277 bool okay = send_if_condition(PUT_LAYER_STATE, &last_layer_state_update, (layer_state != split_shmem->layers.layer_state), &layer_state, sizeof(layer_state));
278 if (okay) {
279 okay &= send_if_condition(PUT_DEFAULT_LAYER_STATE, &last_default_layer_state_update, (default_layer_state != split_shmem->layers.default_layer_state), &default_layer_state, sizeof(default_layer_state));
280 }
281 return okay;
282}
283
284static void layer_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
285 layer_state = split_shmem->layers.layer_state;
286 default_layer_state = split_shmem->layers.default_layer_state;
287}
288
289// clang-format off
290# define TRANSACTIONS_LAYER_STATE_MASTER() TRANSACTION_HANDLER_MASTER(layer_state_handlers)
291# define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(layer_state_handlers)
292# define TRANSACTIONS_LAYER_STATE_REGISTRATIONS \
293 [PUT_LAYER_STATE] = trans_initiator2target_initializer(layers.layer_state), \
294 [PUT_DEFAULT_LAYER_STATE] = trans_initiator2target_initializer(layers.default_layer_state),
295// clang-format on
296
297#else // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
298
299# define TRANSACTIONS_LAYER_STATE_MASTER()
300# define TRANSACTIONS_LAYER_STATE_SLAVE()
301# define TRANSACTIONS_LAYER_STATE_REGISTRATIONS
302
303#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
304
305////////////////////////////////////////////////////
306// LED state
307
308#ifdef SPLIT_LED_STATE_ENABLE
309
310static bool led_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
311 static uint32_t last_update = 0;
312 uint8_t led_state = host_keyboard_leds();
313 return send_if_data_mismatch(PUT_LED_STATE, &last_update, &led_state, &split_shmem->led_state, sizeof(led_state));
314}
315
316static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
317 void set_split_host_keyboard_leds(uint8_t led_state);
318 set_split_host_keyboard_leds(split_shmem->led_state);
319}
320
321# define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state_handlers)
322# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state_handlers)
323# define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state),
324
325#else // SPLIT_LED_STATE_ENABLE
326
327# define TRANSACTIONS_LED_STATE_MASTER()
328# define TRANSACTIONS_LED_STATE_SLAVE()
329# define TRANSACTIONS_LED_STATE_REGISTRATIONS
330
331#endif // SPLIT_LED_STATE_ENABLE
332
333////////////////////////////////////////////////////
334// Mods
335
336#ifdef SPLIT_MODS_ENABLE
337
338static bool mods_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
339 static uint32_t last_update = 0;
340 bool mods_need_sync = timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS;
341 split_mods_sync_t new_mods;
342 new_mods.real_mods = get_mods();
343 if (!mods_need_sync && new_mods.real_mods != split_shmem->mods.real_mods) {
344 mods_need_sync = true;
345 }
346
347 new_mods.weak_mods = get_weak_mods();
348 if (!mods_need_sync && new_mods.weak_mods != split_shmem->mods.weak_mods) {
349 mods_need_sync = true;
350 }
351
352# ifndef NO_ACTION_ONESHOT
353 new_mods.oneshot_mods = get_oneshot_mods();
354 if (!mods_need_sync && new_mods.oneshot_mods != split_shmem->mods.oneshot_mods) {
355 mods_need_sync = true;
356 }
357# endif // NO_ACTION_ONESHOT
358
359 bool okay = true;
360 if (mods_need_sync) {
361 okay &= transport_write(PUT_MODS, &new_mods, sizeof(new_mods));
362 if (okay) {
363 last_update = timer_read32();
364 }
365 }
366
367 return okay;
368}
369
370static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
371 set_mods(split_shmem->mods.real_mods);
372 set_weak_mods(split_shmem->mods.weak_mods);
373# ifndef NO_ACTION_ONESHOT
374 set_oneshot_mods(split_shmem->mods.oneshot_mods);
375# endif
376}
377
378# define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods_handlers)
379# define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods_handlers)
380# define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods),
381
382#else // SPLIT_MODS_ENABLE
383
384# define TRANSACTIONS_MODS_MASTER()
385# define TRANSACTIONS_MODS_SLAVE()
386# define TRANSACTIONS_MODS_REGISTRATIONS
387
388#endif // SPLIT_MODS_ENABLE
389
390////////////////////////////////////////////////////
391// Backlight
392
393#ifdef BACKLIGHT_ENABLE
394
395static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
396 static uint32_t last_update = 0;
397 uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0;
398 return send_if_condition(PUT_BACKLIGHT, &last_update, (level != split_shmem->backlight_level), &level, sizeof(level));
399}
400
401static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { backlight_set(split_shmem->backlight_level); }
402
403# define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight_handlers)
404# define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight_handlers)
405# define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level),
406
407#else // BACKLIGHT_ENABLE
408
409# define TRANSACTIONS_BACKLIGHT_MASTER()
410# define TRANSACTIONS_BACKLIGHT_SLAVE()
411# define TRANSACTIONS_BACKLIGHT_REGISTRATIONS
412
413#endif // BACKLIGHT_ENABLE
414
415////////////////////////////////////////////////////
416// RGBLIGHT
417
418#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
419
420static bool rgblight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
421 static uint32_t last_update = 0;
422 rgblight_syncinfo_t rgblight_sync;
423 rgblight_get_syncinfo(&rgblight_sync);
424 if (send_if_condition(PUT_RGBLIGHT, &last_update, (rgblight_sync.status.change_flags != 0), &rgblight_sync, sizeof(rgblight_sync))) {
425 rgblight_clear_change_flags();
426 } else {
427 return false;
428 }
429 return true;
430}
431
432static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
433 // Update the RGB with the new data
434 if (split_shmem->rgblight_sync.status.change_flags != 0) {
435 rgblight_update_sync(&split_shmem->rgblight_sync, false);
436 split_shmem->rgblight_sync.status.change_flags = 0;
437 }
438}
439
440# define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight_handlers)
441# define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight_handlers)
442# define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync),
443
444#else // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
445
446# define TRANSACTIONS_RGBLIGHT_MASTER()
447# define TRANSACTIONS_RGBLIGHT_SLAVE()
448# define TRANSACTIONS_RGBLIGHT_REGISTRATIONS
449
450#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
451
452////////////////////////////////////////////////////
453// LED Matrix
454
455#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
456
457static bool led_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
458 static uint32_t last_update = 0;
459 led_matrix_sync_t led_matrix_sync;
460 memcpy(&led_matrix_sync.led_matrix, &led_matrix_eeconfig, sizeof(led_eeconfig_t));
461 led_matrix_sync.led_suspend_state = led_matrix_get_suspend_state();
462 return send_if_data_mismatch(PUT_LED_MATRIX, &last_update, &led_matrix_sync, &split_shmem->led_matrix_sync, sizeof(led_matrix_sync));
463}
464
465static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
466 memcpy(&led_matrix_eeconfig, &split_shmem->led_matrix_sync.led_matrix, sizeof(led_eeconfig_t));
467 led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state);
468}
469
470# define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix_handlers)
471# define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix_handlers)
472# define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync),
473
474#else // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
475
476# define TRANSACTIONS_LED_MATRIX_MASTER()
477# define TRANSACTIONS_LED_MATRIX_SLAVE()
478# define TRANSACTIONS_LED_MATRIX_REGISTRATIONS
479
480#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
481
482////////////////////////////////////////////////////
483// RGB Matrix
484
485#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
486
487static bool rgb_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
488 static uint32_t last_update = 0;
489 rgb_matrix_sync_t rgb_matrix_sync;
490 memcpy(&rgb_matrix_sync.rgb_matrix, &rgb_matrix_config, sizeof(rgb_config_t));
491 rgb_matrix_sync.rgb_suspend_state = rgb_matrix_get_suspend_state();
492 return send_if_data_mismatch(PUT_RGB_MATRIX, &last_update, &rgb_matrix_sync, &split_shmem->rgb_matrix_sync, sizeof(rgb_matrix_sync));
493}
494
495static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
496 memcpy(&rgb_matrix_config, &split_shmem->rgb_matrix_sync.rgb_matrix, sizeof(rgb_config_t));
497 rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state);
498}
499
500# define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix_handlers)
501# define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix_handlers)
502# define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync),
503
504#else // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
505
506# define TRANSACTIONS_RGB_MATRIX_MASTER()
507# define TRANSACTIONS_RGB_MATRIX_SLAVE()
508# define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS
509
510#endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
511
512////////////////////////////////////////////////////
513// WPM
514
515#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
516
517static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
518 static uint32_t last_update = 0;
519 uint8_t current_wpm = get_current_wpm();
520 return send_if_condition(PUT_WPM, &last_update, (current_wpm != split_shmem->current_wpm), &current_wpm, sizeof(current_wpm));
521}
522
523static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); }
524
525# define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm_handlers)
526# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm_handlers)
527# define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm),
528
529#else // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
530
531# define TRANSACTIONS_WPM_MASTER()
532# define TRANSACTIONS_WPM_SLAVE()
533# define TRANSACTIONS_WPM_REGISTRATIONS
534
535#endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
536
537////////////////////////////////////////////////////
538
539uint8_t dummy;
540split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
541 // Set defaults
542 [0 ...(NUM_TOTAL_TRANSACTIONS - 1)] = {NULL, 0, 0, 0, 0, 0},
543
544#ifdef USE_I2C
545 [I2C_EXECUTE_CALLBACK] = trans_initiator2target_initializer(transaction_id),
546#endif // USE_I2C
547
548 // clang-format off
549 TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS
550 TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS
551 TRANSACTIONS_ENCODERS_REGISTRATIONS
552 TRANSACTIONS_SYNC_TIMER_REGISTRATIONS
553 TRANSACTIONS_LAYER_STATE_REGISTRATIONS
554 TRANSACTIONS_LED_STATE_REGISTRATIONS
555 TRANSACTIONS_MODS_REGISTRATIONS
556 TRANSACTIONS_BACKLIGHT_REGISTRATIONS
557 TRANSACTIONS_RGBLIGHT_REGISTRATIONS
558 TRANSACTIONS_LED_MATRIX_REGISTRATIONS
559 TRANSACTIONS_RGB_MATRIX_REGISTRATIONS
560 TRANSACTIONS_WPM_REGISTRATIONS
561// clang-format on
562
563#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
564 [PUT_RPC_INFO] = trans_initiator2target_initializer_cb(rpc_info, slave_rpc_info_callback),
565 [PUT_RPC_REQ_DATA] = trans_initiator2target_initializer(rpc_m2s_buffer),
566 [EXECUTE_RPC] = trans_initiator2target_initializer_cb(rpc_info.transaction_id, slave_rpc_exec_callback),
567 [GET_RPC_RESP_DATA] = trans_target2initiator_initializer(rpc_s2m_buffer),
568#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
569};
570
571bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
572 bool okay = true;
573 TRANSACTIONS_SLAVE_MATRIX_MASTER();
574 TRANSACTIONS_MASTER_MATRIX_MASTER();
575 TRANSACTIONS_ENCODERS_MASTER();
576 TRANSACTIONS_SYNC_TIMER_MASTER();
577 TRANSACTIONS_LAYER_STATE_MASTER();
578 TRANSACTIONS_LED_STATE_MASTER();
579 TRANSACTIONS_MODS_MASTER();
580 TRANSACTIONS_BACKLIGHT_MASTER();
581 TRANSACTIONS_RGBLIGHT_MASTER();
582 TRANSACTIONS_LED_MATRIX_MASTER();
583 TRANSACTIONS_RGB_MATRIX_MASTER();
584 TRANSACTIONS_WPM_MASTER();
585 return okay;
586}
587
588void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
589 TRANSACTIONS_SLAVE_MATRIX_SLAVE();
590 TRANSACTIONS_MASTER_MATRIX_SLAVE();
591 TRANSACTIONS_ENCODERS_SLAVE();
592 TRANSACTIONS_SYNC_TIMER_SLAVE();
593 TRANSACTIONS_LAYER_STATE_SLAVE();
594 TRANSACTIONS_LED_STATE_SLAVE();
595 TRANSACTIONS_MODS_SLAVE();
596 TRANSACTIONS_BACKLIGHT_SLAVE();
597 TRANSACTIONS_RGBLIGHT_SLAVE();
598 TRANSACTIONS_LED_MATRIX_SLAVE();
599 TRANSACTIONS_RGB_MATRIX_SLAVE();
600 TRANSACTIONS_WPM_SLAVE();
601}
602
603#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
604
605void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback) {
606 // Prevent invoking RPC on QMK core sync data
607 if (transaction_id <= GET_RPC_RESP_DATA) return;
608
609 // Set the callback
610 split_transaction_table[transaction_id].slave_callback = callback;
611 split_transaction_table[transaction_id].initiator2target_offset = offsetof(split_shared_memory_t, rpc_m2s_buffer);
612 split_transaction_table[transaction_id].target2initiator_offset = offsetof(split_shared_memory_t, rpc_s2m_buffer);
613}
614
615bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) {
616 // Prevent invoking RPC on QMK core sync data
617 if (transaction_id <= GET_RPC_RESP_DATA) return false;
618 // Prevent sizing issues
619 if (initiator2target_buffer_size > RPC_M2S_BUFFER_SIZE) return false;
620 if (target2initiator_buffer_size > RPC_S2M_BUFFER_SIZE) return false;
621
622 // Prepare the metadata block
623 rpc_sync_info_t info = {.transaction_id = transaction_id, .m2s_length = initiator2target_buffer_size, .s2m_length = target2initiator_buffer_size};
624
625 // Make sure the local side knows that we're not sending the full block of data
626 split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = initiator2target_buffer_size;
627 split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = target2initiator_buffer_size;
628
629 // Run through the sequence:
630 // * set the transaction ID and lengths
631 // * send the request data
632 // * execute RPC callback
633 // * retrieve the response data
634 if (!transport_write(PUT_RPC_INFO, &info, sizeof(info))) {
635 return false;
636 }
637 if (!transport_write(PUT_RPC_REQ_DATA, initiator2target_buffer, initiator2target_buffer_size)) {
638 return false;
639 }
640 if (!transport_write(EXECUTE_RPC, &transaction_id, sizeof(transaction_id))) {
641 return false;
642 }
643 if (!transport_read(GET_RPC_RESP_DATA, target2initiator_buffer, target2initiator_buffer_size)) {
644 return false;
645 }
646 return true;
647}
648
649void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) {
650 // The RPC info block contains the intended transaction ID, as well as the sizes for both inbound and outbound data.
651 // Ignore the args -- the `split_shmem` already has the info, we just need to act upon it.
652 // We must keep the `split_transaction_table` non-const, so that it is able to be modified at runtime.
653
654 split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = split_shmem->rpc_info.m2s_length;
655 split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = split_shmem->rpc_info.s2m_length;
656}
657
658void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) {
659 // We can assume that the buffer lengths are correctly set, now, given that sequentially the rpc_info callback was already executed.
660 // Go through the rpc_info and execute _that_ transaction's callback, with the scratch buffers as inputs.
661 int8_t transaction_id = split_shmem->rpc_info.transaction_id;
662 if (transaction_id < NUM_TOTAL_TRANSACTIONS) {
663 split_transaction_desc_t *trans = &split_transaction_table[transaction_id];
664 if (trans->slave_callback) {
665 trans->slave_callback(split_shmem->rpc_info.m2s_length, split_shmem->rpc_m2s_buffer, split_shmem->rpc_info.s2m_length, split_shmem->rpc_s2m_buffer);
666 }
667 }
668}
669
670#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
diff --git a/quantum/split_common/transactions.h b/quantum/split_common/transactions.h
new file mode 100644
index 000000000..4306ba1d8
--- /dev/null
+++ b/quantum/split_common/transactions.h
@@ -0,0 +1,54 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include "stdint.h"
20#include "stdbool.h"
21
22#include "matrix.h"
23#include "transaction_id_define.h"
24#include "transport.h"
25
26typedef void (*slave_callback_t)(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
27
28// Split transaction Descriptor
29typedef struct _split_transaction_desc_t {
30 uint8_t * status;
31 uint8_t initiator2target_buffer_size;
32 uint16_t initiator2target_offset;
33 uint8_t target2initiator_buffer_size;
34 uint16_t target2initiator_offset;
35 slave_callback_t slave_callback;
36} split_transaction_desc_t;
37
38// Forward declaration for the split transactions
39extern split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS];
40
41#define split_shmem_offset_ptr(offset) ((void *)(((uint8_t *)split_shmem) + (offset)))
42#define split_trans_initiator2target_buffer(trans) (split_shmem_offset_ptr((trans)->initiator2target_offset))
43#define split_trans_target2initiator_buffer(trans) (split_shmem_offset_ptr((trans)->target2initiator_offset))
44
45// returns false if valid data not received from slave
46bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
47void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
48
49void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback);
50
51bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
52
53#define transaction_rpc_send(transaction_id, initiator2target_buffer_size, initiator2target_buffer) transaction_rpc_exec(transaction_id, initiator2target_buffer_size, initiator2target_buffer, 0, NULL)
54#define transaction_rpc_recv(transaction_id, target2initiator_buffer_size, target2initiator_buffer) transaction_rpc_exec(transaction_id, 0, NULL, target2initiator_buffer_size, target2initiator_buffer)
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c
index 9ed0f7591..a711ef85f 100644
--- a/quantum/split_common/transport.c
+++ b/quantum/split_common/transport.c
@@ -1,452 +1,118 @@
1#include <string.h> 1/* Copyright 2021 QMK
2#include <stddef.h> 2 *
3 3 * This program is free software: you can redistribute it and/or modify
4#include "config.h" 4 * it under the terms of the GNU General Public License as published by
5#include "matrix.h" 5 * the Free Software Foundation, either version 2 of the License, or
6#include "quantum.h" 6 * (at your option) any later version.
7 7 *
8#define ROWS_PER_HAND (MATRIX_ROWS / 2) 8 * This program is distributed in the hope that it will be useful,
9#define SYNC_TIMER_OFFSET 2 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11#ifdef RGBLIGHT_ENABLE 11 * GNU General Public License for more details.
12# include "rgblight.h" 12 *
13#endif 13 * You should have received a copy of the GNU General Public License
14 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15#ifdef BACKLIGHT_ENABLE 15 */
16# include "backlight.h"
17#endif
18
19#ifdef ENCODER_ENABLE
20# include "encoder.h"
21static pin_t encoders_pad[] = ENCODERS_PAD_A;
22# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t))
23#endif
24
25#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
26# include "led_matrix.h"
27#endif
28#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
29# include "rgb_matrix.h"
30#endif
31
32#if defined(USE_I2C)
33 16
34# include "i2c_master.h" 17#include <string.h>
35# include "i2c_slave.h" 18#include <debug.h>
36
37typedef struct _I2C_slave_buffer_t {
38# ifndef DISABLE_SYNC_TIMER
39 uint32_t sync_timer;
40# endif
41# ifdef SPLIT_TRANSPORT_MIRROR
42 matrix_row_t mmatrix[ROWS_PER_HAND];
43# endif
44 matrix_row_t smatrix[ROWS_PER_HAND];
45# ifdef SPLIT_MODS_ENABLE
46 uint8_t real_mods;
47 uint8_t weak_mods;
48# ifndef NO_ACTION_ONESHOT
49 uint8_t oneshot_mods;
50# endif
51# endif
52# ifdef BACKLIGHT_ENABLE
53 uint8_t backlight_level;
54# endif
55# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
56 rgblight_syncinfo_t rgblight_sync;
57# endif
58# ifdef ENCODER_ENABLE
59 uint8_t encoder_state[NUMBER_OF_ENCODERS];
60# endif
61# ifdef WPM_ENABLE
62 uint8_t current_wpm;
63# endif
64# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
65 led_eeconfig_t led_matrix;
66 bool led_suspend_state;
67# endif
68# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
69 rgb_config_t rgb_matrix;
70 bool rgb_suspend_state;
71# endif
72} I2C_slave_buffer_t;
73 19
74static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; 20#include "transactions.h"
21#include "transport.h"
22#include "transaction_id_define.h"
23#include "atomic_util.h"
75 24
76# define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer) 25#ifdef USE_I2C
77# define I2C_KEYMAP_MASTER_START offsetof(I2C_slave_buffer_t, mmatrix)
78# define I2C_KEYMAP_SLAVE_START offsetof(I2C_slave_buffer_t, smatrix)
79# define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods)
80# define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods)
81# define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods)
82# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level)
83# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync)
84# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)
85# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm)
86# define I2C_LED_MATRIX_START offsetof(I2C_slave_buffer_t, led_matrix)
87# define I2C_LED_SUSPEND_START offsetof(I2C_slave_buffer_t, led_suspend_state)
88# define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix)
89# define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state)
90 26
91# define TIMEOUT 100 27# ifndef SLAVE_I2C_TIMEOUT
28# define SLAVE_I2C_TIMEOUT 100
29# endif // SLAVE_I2C_TIMEOUT
92 30
93# ifndef SLAVE_I2C_ADDRESS 31# ifndef SLAVE_I2C_ADDRESS
94# define SLAVE_I2C_ADDRESS 0x32 32# define SLAVE_I2C_ADDRESS 0x32
95# endif 33# endif
96 34
97// Get rows from other half over i2c 35# include "i2c_master.h"
98bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { 36# include "i2c_slave.h"
99 i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_SLAVE_START, (void *)slave_matrix, sizeof(i2c_buffer->smatrix), TIMEOUT);
100# ifdef SPLIT_TRANSPORT_MIRROR
101 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_MASTER_START, (void *)master_matrix, sizeof(i2c_buffer->mmatrix), TIMEOUT);
102# endif
103 37
104 // write backlight info 38// Ensure the I2C buffer has enough space
105# ifdef BACKLIGHT_ENABLE 39_Static_assert(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT");
106 uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0;
107 if (level != i2c_buffer->backlight_level) {
108 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) {
109 i2c_buffer->backlight_level = level;
110 }
111 }
112# endif
113 40
114# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) 41split_shared_memory_t *const split_shmem = (split_shared_memory_t *)i2c_slave_reg;
115 if (rgblight_get_change_flags()) {
116 rgblight_syncinfo_t rgblight_sync;
117 rgblight_get_syncinfo(&rgblight_sync);
118 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) {
119 rgblight_clear_change_flags();
120 }
121 }
122# endif
123 42
124# ifdef ENCODER_ENABLE 43void transport_master_init(void) { i2c_init(); }
125 i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT); 44void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); }
126 encoder_update_raw(i2c_buffer->encoder_state);
127# endif
128 45
129# ifdef WPM_ENABLE 46i2c_status_t transport_trigger_callback(int8_t id) {
130 uint8_t current_wpm = get_current_wpm(); 47 // If there's no callback, indicate that we were successful
131 if (current_wpm != i2c_buffer->current_wpm) { 48 if (!split_transaction_table[id].slave_callback) {
132 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WPM_START, (void *)&current_wpm, sizeof(current_wpm), TIMEOUT) >= 0) { 49 return I2C_STATUS_SUCCESS;
133 i2c_buffer->current_wpm = current_wpm;
134 }
135 } 50 }
136# endif
137 51
138# ifdef SPLIT_MODS_ENABLE 52 // Kick off the "callback executor", now that data has been written to the slave
139 uint8_t real_mods = get_mods(); 53 split_shmem->transaction_id = id;
140 if (real_mods != i2c_buffer->real_mods) { 54 split_transaction_desc_t *trans = &split_transaction_table[I2C_EXECUTE_CALLBACK];
141 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) { 55 return i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, SLAVE_I2C_TIMEOUT);
142 i2c_buffer->real_mods = real_mods; 56}
57
58bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) {
59 i2c_status_t status;
60 split_transaction_desc_t *trans = &split_transaction_table[id];
61 if (initiator2target_length > 0) {
62 size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length;
63 memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len);
64 if ((status = i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) {
65 return false;
143 } 66 }
144 } 67 }
145 68
146 uint8_t weak_mods = get_weak_mods(); 69 // If we need to execute a callback on the slave, do so
147 if (weak_mods != i2c_buffer->weak_mods) { 70 if ((status = transport_trigger_callback(id)) < 0) {
148 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) { 71 return false;
149 i2c_buffer->weak_mods = weak_mods;
150 }
151 } 72 }
152 73
153# ifndef NO_ACTION_ONESHOT 74 if (target2initiator_length > 0) {
154 uint8_t oneshot_mods = get_oneshot_mods(); 75 size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length;
155 if (oneshot_mods != i2c_buffer->oneshot_mods) { 76 if ((status = i2c_readReg(SLAVE_I2C_ADDRESS, trans->target2initiator_offset, split_trans_target2initiator_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) {
156 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) { 77 return false;
157 i2c_buffer->oneshot_mods = oneshot_mods;
158 } 78 }
79 memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len);
159 } 80 }
160# endif
161# endif
162 81
163# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
164 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_MATRIX_START, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix), TIMEOUT);
165 bool suspend_state = led_matrix_get_suspend_state();
166 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->led_suspend_state), TIMEOUT);
167# endif
168# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
169 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT);
170 bool suspend_state = rgb_matrix_get_suspend_state();
171 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT);
172# endif
173
174# ifndef DISABLE_SYNC_TIMER
175 i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
176 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT);
177# endif
178 return true; 82 return true;
179} 83}
180 84
181void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { 85#else // USE_I2C
182# ifndef DISABLE_SYNC_TIMER
183 sync_timer_update(i2c_buffer->sync_timer);
184# endif
185 // Copy matrix to I2C buffer
186 memcpy((void *)i2c_buffer->smatrix, (void *)slave_matrix, sizeof(i2c_buffer->smatrix));
187# ifdef SPLIT_TRANSPORT_MIRROR
188 memcpy((void *)master_matrix, (void *)i2c_buffer->mmatrix, sizeof(i2c_buffer->mmatrix));
189# endif
190
191// Read Backlight Info
192# ifdef BACKLIGHT_ENABLE
193 backlight_set(i2c_buffer->backlight_level);
194# endif
195
196# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
197 // Update the RGB with the new data
198 if (i2c_buffer->rgblight_sync.status.change_flags != 0) {
199 rgblight_update_sync(&i2c_buffer->rgblight_sync, false);
200 i2c_buffer->rgblight_sync.status.change_flags = 0;
201 }
202# endif
203
204# ifdef ENCODER_ENABLE
205 encoder_state_raw(i2c_buffer->encoder_state);
206# endif
207
208# ifdef WPM_ENABLE
209 set_current_wpm(i2c_buffer->current_wpm);
210# endif
211
212# ifdef SPLIT_MODS_ENABLE
213 set_mods(i2c_buffer->real_mods);
214 set_weak_mods(i2c_buffer->weak_mods);
215# ifndef NO_ACTION_ONESHOT
216 set_oneshot_mods(i2c_buffer->oneshot_mods);
217# endif
218# endif
219
220# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
221 memcpy((void *)i2c_buffer->led_matrix, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix));
222 led_matrix_set_suspend_state(i2c_buffer->led_suspend_state);
223# endif
224# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
225 memcpy((void *)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix));
226 rgb_matrix_set_suspend_state(i2c_buffer->rgb_suspend_state);
227# endif
228}
229
230void transport_master_init(void) { i2c_init(); }
231
232void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); }
233
234#else // USE_SERIAL
235 86
236# include "serial.h" 87# include "serial.h"
237 88
238typedef struct _Serial_s2m_buffer_t { 89static split_shared_memory_t shared_memory;
239 // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack 90split_shared_memory_t *const split_shmem = &shared_memory;
240 matrix_row_t smatrix[ROWS_PER_HAND];
241
242# ifdef ENCODER_ENABLE
243 uint8_t encoder_state[NUMBER_OF_ENCODERS];
244# endif
245
246} Serial_s2m_buffer_t;
247
248typedef struct _Serial_m2s_buffer_t {
249# ifdef SPLIT_MODS_ENABLE
250 uint8_t real_mods;
251 uint8_t weak_mods;
252# ifndef NO_ACTION_ONESHOT
253 uint8_t oneshot_mods;
254# endif
255# endif
256# ifndef DISABLE_SYNC_TIMER
257 uint32_t sync_timer;
258# endif
259# ifdef SPLIT_TRANSPORT_MIRROR
260 matrix_row_t mmatrix[ROWS_PER_HAND];
261# endif
262# ifdef BACKLIGHT_ENABLE
263 uint8_t backlight_level;
264# endif
265# ifdef WPM_ENABLE
266 uint8_t current_wpm;
267# endif
268# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
269 led_eeconfig_t led_matrix;
270 bool led_suspend_state;
271# endif
272# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
273 rgb_config_t rgb_matrix;
274 bool rgb_suspend_state;
275# endif
276} Serial_m2s_buffer_t;
277
278# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
279// When MCUs on both sides drive their respective RGB LED chains,
280// it is necessary to synchronize, so it is necessary to communicate RGB
281// information. In that case, define RGBLIGHT_SPLIT with info on the number
282// of LEDs on each half.
283//
284// Otherwise, if the master side MCU drives both sides RGB LED chains,
285// there is no need to communicate.
286
287typedef struct _Serial_rgblight_t {
288 rgblight_syncinfo_t rgblight_sync;
289} Serial_rgblight_t;
290 91
291volatile Serial_rgblight_t serial_rgblight = {}; 92void transport_master_init(void) { soft_serial_initiator_init(); }
292uint8_t volatile status_rgblight = 0; 93void transport_slave_init(void) { soft_serial_target_init(); }
293# endif
294
295volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
296volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
297uint8_t volatile status0 = 0;
298
299enum serial_transaction_id {
300 GET_SLAVE_MATRIX = 0,
301# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
302 PUT_RGBLIGHT,
303# endif
304};
305
306SSTD_t transactions[] = {
307 [GET_SLAVE_MATRIX] =
308 {
309 (uint8_t *)&status0,
310 sizeof(serial_m2s_buffer),
311 (uint8_t *)&serial_m2s_buffer,
312 sizeof(serial_s2m_buffer),
313 (uint8_t *)&serial_s2m_buffer,
314 },
315# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
316 [PUT_RGBLIGHT] =
317 {
318 (uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL // no slave to master transfer
319 },
320# endif
321};
322
323void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
324
325void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
326 94
327# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) 95bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) {
328 96 split_transaction_desc_t *trans = &split_transaction_table[id];
329// rgblight synchronization information communication. 97 if (initiator2target_length > 0) {
330 98 size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length;
331void transport_rgblight_master(void) { 99 memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len);
332 if (rgblight_get_change_flags()) {
333 rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync);
334 if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) {
335 rgblight_clear_change_flags();
336 }
337 }
338}
339
340void transport_rgblight_slave(void) {
341 if (status_rgblight == TRANSACTION_ACCEPTED) {
342 rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false);
343 status_rgblight = TRANSACTION_END;
344 } 100 }
345}
346 101
347# else 102 if (soft_serial_transaction(id) != TRANSACTION_END) {
348# define transport_rgblight_master()
349# define transport_rgblight_slave()
350# endif
351
352bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
353# ifndef SERIAL_USE_MULTI_TRANSACTION
354 if (soft_serial_transaction() != TRANSACTION_END) {
355 return false;
356 }
357# else
358 transport_rgblight_master();
359 if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) {
360 return false; 103 return false;
361 } 104 }
362# endif
363 105
364 // TODO: if MATRIX_COLS > 8 change to unpack() 106 if (target2initiator_length > 0) {
365 for (int i = 0; i < ROWS_PER_HAND; ++i) { 107 size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length;
366 slave_matrix[i] = serial_s2m_buffer.smatrix[i]; 108 memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len);
367# ifdef SPLIT_TRANSPORT_MIRROR
368 serial_m2s_buffer.mmatrix[i] = master_matrix[i];
369# endif
370 } 109 }
371 110
372# ifdef BACKLIGHT_ENABLE
373 // Write backlight level for slave to read
374 serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0;
375# endif
376
377# ifdef ENCODER_ENABLE
378 encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state);
379# endif
380
381# ifdef WPM_ENABLE
382 // Write wpm to slave
383 serial_m2s_buffer.current_wpm = get_current_wpm();
384# endif
385
386# ifdef SPLIT_MODS_ENABLE
387 serial_m2s_buffer.real_mods = get_mods();
388 serial_m2s_buffer.weak_mods = get_weak_mods();
389# ifndef NO_ACTION_ONESHOT
390 serial_m2s_buffer.oneshot_mods = get_oneshot_mods();
391# endif
392# endif
393
394# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
395 serial_m2s_buffer.led_matrix = led_matrix_eeconfig;
396 serial_m2s_buffer.led_suspend_state = led_matrix_get_suspend_state();
397# endif
398# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
399 serial_m2s_buffer.rgb_matrix = rgb_matrix_config;
400 serial_m2s_buffer.rgb_suspend_state = rgb_matrix_get_suspend_state();
401# endif
402
403# ifndef DISABLE_SYNC_TIMER
404 serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
405# endif
406 return true; 111 return true;
407} 112}
408 113
409void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { 114#endif // USE_I2C
410 transport_rgblight_slave();
411# ifndef DISABLE_SYNC_TIMER
412 sync_timer_update(serial_m2s_buffer.sync_timer);
413# endif
414
415 // TODO: if MATRIX_COLS > 8 change to pack()
416 for (int i = 0; i < ROWS_PER_HAND; ++i) {
417 serial_s2m_buffer.smatrix[i] = slave_matrix[i];
418# ifdef SPLIT_TRANSPORT_MIRROR
419 master_matrix[i] = serial_m2s_buffer.mmatrix[i];
420# endif
421 }
422# ifdef BACKLIGHT_ENABLE
423 backlight_set(serial_m2s_buffer.backlight_level);
424# endif
425
426# ifdef ENCODER_ENABLE
427 encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state);
428# endif
429 115
430# ifdef WPM_ENABLE 116bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { return transactions_master(master_matrix, slave_matrix); }
431 set_current_wpm(serial_m2s_buffer.current_wpm);
432# endif
433
434# ifdef SPLIT_MODS_ENABLE
435 set_mods(serial_m2s_buffer.real_mods);
436 set_weak_mods(serial_m2s_buffer.weak_mods);
437# ifndef NO_ACTION_ONESHOT
438 set_oneshot_mods(serial_m2s_buffer.oneshot_mods);
439# endif
440# endif
441
442# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
443 led_matrix_eeconfig = serial_m2s_buffer.led_matrix;
444 led_matrix_set_suspend_state(serial_m2s_buffer.led_suspend_state);
445# endif
446# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
447 rgb_matrix_config = serial_m2s_buffer.rgb_matrix;
448 rgb_matrix_set_suspend_state(serial_m2s_buffer.rgb_suspend_state);
449# endif
450}
451 117
452#endif 118void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { transactions_slave(master_matrix, slave_matrix); } \ No newline at end of file
diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h
index a9f66301b..2e07f6b25 100644
--- a/quantum/split_common/transport.h
+++ b/quantum/split_common/transport.h
@@ -1,10 +1,175 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
1#pragma once 17#pragma once
2 18
19#include "stdint.h"
20#include "stdbool.h"
21
22#include "progmem.h"
23#include "action_layer.h"
3#include "matrix.h" 24#include "matrix.h"
4 25
26#ifndef RPC_M2S_BUFFER_SIZE
27# define RPC_M2S_BUFFER_SIZE 32
28#endif // RPC_M2S_BUFFER_SIZE
29
30#ifndef RPC_S2M_BUFFER_SIZE
31# define RPC_S2M_BUFFER_SIZE 32
32#endif // RPC_S2M_BUFFER_SIZE
33
5void transport_master_init(void); 34void transport_master_init(void);
6void transport_slave_init(void); 35void transport_slave_init(void);
7 36
8// returns false if valid data not received from slave 37// returns false if valid data not received from slave
9bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); 38bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
10void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); 39void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
40
41bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length);
42
43#ifdef ENCODER_ENABLE
44# include "encoder.h"
45# define NUMBER_OF_ENCODERS (sizeof((pin_t[])ENCODERS_PAD_A) / sizeof(pin_t))
46#endif // ENCODER_ENABLE
47
48#ifdef BACKLIGHT_ENABLE
49# include "backlight.h"
50#endif // BACKLIGHT_ENABLE
51
52#ifdef RGBLIGHT_ENABLE
53# include "rgblight.h"
54#endif // RGBLIGHT_ENABLE
55
56typedef struct _split_slave_matrix_sync_t {
57 uint8_t checksum;
58 matrix_row_t matrix[(MATRIX_ROWS) / 2];
59} split_slave_matrix_sync_t;
60
61#ifdef SPLIT_TRANSPORT_MIRROR
62typedef struct _split_master_matrix_sync_t {
63 matrix_row_t matrix[(MATRIX_ROWS) / 2];
64} split_master_matrix_sync_t;
65#endif // SPLIT_TRANSPORT_MIRROR
66
67#ifdef ENCODER_ENABLE
68typedef struct _split_slave_encoder_sync_t {
69 uint8_t checksum;
70 uint8_t state[NUMBER_OF_ENCODERS];
71} split_slave_encoder_sync_t;
72#endif // ENCODER_ENABLE
73
74#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
75typedef struct _split_layers_sync_t {
76 layer_state_t layer_state;
77 layer_state_t default_layer_state;
78} split_layers_sync_t;
79#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
80
81#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
82# include "led_matrix.h"
83
84typedef struct _led_matrix_sync_t {
85 led_eeconfig_t led_matrix;
86 bool led_suspend_state;
87} led_matrix_sync_t;
88#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
89
90#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
91# include "rgb_matrix.h"
92
93typedef struct _rgb_matrix_sync_t {
94 rgb_config_t rgb_matrix;
95 bool rgb_suspend_state;
96} rgb_matrix_sync_t;
97#endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
98
99#ifdef SPLIT_MODS_ENABLE
100typedef struct _split_mods_sync_t {
101 uint8_t real_mods;
102 uint8_t weak_mods;
103# ifndef NO_ACTION_ONESHOT
104 uint8_t oneshot_mods;
105# endif // NO_ACTION_ONESHOT
106} split_mods_sync_t;
107#endif // SPLIT_MODS_ENABLE
108
109#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
110typedef struct _rpc_sync_info_t {
111 int8_t transaction_id;
112 uint8_t m2s_length;
113 uint8_t s2m_length;
114} rpc_sync_info_t;
115#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
116
117typedef struct _split_shared_memory_t {
118#ifdef USE_I2C
119 int8_t transaction_id;
120#endif // USE_I2C
121
122 split_slave_matrix_sync_t smatrix;
123
124#ifdef SPLIT_TRANSPORT_MIRROR
125 split_master_matrix_sync_t mmatrix;
126#endif // SPLIT_TRANSPORT_MIRROR
127
128#ifdef ENCODER_ENABLE
129 split_slave_encoder_sync_t encoders;
130#endif // ENCODER_ENABLE
131
132#ifndef DISABLE_SYNC_TIMER
133 uint32_t sync_timer;
134#endif // DISABLE_SYNC_TIMER
135
136#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
137 split_layers_sync_t layers;
138#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
139
140#ifdef SPLIT_LED_STATE_ENABLE
141 uint8_t led_state;
142#endif // SPLIT_LED_STATE_ENABLE
143
144#ifdef SPLIT_MODS_ENABLE
145 split_mods_sync_t mods;
146#endif // SPLIT_MODS_ENABLE
147
148#ifdef BACKLIGHT_ENABLE
149 uint8_t backlight_level;
150#endif // BACKLIGHT_ENABLE
151
152#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
153 rgblight_syncinfo_t rgblight_sync;
154#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
155
156#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
157 led_matrix_sync_t led_matrix_sync;
158#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
159
160#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
161 rgb_matrix_sync_t rgb_matrix_sync;
162#endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
163
164#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
165 uint8_t current_wpm;
166#endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
167
168#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
169 rpc_sync_info_t rpc_info;
170 uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];
171 uint8_t rpc_s2m_buffer[RPC_S2M_BUFFER_SIZE];
172#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
173} split_shared_memory_t;
174
175extern split_shared_memory_t *const split_shmem; \ No newline at end of file
diff --git a/testlist.mk b/testlist.mk
index 0d7609b9f..d256f4c81 100644
--- a/testlist.mk
+++ b/testlist.mk
@@ -1,6 +1,7 @@
1TEST_LIST = $(notdir $(patsubst %/rules.mk,%,$(wildcard $(ROOT_DIR)/tests/*/rules.mk))) 1TEST_LIST = $(notdir $(patsubst %/rules.mk,%,$(wildcard $(ROOT_DIR)/tests/*/rules.mk)))
2FULL_TESTS := $(TEST_LIST) 2FULL_TESTS := $(TEST_LIST)
3 3
4include $(ROOT_DIR)/quantum/debounce/tests/testlist.mk
4include $(ROOT_DIR)/quantum/sequencer/tests/testlist.mk 5include $(ROOT_DIR)/quantum/sequencer/tests/testlist.mk
5include $(ROOT_DIR)/quantum/serial_link/tests/testlist.mk 6include $(ROOT_DIR)/quantum/serial_link/tests/testlist.mk
6 7
diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk
index eb934ffe6..b787e77ec 100644
--- a/tmk_core/avr.mk
+++ b/tmk_core/avr.mk
@@ -301,7 +301,7 @@ ifneq ($(strip $(BOOTLOADER)), qmk-dfu)
301endif 301endif
302 make -C lib/lufa/Bootloaders/DFU/ clean 302 make -C lib/lufa/Bootloaders/DFU/ clean
303 $(QMK_BIN) generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/DFU/Keyboard.h 303 $(QMK_BIN) generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/DFU/Keyboard.h
304 $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) 304 $(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))
305 $(eval PROGRAM_SIZE_KB=$(shell n=`expr $(MAX_SIZE) / 1024` && echo $$(($$n)) || echo 0)) 305 $(eval PROGRAM_SIZE_KB=$(shell n=`expr $(MAX_SIZE) / 1024` && echo $$(($$n)) || echo 0))
306 $(eval BOOT_SECTION_SIZE_KB=$(shell n=`expr $(BOOTLOADER_SIZE) / 1024` && echo $$(($$n)) || echo 0)) 306 $(eval BOOT_SECTION_SIZE_KB=$(shell n=`expr $(BOOTLOADER_SIZE) / 1024` && echo $$(($$n)) || echo 0))
307 $(eval FLASH_SIZE_KB=$(shell n=`expr $(PROGRAM_SIZE_KB) + $(BOOT_SECTION_SIZE_KB)` && echo $$(($$n)) || echo 0)) 307 $(eval FLASH_SIZE_KB=$(shell n=`expr $(PROGRAM_SIZE_KB) + $(BOOT_SECTION_SIZE_KB)` && echo $$(($$n)) || echo 0))
diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk
index 97299b7d3..7eda36046 100644
--- a/tmk_core/chibios.mk
+++ b/tmk_core/chibios.mk
@@ -390,8 +390,10 @@ ifndef TEENSY_LOADER_CLI
390 endif 390 endif
391endif 391endif
392 392
393TEENSY_LOADER_CLI_MCU ?= $(MCU_LDSCRIPT)
394
393define EXEC_TEENSY 395define EXEC_TEENSY
394 $(TEENSY_LOADER_CLI) -mmcu=$(MCU_LDSCRIPT) -w -v $(BUILD_DIR)/$(TARGET).hex 396 $(TEENSY_LOADER_CLI) -mmcu=$(TEENSY_LOADER_CLI_MCU) -w -v $(BUILD_DIR)/$(TARGET).hex
395endef 397endef
396 398
397teensy: $(BUILD_DIR)/$(TARGET).hex cpfirmware sizeafter 399teensy: $(BUILD_DIR)/$(TARGET).hex cpfirmware sizeafter
@@ -408,6 +410,8 @@ else ifeq ($(strip $(BOOTLOADER)),kiibohd)
408 $(call EXEC_DFU_UTIL) 410 $(call EXEC_DFU_UTIL)
409else ifeq ($(strip $(MCU_FAMILY)),KINETIS) 411else ifeq ($(strip $(MCU_FAMILY)),KINETIS)
410 $(call EXEC_TEENSY) 412 $(call EXEC_TEENSY)
413else ifeq ($(strip $(MCU_FAMILY)),MIMXRT1062)
414 $(call EXEC_TEENSY)
411else ifeq ($(strip $(MCU_FAMILY)),STM32) 415else ifeq ($(strip $(MCU_FAMILY)),STM32)
412 $(call EXEC_DFU_UTIL) 416 $(call EXEC_DFU_UTIL)
413else 417else
diff --git a/tmk_core/common/arm_atsam/_timer.h b/tmk_core/common/arm_atsam/_timer.h
new file mode 100644
index 000000000..77402b612
--- /dev/null
+++ b/tmk_core/common/arm_atsam/_timer.h
@@ -0,0 +1,19 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#pragma once
17
18// The platform is 32-bit, so prefer 32-bit timers to avoid overflow
19#define FAST_TIMER_T_SIZE 32
diff --git a/tmk_core/common/avr/_timer.h b/tmk_core/common/avr/_timer.h
new file mode 100644
index 000000000..b81e0f68b
--- /dev/null
+++ b/tmk_core/common/avr/_timer.h
@@ -0,0 +1,19 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#pragma once
17
18// The platform is 8-bit, so prefer 16-bit timers to reduce code size
19#define FAST_TIMER_T_SIZE 16
diff --git a/tmk_core/common/avr/gpio.h b/tmk_core/common/avr/gpio.h
index 231556c29..e9be68491 100644
--- a/tmk_core/common/avr/gpio.h
+++ b/tmk_core/common/avr/gpio.h
@@ -20,6 +20,8 @@
20 20
21typedef uint8_t pin_t; 21typedef uint8_t pin_t;
22 22
23/* Operation of GPIO by pin. */
24
23#define setPinInput(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF)) 25#define setPinInput(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
24#define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF)) 26#define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
25#define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low") 27#define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low")
@@ -32,3 +34,16 @@ typedef uint8_t pin_t;
32#define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF))) 34#define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
33 35
34#define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF)) 36#define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF))
37
38/* Operation of GPIO by port. */
39
40typedef uint8_t port_data_t;
41
42#define readPort(port) PINx_ADDRESS(port)
43
44#define setPortBitInput(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) &= ~_BV((bit)&0xF))
45#define setPortBitInputHigh(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) |= _BV((bit)&0xF))
46#define setPortBitOutput(port, bit) (DDRx_ADDRESS(port) |= _BV((bit)&0xF))
47
48#define writePortBitLow(port, bit) (PORTx_ADDRESS(port) &= ~_BV((bit)&0xF))
49#define writePortBitHigh(port, bit) (PORTx_ADDRESS(port) |= _BV((bit)&0xF))
diff --git a/tmk_core/common/chibios/_timer.h b/tmk_core/common/chibios/_timer.h
new file mode 100644
index 000000000..77402b612
--- /dev/null
+++ b/tmk_core/common/chibios/_timer.h
@@ -0,0 +1,19 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#pragma once
17
18// The platform is 32-bit, so prefer 32-bit timers to avoid overflow
19#define FAST_TIMER_T_SIZE 32
diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c
index 11f7abf43..76d52ea60 100644
--- a/tmk_core/common/chibios/bootloader.c
+++ b/tmk_core/common/chibios/bootloader.c
@@ -95,7 +95,7 @@ void enter_bootloader_mode_if_requested(void) {
95 } 95 }
96} 96}
97 97
98#elif defined(KL2x) || defined(K20x) || defined(MK66F18) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS 98#elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS
99/* Kinetis */ 99/* Kinetis */
100 100
101# if defined(BOOTLOADER_KIIBOHD) 101# if defined(BOOTLOADER_KIIBOHD)
diff --git a/tmk_core/common/chibios/gpio.h b/tmk_core/common/chibios/gpio.h
index 5d0e142ab..4d057f1ca 100644
--- a/tmk_core/common/chibios/gpio.h
+++ b/tmk_core/common/chibios/gpio.h
@@ -20,6 +20,8 @@
20 20
21typedef ioline_t pin_t; 21typedef ioline_t pin_t;
22 22
23/* Operation of GPIO by pin. */
24
23#define setPinInput(pin) palSetLineMode(pin, PAL_MODE_INPUT) 25#define setPinInput(pin) palSetLineMode(pin, PAL_MODE_INPUT)
24#define setPinInputHigh(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLUP) 26#define setPinInputHigh(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLUP)
25#define setPinInputLow(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN) 27#define setPinInputLow(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN)
@@ -32,3 +34,17 @@ typedef ioline_t pin_t;
32#define readPin(pin) palReadLine(pin) 34#define readPin(pin) palReadLine(pin)
33 35
34#define togglePin(pin) palToggleLine(pin) 36#define togglePin(pin) palToggleLine(pin)
37
38/* Operation of GPIO by port. */
39
40typedef uint16_t port_data_t;
41
42#define readPort(pin) palReadPort(PAL_PORT(pin))
43
44#define setPortBitInput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT)
45#define setPortBitInputHigh(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLUP)
46#define setPortBitInputLow(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLDOWN)
47#define setPortBitOutput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_OUTPUT_PUSHPULL)
48
49#define writePortBitLow(pin, bit) palClearLine(PAL_LINE(PAL_PORT(pin), bit))
50#define writePortBitHigh(pin, bit) palSetLine(PAL_LINE(PAL_PORT(pin), bit))
diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c
index e7d92cfac..a8b391e89 100644
--- a/tmk_core/common/host.c
+++ b/tmk_core/common/host.c
@@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18#include <stdint.h> 18#include <stdint.h>
19//#include <avr/interrupt.h> 19//#include <avr/interrupt.h>
20#include "keyboard.h"
20#include "keycode.h" 21#include "keycode.h"
21#include "host.h" 22#include "host.h"
22#include "util.h" 23#include "util.h"
@@ -35,15 +36,20 @@ void host_set_driver(host_driver_t *d) { driver = d; }
35 36
36host_driver_t *host_get_driver(void) { return driver; } 37host_driver_t *host_get_driver(void) { return driver; }
37 38
39#ifdef SPLIT_KEYBOARD
40uint8_t split_led_state = 0;
41void set_split_host_keyboard_leds(uint8_t led_state) { split_led_state = led_state; }
42#endif
43
38uint8_t host_keyboard_leds(void) { 44uint8_t host_keyboard_leds(void) {
45#ifdef SPLIT_KEYBOARD
46 if (!is_keyboard_master()) return split_led_state;
47#endif
39 if (!driver) return 0; 48 if (!driver) return 0;
40 return (*driver->keyboard_leds)(); 49 return (*driver->keyboard_leds)();
41} 50}
42 51
43led_t host_keyboard_led_state(void) { 52led_t host_keyboard_led_state(void) { return (led_t)host_keyboard_leds(); }
44 if (!driver) return (led_t){0};
45 return (led_t)((*driver->keyboard_leds)());
46}
47 53
48/* send report */ 54/* send report */
49void host_keyboard_send(report_keyboard_t *report) { 55void host_keyboard_send(report_keyboard_t *report) {
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c
index 3d6092e71..28fa97bc8 100644
--- a/tmk_core/common/keyboard.c
+++ b/tmk_core/common/keyboard.c
@@ -85,6 +85,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
85#ifdef OLED_DRIVER_ENABLE 85#ifdef OLED_DRIVER_ENABLE
86# include "oled_driver.h" 86# include "oled_driver.h"
87#endif 87#endif
88#ifdef ST7565_ENABLE
89# include "st7565.h"
90#endif
88#ifdef VELOCIKEY_ENABLE 91#ifdef VELOCIKEY_ENABLE
89# include "velocikey.h" 92# include "velocikey.h"
90#endif 93#endif
@@ -100,6 +103,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
100#ifdef EEPROM_DRIVER 103#ifdef EEPROM_DRIVER
101# include "eeprom_driver.h" 104# include "eeprom_driver.h"
102#endif 105#endif
106#if defined(CRC_ENABLE)
107# include "crc.h"
108#endif
103 109
104static uint32_t last_input_modification_time = 0; 110static uint32_t last_input_modification_time = 0;
105uint32_t last_input_activity_time(void) { return last_input_modification_time; } 111uint32_t last_input_activity_time(void) { return last_input_modification_time; }
@@ -297,6 +303,9 @@ void keyboard_init(void) {
297 timer_init(); 303 timer_init();
298 sync_timer_init(); 304 sync_timer_init();
299 matrix_init(); 305 matrix_init();
306#if defined(CRC_ENABLE)
307 crc_init();
308#endif
300#ifdef VIA_ENABLE 309#ifdef VIA_ENABLE
301 via_init(); 310 via_init();
302#endif 311#endif
@@ -306,6 +315,9 @@ void keyboard_init(void) {
306#ifdef OLED_DRIVER_ENABLE 315#ifdef OLED_DRIVER_ENABLE
307 oled_init(OLED_ROTATION_0); 316 oled_init(OLED_ROTATION_0);
308#endif 317#endif
318#ifdef ST7565_ENABLE
319 st7565_init(DISPLAY_ROTATION_0);
320#endif
309#ifdef PS2_MOUSE_ENABLE 321#ifdef PS2_MOUSE_ENABLE
310 ps2_mouse_init(); 322 ps2_mouse_init();
311#endif 323#endif
@@ -470,6 +482,18 @@ MATRIX_LOOP_END:
470# endif 482# endif
471#endif 483#endif
472 484
485#ifdef ST7565_ENABLE
486 st7565_task();
487# ifndef ST7565_DISABLE_TIMEOUT
488 // Wake up display if user is using those fabulous keys or spinning those encoders!
489# ifdef ENCODER_ENABLE
490 if (matrix_changed || encoders_changed) st7565_on();
491# else
492 if (matrix_changed) st7565_on();
493# endif
494# endif
495#endif
496
473#ifdef MOUSEKEY_ENABLE 497#ifdef MOUSEKEY_ENABLE
474 // mousekey repeat & acceleration 498 // mousekey repeat & acceleration
475 mousekey_task(); 499 mousekey_task();
diff --git a/tmk_core/common/sync_timer.c b/tmk_core/common/sync_timer.c
index de24b463b..68b92d8b4 100644
--- a/tmk_core/common/sync_timer.c
+++ b/tmk_core/common/sync_timer.c
@@ -26,7 +26,7 @@ SOFTWARE.
26#include "sync_timer.h" 26#include "sync_timer.h"
27#include "keyboard.h" 27#include "keyboard.h"
28 28
29#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) 29#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER)
30volatile int32_t sync_timer_ms; 30volatile int32_t sync_timer_ms;
31 31
32void sync_timer_init(void) { sync_timer_ms = 0; } 32void sync_timer_init(void) { sync_timer_ms = 0; }
diff --git a/tmk_core/common/sync_timer.h b/tmk_core/common/sync_timer.h
index 9ddef45bb..744e2b50d 100644
--- a/tmk_core/common/sync_timer.h
+++ b/tmk_core/common/sync_timer.h
@@ -32,7 +32,7 @@ SOFTWARE.
32extern "C" { 32extern "C" {
33#endif 33#endif
34 34
35#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) 35#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER)
36void sync_timer_init(void); 36void sync_timer_init(void);
37void sync_timer_update(uint32_t time); 37void sync_timer_update(uint32_t time);
38uint16_t sync_timer_read(void); 38uint16_t sync_timer_read(void);
diff --git a/tmk_core/common/timer.h b/tmk_core/common/timer.h
index 58f637dd9..928811a2b 100644
--- a/tmk_core/common/timer.h
+++ b/tmk_core/common/timer.h
@@ -1,5 +1,6 @@
1/* 1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com> 2Copyright 2011 Jun Wako <wakojun@gmail.com>
3Copyright 2021 Simon Arlott
3 4
4This program is free software: you can redistribute it and/or modify 5This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by 6it under the terms of the GNU General Public License as published by
@@ -17,13 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
17 18
18#pragma once 19#pragma once
19 20
21#if __has_include_next("_timer.h")
22# include_next "_timer.h" /* Include the platform's _timer.h */
23#endif
24
20#include <stdint.h> 25#include <stdint.h>
21#include <stdbool.h> 26#include <stdbool.h>
22 27
23#if defined(__AVR__)
24# include "avr/timer_avr.h"
25#endif
26
27#define TIMER_DIFF(a, b, max) ((max == UINT8_MAX) ? ((uint8_t)((a) - (b))) : ((max == UINT16_MAX) ? ((uint16_t)((a) - (b))) : ((max == UINT32_MAX) ? ((uint32_t)((a) - (b))) : ((a) >= (b) ? (a) - (b) : (max) + 1 - (b) + (a))))) 28#define TIMER_DIFF(a, b, max) ((max == UINT8_MAX) ? ((uint8_t)((a) - (b))) : ((max == UINT16_MAX) ? ((uint16_t)((a) - (b))) : ((max == UINT32_MAX) ? ((uint32_t)((a) - (b))) : ((a) >= (b) ? (a) - (b) : (max) + 1 - (b) + (a)))))
28#define TIMER_DIFF_8(a, b) TIMER_DIFF(a, b, UINT8_MAX) 29#define TIMER_DIFF_8(a, b) TIMER_DIFF(a, b, UINT8_MAX)
29#define TIMER_DIFF_16(a, b) TIMER_DIFF(a, b, UINT16_MAX) 30#define TIMER_DIFF_16(a, b) TIMER_DIFF(a, b, UINT16_MAX)
@@ -47,6 +48,21 @@ uint32_t timer_elapsed32(uint32_t last);
47#define timer_expired(current, future) ((uint16_t)(current - future) < UINT16_MAX / 2) 48#define timer_expired(current, future) ((uint16_t)(current - future) < UINT16_MAX / 2)
48#define timer_expired32(current, future) ((uint32_t)(current - future) < UINT32_MAX / 2) 49#define timer_expired32(current, future) ((uint32_t)(current - future) < UINT32_MAX / 2)
49 50
51// Use an appropriate timer integer size based on architecture (16-bit will overflow sooner)
52#if FAST_TIMER_T_SIZE < 32
53# define TIMER_DIFF_FAST(a, b) TIMER_DIFF_16(a, b)
54# define timer_expired_fast(current, future) timer_expired(current, future)
55typedef uint16_t fast_timer_t;
56fast_timer_t inline timer_read_fast(void) { return timer_read(); }
57fast_timer_t inline timer_elapsed_fast(fast_timer_t last) { return timer_elapsed(last); }
58#else
59# define TIMER_DIFF_FAST(a, b) TIMER_DIFF_32(a, b)
60# define timer_expired_fast(current, future) timer_expired32(current, future)
61typedef uint32_t fast_timer_t;
62fast_timer_t inline timer_read_fast(void) { return timer_read32(); }
63fast_timer_t inline timer_elapsed_fast(fast_timer_t last) { return timer_elapsed32(last); }
64#endif
65
50#ifdef __cplusplus 66#ifdef __cplusplus
51} 67}
52#endif 68#endif
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index d04302aca..407b8ea75 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -903,7 +903,8 @@ static void send_extra(uint8_t report_id, uint16_t data) {
903 return; 903 return;
904 } 904 }
905 905
906 report_extra_t report = {.report_id = report_id, .usage = data}; 906 static report_extra_t report;
907 report = (report_extra_t){.report_id = report_id, .usage = data};
907 908
908 usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t)); 909 usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
909 osalSysUnlock(); 910 osalSysUnlock();
@@ -1051,45 +1052,44 @@ void virtser_task(void) {
1051#ifdef JOYSTICK_ENABLE 1052#ifdef JOYSTICK_ENABLE
1052 1053
1053void send_joystick_packet(joystick_t *joystick) { 1054void send_joystick_packet(joystick_t *joystick) {
1054 joystick_report_t rep = { 1055 static joystick_report_t rep;
1056 rep = (joystick_report_t) {
1055# if JOYSTICK_AXES_COUNT > 0 1057# if JOYSTICK_AXES_COUNT > 0
1056 .axes = 1058 .axes =
1057 { 1059 { joystick->axes[0],
1058 joystick->axes[0],
1059 1060
1060# if JOYSTICK_AXES_COUNT >= 2 1061# if JOYSTICK_AXES_COUNT >= 2
1061 joystick->axes[1], 1062 joystick->axes[1],
1062# endif 1063# endif
1063# if JOYSTICK_AXES_COUNT >= 3 1064# if JOYSTICK_AXES_COUNT >= 3
1064 joystick->axes[2], 1065 joystick->axes[2],
1065# endif 1066# endif
1066# if JOYSTICK_AXES_COUNT >= 4 1067# if JOYSTICK_AXES_COUNT >= 4
1067 joystick->axes[3], 1068 joystick->axes[3],
1068# endif 1069# endif
1069# if JOYSTICK_AXES_COUNT >= 5 1070# if JOYSTICK_AXES_COUNT >= 5
1070 joystick->axes[4], 1071 joystick->axes[4],
1071# endif 1072# endif
1072# if JOYSTICK_AXES_COUNT >= 6 1073# if JOYSTICK_AXES_COUNT >= 6
1073 joystick->axes[5], 1074 joystick->axes[5],
1074# endif 1075# endif
1075 }, 1076 },
1076# endif // JOYSTICK_AXES_COUNT>0 1077# endif // JOYSTICK_AXES_COUNT>0
1077 1078
1078# if JOYSTICK_BUTTON_COUNT > 0 1079# if JOYSTICK_BUTTON_COUNT > 0
1079 .buttons = 1080 .buttons = {
1080 { 1081 joystick->buttons[0],
1081 joystick->buttons[0],
1082 1082
1083# if JOYSTICK_BUTTON_COUNT > 8 1083# if JOYSTICK_BUTTON_COUNT > 8
1084 joystick->buttons[1], 1084 joystick->buttons[1],
1085# endif 1085# endif
1086# if JOYSTICK_BUTTON_COUNT > 16 1086# if JOYSTICK_BUTTON_COUNT > 16
1087 joystick->buttons[2], 1087 joystick->buttons[2],
1088# endif 1088# endif
1089# if JOYSTICK_BUTTON_COUNT > 24 1089# if JOYSTICK_BUTTON_COUNT > 24
1090 joystick->buttons[3], 1090 joystick->buttons[3],
1091# endif 1091# endif
1092 } 1092 }
1093# endif // JOYSTICK_BUTTON_COUNT>0 1093# endif // JOYSTICK_BUTTON_COUNT>0
1094 }; 1094 };
1095 1095
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 63619fdb3..4ac079e16 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -314,45 +314,44 @@ static void Console_Task(void) {
314void send_joystick_packet(joystick_t *joystick) { 314void send_joystick_packet(joystick_t *joystick) {
315 uint8_t timeout = 255; 315 uint8_t timeout = 255;
316 316
317 joystick_report_t r = { 317 static joystick_report_t;
318 r = (joystick_report_t) {
318# if JOYSTICK_AXES_COUNT > 0 319# if JOYSTICK_AXES_COUNT > 0
319 .axes = 320 .axes =
320 { 321 { joystick->axes[0],
321 joystick->axes[0],
322 322
323# if JOYSTICK_AXES_COUNT >= 2 323# if JOYSTICK_AXES_COUNT >= 2
324 joystick->axes[1], 324 joystick->axes[1],
325# endif 325# endif
326# if JOYSTICK_AXES_COUNT >= 3 326# if JOYSTICK_AXES_COUNT >= 3
327 joystick->axes[2], 327 joystick->axes[2],
328# endif 328# endif
329# if JOYSTICK_AXES_COUNT >= 4 329# if JOYSTICK_AXES_COUNT >= 4
330 joystick->axes[3], 330 joystick->axes[3],
331# endif 331# endif
332# if JOYSTICK_AXES_COUNT >= 5 332# if JOYSTICK_AXES_COUNT >= 5
333 joystick->axes[4], 333 joystick->axes[4],
334# endif 334# endif
335# if JOYSTICK_AXES_COUNT >= 6 335# if JOYSTICK_AXES_COUNT >= 6
336 joystick->axes[5], 336 joystick->axes[5],
337# endif 337# endif
338 }, 338 },
339# endif // JOYSTICK_AXES_COUNT>0 339# endif // JOYSTICK_AXES_COUNT>0
340 340
341# if JOYSTICK_BUTTON_COUNT > 0 341# if JOYSTICK_BUTTON_COUNT > 0
342 .buttons = 342 .buttons = {
343 { 343 joystick->buttons[0],
344 joystick->buttons[0],
345 344
346# if JOYSTICK_BUTTON_COUNT > 8 345# if JOYSTICK_BUTTON_COUNT > 8
347 joystick->buttons[1], 346 joystick->buttons[1],
348# endif 347# endif
349# if JOYSTICK_BUTTON_COUNT > 16 348# if JOYSTICK_BUTTON_COUNT > 16
350 joystick->buttons[2], 349 joystick->buttons[2],
351# endif 350# endif
352# if JOYSTICK_BUTTON_COUNT > 24 351# if JOYSTICK_BUTTON_COUNT > 24
353 joystick->buttons[3], 352 joystick->buttons[3],
354# endif 353# endif
355 } 354 }
356# endif // JOYSTICK_BUTTON_COUNT>0 355# endif // JOYSTICK_BUTTON_COUNT>0
357 }; 356 };
358 357
@@ -768,7 +767,8 @@ static void send_extra(uint8_t report_id, uint16_t data) {
768 767
769 if (USB_DeviceState != DEVICE_STATE_Configured) return; 768 if (USB_DeviceState != DEVICE_STATE_Configured) return;
770 769
771 report_extra_t r = {.report_id = report_id, .usage = data}; 770 static report_extra_t r;
771 r = (report_extra_t){.report_id = report_id, .usage = data};
772 Endpoint_SelectEndpoint(SHARED_IN_EPNUM); 772 Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
773 773
774 /* Check if write ready for a polling interval around 10ms */ 774 /* Check if write ready for a polling interval around 10ms */
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index ba7760f28..c88aceb6e 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -351,7 +351,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {
351 .Size = sizeof(USB_Descriptor_Device_t), 351 .Size = sizeof(USB_Descriptor_Device_t),
352 .Type = DTYPE_Device 352 .Type = DTYPE_Device
353 }, 353 },
354 .USBSpecification = VERSION_BCD(1, 1, 0), 354 .USBSpecification = VERSION_BCD(2, 0, 0),
355 355
356#if VIRTSER_ENABLE 356#if VIRTSER_ENABLE
357 .Class = USB_CSCP_IADDeviceClass, 357 .Class = USB_CSCP_IADDeviceClass,
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index 9362fbde7..876a31378 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -272,7 +272,8 @@ static void send_extra(uint8_t report_id, uint16_t data) {
272 last_id = report_id; 272 last_id = report_id;
273 last_data = data; 273 last_data = data;
274 274
275 report_extra_t report = {.report_id = report_id, .usage = data}; 275 static report_extra_t report;
276 report = (report_extra_t){.report_id = report_id, .usage = data};
276 if (usbInterruptIsReadyShared()) { 277 if (usbInterruptIsReadyShared()) {
277 usbSetInterruptShared((void *)&report, sizeof(report_extra_t)); 278 usbSetInterruptShared((void *)&report, sizeof(report_extra_t));
278 } 279 }
diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk
index fc2dc68be..597f7aa82 100644
--- a/tmk_core/rules.mk
+++ b/tmk_core/rules.mk
@@ -458,7 +458,7 @@ ifeq ($(findstring avr-gcc,$(CC)),avr-gcc)
458SIZE_MARGIN = 1024 458SIZE_MARGIN = 1024
459 459
460check-size: 460check-size:
461 $(eval MAX_SIZE=$(shell n=`$(CC) -E -mmcu=$(MCU) $(CFLAGS) $(OPT_DEFS) tmk_core/common/avr/bootloader_size.c 2> /dev/null | sed -ne 's/\r//;/^#/n;/^AVR_SIZE:/,$${s/^AVR_SIZE: //;p;}'` && echo $$(($$n)) || echo 0)) 461 $(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))
462 $(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)) 462 $(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))
463 $(eval FREE_SIZE=$(shell expr $(MAX_SIZE) - $(CURRENT_SIZE))) 463 $(eval FREE_SIZE=$(shell expr $(MAX_SIZE) - $(CURRENT_SIZE)))
464 $(eval OVER_SIZE=$(shell expr $(CURRENT_SIZE) - $(MAX_SIZE))) 464 $(eval OVER_SIZE=$(shell expr $(CURRENT_SIZE) - $(MAX_SIZE)))
diff --git a/users/bcat/config.h b/users/bcat/config.h
index 16188950e..5bb93f383 100644
--- a/users/bcat/config.h
+++ b/users/bcat/config.h
@@ -33,7 +33,7 @@
33 33
34#if defined(RGB_MATRIX_ENABLE) 34#if defined(RGB_MATRIX_ENABLE)
35/* Turn off per-key RGB when the host goes to sleep. */ 35/* Turn off per-key RGB when the host goes to sleep. */
36# define RGB_DISABLE_WHEN_USB_SUSPENDED true 36# define RGB_DISABLE_WHEN_USB_SUSPENDED
37 37
38/* Keep per-key RGB increments consistent across keyboards. */ 38/* Keep per-key RGB increments consistent across keyboards. */
39# undef RGB_MATRIX_HUE_STEP 39# undef RGB_MATRIX_HUE_STEP
diff --git a/users/bocaj/config.h b/users/bocaj/config.h
index 2a44aabfc..ecfb09c6f 100644
--- a/users/bocaj/config.h
+++ b/users/bocaj/config.h
@@ -28,7 +28,7 @@
28// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (not recommened) 28// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (not recommened)
29# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 29# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
30// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 30// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
31# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 31# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
32// # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 32// # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
33// # define EECONFIG_RGB_MATRIX (uint32_t *)16 33// # define EECONFIG_RGB_MATRIX (uint32_t *)16
34 34
diff --git a/users/curry/config.h b/users/curry/config.h
index b982dab03..e3c0a103e 100644
--- a/users/curry/config.h
+++ b/users/curry/config.h
@@ -17,7 +17,7 @@
17#if defined(RGB_MATRIX_ENABLE) 17#if defined(RGB_MATRIX_ENABLE)
18# define RGB_MATRIX_KEYPRESSES 18# define RGB_MATRIX_KEYPRESSES
19# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 19# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
20# define RGB_DISABLE_WHEN_USB_SUSPENDED true 20# define RGB_DISABLE_WHEN_USB_SUSPENDED
21 21
22# define DISABLE_RGB_MATRIX_ALPHAS_MODS 22# define DISABLE_RGB_MATRIX_ALPHAS_MODS
23# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN 23# define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
diff --git a/users/drashna/config.h b/users/drashna/config.h
index 5f7c32ff3..796485689 100644
--- a/users/drashna/config.h
+++ b/users/drashna/config.h
@@ -65,7 +65,7 @@
65// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (not recommened) 65// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (not recommened)
66# define RGB_MATRIX_FRAMEBUFFER_EFFECTS 66# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
67// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects 67// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
68# define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 68# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
69// # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 69// # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
70// # define EECONFIG_RGB_MATRIX (uint32_t *)16 70// # define EECONFIG_RGB_MATRIX (uint32_t *)16
71 71
diff --git a/users/drashna/drashna.h b/users/drashna/drashna.h
index e66f10657..e37c73bb2 100644
--- a/users/drashna/drashna.h
+++ b/users/drashna/drashna.h
@@ -33,7 +33,7 @@
33# include "oled_stuff.h" 33# include "oled_stuff.h"
34#endif 34#endif
35#if defined(PIMORONI_TRACKBALL_ENABLE) 35#if defined(PIMORONI_TRACKBALL_ENABLE)
36# include "pimoroni_trackball.h" 36# include "drivers/sensors/pimoroni_trackball.h"
37#endif 37#endif
38 38
39/* Define layer names */ 39/* Define layer names */
diff --git a/users/drashna/pimoroni_trackball.c b/users/drashna/pimoroni_trackball.c
deleted file mode 100644
index a6ca6c996..000000000
--- a/users/drashna/pimoroni_trackball.c
+++ /dev/null
@@ -1,151 +0,0 @@
1/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "pimoroni_trackball.h"
18#include "i2c_master.h"
19
20static uint8_t scrolling = 0;
21static int16_t x_offset = 0;
22static int16_t y_offset = 0;
23static int16_t h_offset = 0;
24static int16_t v_offset = 0;
25static float precisionSpeed = 1;
26
27#ifndef I2C_TIMEOUT
28# define I2C_TIMEOUT 100
29#endif
30#ifndef MOUSE_DEBOUNCE
31# define MOUSE_DEBOUNCE 5
32#endif
33
34void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) {
35 uint8_t data[] = {0x00, red, green, blue, white};
36 i2c_transmit(TRACKBALL_ADDRESS << 1, data, sizeof(data), I2C_TIMEOUT);
37}
38
39int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) {
40 int16_t offset = (int16_t)positive - (int16_t)negative;
41 int16_t magnitude = (int16_t)(scale * offset * offset * precisionSpeed);
42 return offset < 0 ? -magnitude : magnitude;
43}
44
45void update_member(int8_t* member, int16_t* offset) {
46 if (*offset > 127) {
47 *member = 127;
48 *offset -= 127;
49 } else if (*offset < -127) {
50 *member = -127;
51 *offset += 127;
52 } else {
53 *member = *offset;
54 *offset = 0;
55 }
56}
57
58__attribute__((weak)) void trackball_check_click(bool pressed, report_mouse_t* mouse) {
59 if (pressed) {
60 mouse->buttons |= MOUSE_BTN1;
61 } else {
62 mouse->buttons &= ~MOUSE_BTN1;
63 }
64}
65
66void trackball_register_button(bool pressed, enum mouse_buttons button) {
67 report_mouse_t currentReport = pointing_device_get_report();
68 if (pressed) {
69 currentReport.buttons |= button;
70 } else {
71 currentReport.buttons &= ~button;
72 }
73 pointing_device_set_report(currentReport);
74}
75
76float trackball_get_precision(void) { return precisionSpeed; }
77void trackball_set_precision(float precision) { precisionSpeed = precision; }
78bool trackball_is_scrolling(void) { return scrolling; }
79void trackball_set_scrolling(bool scroll) { scrolling = scroll; }
80
81bool has_report_changed (report_mouse_t first, report_mouse_t second) {
82 return !(
83 (!first.buttons && first.buttons == second.buttons) &&
84 (!first.x && first.x == second.x) &&
85 (!first.y && first.y == second.y) &&
86 (!first.h && first.h == second.h) &&
87 (!first.v && first.v == second.v) );
88}
89
90
91__attribute__((weak)) void pointing_device_init(void) { trackball_set_rgbw(0x00, 0x00, 0x00, 0x4F); }
92
93void pointing_device_task(void) {
94 static bool debounce;
95 static uint16_t debounce_timer;
96 uint8_t state[5] = {};
97 if (i2c_readReg(TRACKBALL_ADDRESS << 1, 0x04, state, 5, I2C_TIMEOUT) == I2C_STATUS_SUCCESS) {
98 if (!state[4] && !debounce) {
99 if (scrolling) {
100#ifdef PIMORONI_TRACKBALL_INVERT_X
101 h_offset += mouse_offset(state[2], state[3], 1);
102#else
103 h_offset -= mouse_offset(state[2], state[3], 1);
104#endif
105#ifdef PIMORONI_TRACKBALL_INVERT_Y
106 v_offset += mouse_offset(state[1], state[0], 1);
107#else
108 v_offset -= mouse_offset(state[1], state[0], 1);
109#endif
110 } else {
111#ifdef PIMORONI_TRACKBALL_INVERT_X
112 x_offset -= mouse_offset(state[2], state[3], 5);
113#else
114 x_offset += mouse_offset(state[2], state[3], 5);
115#endif
116#ifdef PIMORONI_TRACKBALL_INVERT_Y
117 y_offset -= mouse_offset(state[1], state[0], 5);
118#else
119 y_offset += mouse_offset(state[1], state[0], 5);
120#endif
121 }
122 } else {
123 if (state[4]) {
124 debounce = true;
125 debounce_timer = timer_read();
126 }
127 }
128 }
129
130 if (timer_elapsed(debounce_timer) > MOUSE_DEBOUNCE) debounce = false;
131
132 report_mouse_t mouse = pointing_device_get_report();
133
134 trackball_check_click(state[4] & (1 << 7), &mouse);
135
136#ifndef PIMORONI_TRACKBALL_ROTATE
137 update_member(&mouse.x, &x_offset);
138 update_member(&mouse.y, &y_offset);
139 update_member(&mouse.h, &h_offset);
140 update_member(&mouse.v, &v_offset);
141#else
142 update_member(&mouse.x, &y_offset);
143 update_member(&mouse.y, &x_offset);
144 update_member(&mouse.h, &v_offset);
145 update_member(&mouse.v, &h_offset);
146#endif
147 pointing_device_set_report(mouse);
148 if (has_report_changed(mouse, pointing_device_get_report())) {
149 pointing_device_send();
150 }
151}
diff --git a/users/drashna/rules.mk b/users/drashna/rules.mk
index b79051508..fa4fb2420 100644
--- a/users/drashna/rules.mk
+++ b/users/drashna/rules.mk
@@ -74,7 +74,7 @@ endif
74ifeq ($(strip $(PIMORONI_TRACKBALL_ENABLE)), yes) 74ifeq ($(strip $(PIMORONI_TRACKBALL_ENABLE)), yes)
75 POINTING_DEVICE_ENABLE := yes 75 POINTING_DEVICE_ENABLE := yes
76 OPT_DEFS += -DPIMORONI_TRACKBALL_ENABLE 76 OPT_DEFS += -DPIMORONI_TRACKBALL_ENABLE
77 SRC += pimoroni_trackball.c 77 SRC += drivers/sensors/pimoroni_trackball.c
78 QUANTUM_LIB_SRC += i2c_master.c 78 QUANTUM_LIB_SRC += i2c_master.c
79endif 79endif
80 80
diff --git a/users/spidey3/config.h b/users/spidey3/config.h
index 7062fde03..f5f5e07f0 100644
--- a/users/spidey3/config.h
+++ b/users/spidey3/config.h
@@ -1,7 +1,7 @@
1#pragma once 1#pragma once
2 2
3#define LED_DISABLE_WHEN_USB_SUSPENDED true 3#define LED_DISABLE_WHEN_USB_SUSPENDED
4#define RGB_DISABLE_WHEN_USB_SUSPENDED true 4#define RGB_DISABLE_WHEN_USB_SUSPENDED
5#define RGBLIGHT_LAYERS 5#define RGBLIGHT_LAYERS
6#define RGBLIGHT_MAX_LAYERS 17 6#define RGBLIGHT_MAX_LAYERS 17
7#define RGBLIGHT_LAYER_BLINK 7#define RGBLIGHT_LAYER_BLINK
diff --git a/users/tominabox1/config.h b/users/tominabox1/config.h
index 2a8c1e943..004f58ab5 100644
--- a/users/tominabox1/config.h
+++ b/users/tominabox1/config.h
@@ -31,7 +31,7 @@
31// RGB_Matrix settings 31// RGB_Matrix settings
32#ifdef RGB_MATRIX_ENABLE 32#ifdef RGB_MATRIX_ENABLE
33 #define RGB_MATRIX_KEYPRESSES // reacts to keypresses 33 #define RGB_MATRIX_KEYPRESSES // reacts to keypresses
34 #define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended 34 #define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
35 #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness) 35 #define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
36 #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash. 36 #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
37 #define RGB_MATRIX_HUE_STEP 8 37 #define RGB_MATRIX_HUE_STEP 8
diff --git a/util/update_chibios_mirror.sh b/util/update_chibios_mirror.sh
new file mode 100755
index 000000000..3df689f54
--- /dev/null
+++ b/util/update_chibios_mirror.sh
@@ -0,0 +1,55 @@
1#!/bin/bash
2
3################################
4# Configuration
5
6# The branches to mirror
7branches="trunk stable_20.3.x stable_21.6.x"
8
9# The tags to mirror
10tags="ver19.1.3 ver20.3.1 ver20.3.2 ver20.3.3 ver21.6.0"
11
12################################
13# Actions
14
15set -eEuo pipefail
16umask 022
17
18this_script="$(realpath "${BASH_SOURCE[0]}")"
19script_dir="$(realpath "$(dirname "$this_script")")"
20qmk_firmware_dir="$(realpath "$script_dir/../")"
21chibios_dir="$qmk_firmware_dir/lib/chibios"
22
23chibios_git_location=$(realpath "$chibios_dir/$(cat "$chibios_dir/.git" | awk '/gitdir:/ {print $2}')")
24chibios_git_config=$(realpath "$chibios_git_location/config")
25
26cd "$chibios_dir"
27
28if [[ -z "$(cat "$chibios_git_config" | grep '\[svn-remote "svn"\]')" ]] ; then
29 git svn init --stdlayout --prefix='svn/' http://svn.osdn.net/svnroot/chibios/
30fi
31
32if [[ -z "$(cat "$chibios_git_config" | grep '\[remote "qmk"\]')" ]] ; then
33 git remote add qmk git@github.com:qmk/ChibiOS.git
34 git remote set-url qmk git@github.com:qmk/ChibiOS.git --push
35fi
36
37echo "Updating remotes..."
38git fetch --all --tags --prune
39
40echo "Fetching latest from subversion..."
41git svn fetch
42
43echo "Updating branches..."
44for branch in $branches ; do
45 echo "Creating branch 'svn-mirror/$branch' from 'svn/$branch'..."
46 git branch -f svn-mirror/$branch svn/$branch \
47 && git push qmk svn-mirror/$branch
48done
49
50echo "Updating tags..."
51for tagname in $tags ; do
52 echo "Creating tag 'svn-mirror/$tagname' from 'svn/tags/$tagname'..."
53 GIT_COMMITTER_DATE="$(git log -n1 --pretty=format:'%ad' svn/tags/$tagname)" git tag -f -a -m "Tagging $tagname" svn-mirror/$tagname svn/tags/$tagname
54 git push qmk svn-mirror/$tagname
55done \ No newline at end of file