summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile1
-rw-r--r--builddefs/bootloader.mk4
-rw-r--r--builddefs/build_keyboard.mk33
-rw-r--r--builddefs/build_test.mk3
-rw-r--r--builddefs/common_features.mk125
-rw-r--r--builddefs/common_rules.mk117
-rw-r--r--builddefs/mcu_selection.mk35
-rw-r--r--builddefs/show_options.mk2
-rw-r--r--builddefs/testlist.mk1
-rw-r--r--data/mappings/info_config.json4
-rw-r--r--data/mappings/info_rules.json3
-rw-r--r--data/schemas/definitions.jsonschema41
-rw-r--r--data/schemas/keyboard.jsonschema123
-rw-r--r--data/schemas/keymap.jsonschema5
-rw-r--r--docs/_summary.md3
-rw-r--r--docs/compatible_microcontrollers.md6
-rw-r--r--docs/config_options.md4
-rw-r--r--docs/eeprom_driver.md103
-rw-r--r--docs/feature_mouse_keys.md6
-rw-r--r--docs/feature_pointing_device.md44
-rw-r--r--docs/feature_rgb_matrix.md20
-rw-r--r--docs/feature_split_keyboard.md5
-rw-r--r--docs/feature_stenography.md123
-rw-r--r--docs/feature_tap_dance.md143
-rw-r--r--docs/feature_terminal.md107
-rw-r--r--docs/flashing.md43
-rw-r--r--docs/ja/_summary.md1
-rw-r--r--docs/ja/config_options.md2
-rw-r--r--docs/ja/feature_tap_dance.md1
-rw-r--r--docs/ja/feature_terminal.md112
-rw-r--r--docs/ja/understanding_qmk.md1
-rw-r--r--docs/platformdev_chibios_earlyinit.md2
-rw-r--r--docs/platformdev_rp2040.md125
-rw-r--r--docs/quantum_painter.md25
-rw-r--r--docs/reference_info_json.md36
-rw-r--r--docs/serial_driver.md322
-rw-r--r--docs/understanding_qmk.md1
-rw-r--r--docs/ws2812_driver.md62
-rw-r--r--docs/zh-cn/_summary.md1
-rw-r--r--docs/zh-cn/custom_quantum_functions.md7
-rw-r--r--drivers/eeprom/eeprom_i2c.h5
-rw-r--r--drivers/eeprom/eeprom_wear_leveling.c23
-rw-r--r--drivers/led/aw20216.c6
-rw-r--r--drivers/led/issi/is31fl3733-simple.c6
-rw-r--r--drivers/led/issi/is31fl3733.c6
-rw-r--r--drivers/led/issi/is31fl3736.c6
-rw-r--r--drivers/led/issi/is31fl3737.c6
-rw-r--r--drivers/led/issi/is31fl3741.c6
-rw-r--r--drivers/painter/gc9a01/qp_gc9a01.c9
-rw-r--r--drivers/painter/ili9xxx/qp_ili9163.c9
-rw-r--r--drivers/painter/ili9xxx/qp_ili9341.c9
-rw-r--r--drivers/painter/ili9xxx/qp_ili9488.c120
-rw-r--r--drivers/painter/ili9xxx/qp_ili9488.h37
-rw-r--r--drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h1
-rw-r--r--drivers/painter/ssd1351/qp_ssd1351.c9
-rw-r--r--drivers/painter/st77xx/qp_st7789.c9
-rw-r--r--drivers/painter/tft_panel/qp_tft_panel.c60
-rw-r--r--drivers/painter/tft_panel/qp_tft_panel.h16
-rw-r--r--drivers/ps2/ps2.h1
-rw-r--r--drivers/ps2/ps2_interrupt.c4
-rw-r--r--drivers/ps2/ps2_mouse.c19
-rw-r--r--drivers/sensors/cirque_pinnacle.c105
-rw-r--r--drivers/sensors/cirque_pinnacle.h50
-rw-r--r--drivers/sensors/cirque_pinnacle_i2c.c4
-rw-r--r--drivers/sensors/cirque_pinnacle_spi.c4
-rw-r--r--drivers/sensors/pimoroni_trackball.c13
-rw-r--r--drivers/sensors/pimoroni_trackball.h1
-rw-r--r--drivers/serial.h10
-rw-r--r--drivers/wear_leveling/wear_leveling_flash_spi.c101
-rw-r--r--drivers/wear_leveling/wear_leveling_flash_spi_config.h34
-rw-r--r--keyboards/1k/keymaps/tap_dance/config.h1
-rw-r--r--keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/config.h3
-rw-r--r--keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/keymap.c2
-rw-r--r--keyboards/40percentclub/gherkin/keymaps/itsaferbie/keymap.c2
-rw-r--r--keyboards/40percentclub/half_n_half/keymaps/Boy_314/keymap.c4
-rw-r--r--keyboards/40percentclub/mf68/keymaps/delivrance/rules.mk1
-rw-r--r--keyboards/annepro2/c15/config.h18
-rw-r--r--keyboards/annepro2/c15/rules.mk4
-rw-r--r--keyboards/annepro2/c18/config.h18
-rw-r--r--keyboards/annepro2/c18/rules.mk4
-rw-r--r--keyboards/annepro2/halconf.h4
-rw-r--r--keyboards/annepro2/mcuconf.h8
-rw-r--r--keyboards/bandominedoni/keymaps/led/keymap.c2
-rw-r--r--keyboards/bandominedoni/keymaps/via/keymap.c2
-rw-r--r--keyboards/basekeys/slice/rev1/keymaps/2moons/keymap.c4
-rw-r--r--keyboards/basekeys/slice/rev1_rgb/keymaps/2moons_rgb/keymap.c4
-rw-r--r--keyboards/biacco42/ergo42/keymaps/hdbx/keymap.c4
-rw-r--r--keyboards/bpiphany/frosty_flake/keymaps/nikchi/config.h1
-rw-r--r--keyboards/bpiphany/frosty_flake/keymaps/nikchi/keymap.c32
-rw-r--r--keyboards/bpiphany/frosty_flake/keymaps/nikchi/variableTapDance.md5
-rw-r--r--keyboards/bpiphany/kitten_paw/keymaps/ickerwx/keymap.c4
-rw-r--r--keyboards/bpiphany/pegasushoof/keymaps/blowrak/keymap.c2
-rw-r--r--keyboards/cannonkeys/ortho75/ortho75.c73
-rw-r--r--keyboards/cannonkeys/satisfaction75/satisfaction75.c2
-rwxr-xr-xkeyboards/ckeys/handwire_101/keymaps/default/keymap.c8
-rwxr-xr-xkeyboards/ckeys/handwire_101/rules.mk1
-rw-r--r--keyboards/ckeys/washington/keymaps/default/keymap.c4
-rw-r--r--keyboards/clueboard/66/keymaps/magicmonty/keymap.c2
-rw-r--r--keyboards/contra/keymaps/default/keymap.c2
-rw-r--r--keyboards/crkbd/keymaps/dsanchezseco/keymap.c2
-rw-r--r--keyboards/crkbd/keymaps/edvorakjp/keymap.c4
-rw-r--r--keyboards/crkbd/keymaps/edvorakjp/oled.c2
-rw-r--r--keyboards/crkbd/keymaps/jarred/keymap.c2
-rw-r--r--keyboards/delikeeb/vaneela/keymaps/default/keymap.c2
-rw-r--r--keyboards/delikeeb/vaneela/keymaps/via/keymap.c2
-rwxr-xr-xkeyboards/dichotomy/keymaps/default/keymap.c4
-rw-r--r--keyboards/dm9records/plaid/keymaps/default/keymap.c2
-rw-r--r--keyboards/dm9records/plaid/keymaps/thehalfdeafchef/keymap.c2
-rw-r--r--keyboards/doppelganger/doppelganger.c36
-rw-r--r--keyboards/duck/lightsaver/keymaps/rasmus/keymap.c4
-rw-r--r--keyboards/dz60/keymaps/iso_split-spacebar/keymap.c28
-rw-r--r--keyboards/dz60/keymaps/marianas/customLogic.c2
-rw-r--r--keyboards/dz60/keymaps/xtonhasvim/keymap.c4
-rw-r--r--keyboards/dztech/dz60rgb/keymaps/matthewrobo/keymap.c2
-rw-r--r--keyboards/dztech/dz60rgb/keymaps/mekanist/keymap.c4
-rw-r--r--keyboards/dztech/dz60rgb/keymaps/perseid/keymap.c4
-rw-r--r--keyboards/dztech/dz65rgb/keymaps/catrielmuller/keymap.c4
-rw-r--r--keyboards/dztech/dz65rgb/keymaps/drootz/keymap.c156
-rw-r--r--keyboards/dztech/dz65rgb/keymaps/matthewrobo/keymap.c2
-rwxr-xr-xkeyboards/ergodox_ez/keymaps/bepo_tm_style/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/blakedietz/keymap.c3
-rw-r--r--keyboards/ergodox_ez/keymaps/bpruitt-goddard/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/default_osx/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/dvorak_42_key/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h1
-rw-r--r--keyboards/ergodox_ez/keymaps/hacker_dvorak/tap_dance/tap_dance_actions.c38
-rw-r--r--keyboards/ergodox_ez/keymaps/hacker_dvorak/user/layer_set_state_user.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/heartrobotninja/keymap.c4
-rw-r--r--keyboards/ergodox_ez/keymaps/kou/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/lukaus/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/matrixman/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/nathanvercaemert/keymap.c3
-rw-r--r--keyboards/ergodox_ez/keymaps/nfriend/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/profet_80/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/pvinis/keymap.c6
-rw-r--r--keyboards/ergodox_ez/keymaps/rgb_layer/keymap.c3
-rw-r--r--keyboards/ergodox_ez/keymaps/rishka/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/skug/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/smurmann/keymap.c8
-rw-r--r--keyboards/ergodox_ez/keymaps/steno/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/testing/keymap.c2
-rw-r--r--keyboards/ergodox_ez/keymaps/vim/keymap.c2
-rwxr-xr-xkeyboards/ergodox_ez/util/compile_keymap.py110
-rw-r--r--keyboards/ergoslab/keymaps/default/keymap.c2
-rw-r--r--keyboards/exclusive/e65/keymaps/masterzen/keymap.c2
-rw-r--r--keyboards/exclusive/e7v1/keymaps/masterzen/keymap.c2
-rw-r--r--keyboards/flehrad/bigswitch/keymaps/333fred/config.h1
-rw-r--r--keyboards/fractal/keymaps/default/keymap.c2
-rw-r--r--keyboards/gboards/gergo/keymaps/colemak/keymap.c5
-rw-r--r--keyboards/gboards/gergoplex/keymaps/georgepetri/config.h2
-rw-r--r--keyboards/gboards/gergoplex/keymaps/georgepetri/keymap.c11
-rw-r--r--keyboards/gh60/revc/keymaps/dbroqua/keymap.c4
-rw-r--r--keyboards/gh60/revc/keymaps/default/keymap.c2
-rw-r--r--keyboards/gh60/revc/keymaps/robotmaxtron/keymap.c2
-rw-r--r--keyboards/gh60/satan/keymaps/addcninblue/keymap.c2
-rw-r--r--keyboards/glenpickle/chimera_ergo/keymaps/default/keymap.c2
-rw-r--r--keyboards/glenpickle/chimera_ls/keymaps/default/keymap.c2
-rw-r--r--keyboards/glenpickle/chimera_ortho/keymaps/default/keymap.c2
-rw-r--r--keyboards/gon/nerdtkl/keymaps/gam3cat/keymap.c2
-rw-r--r--keyboards/handwired/ergocheap/config.h1
-rw-r--r--keyboards/handwired/frenchdev/keymaps/default/keymap.c2
-rw-r--r--keyboards/handwired/kbod/keymaps/default/keymap.c2
-rw-r--r--keyboards/handwired/onekey/config.h1
-rw-r--r--keyboards/handwired/onekey/onekey.c11
-rw-r--r--keyboards/handwired/onekey/rp2040/config.h17
-rw-r--r--keyboards/handwired/onekey/rp2040/readme.md12
-rw-r--r--keyboards/handwired/onekey/rp2040/rules.mk3
-rw-r--r--keyboards/handwired/ortho5x14/keymaps/2u/keymap.c6
-rw-r--r--keyboards/handwired/ortho5x14/keymaps/split1/keymap.c6
-rw-r--r--keyboards/handwired/ortho_brass/keymaps/default/keymap.c2
-rw-r--r--keyboards/handwired/prime_exl/keymaps/via/keymap.c2
-rw-r--r--keyboards/handwired/promethium/keymaps/default/keymap.c6
-rw-r--r--keyboards/handwired/promethium/keymaps/priyadi/keymap.c8
-rw-r--r--keyboards/handwired/riblee_f401/keymaps/default/keymap.c2
-rw-r--r--keyboards/handwired/riblee_f411/keymaps/default/keymap.c2
-rw-r--r--keyboards/handwired/rs60/keymaps/default/keymap.c2
-rw-r--r--keyboards/handwired/terminus_mini/keymaps/default/keymap.c2
-rw-r--r--keyboards/handwired/traveller/keymaps/default/keymap.c2
-rw-r--r--keyboards/handwired/tritium_numpad/keymaps/blu/keymap.c2
-rw-r--r--keyboards/handwired/uthol/rev3/config.h1
-rw-r--r--keyboards/helix/pico/keymaps/mtei/config.h2
-rw-r--r--keyboards/helix/pico/keymaps/mtei/keymap.c2
-rw-r--r--keyboards/helix/rev2/keymaps/default/oled_display.c2
-rw-r--r--keyboards/helix/rev2/keymaps/edvorakjp/keymap.c4
-rw-r--r--keyboards/helix/rev2/keymaps/edvorakjp/oled.c2
-rw-r--r--keyboards/helix/rev2/keymaps/five_rows/config.h2
-rw-r--r--keyboards/helix/rev2/keymaps/five_rows/keymap.c4
-rw-r--r--keyboards/helix/rev3_5rows/keymaps/five_rows/config.h2
-rw-r--r--keyboards/helix/rev3_5rows/keymaps/five_rows/keymap.c4
-rw-r--r--keyboards/hineybush/h87a/keymaps/gam3cat/keymap.c2
-rw-r--r--keyboards/hotdox/keymaps/default/keymap.c2
-rw-r--r--keyboards/hotdox/keymaps/eozaki/keymap.c2
-rw-r--r--keyboards/hotdox/keymaps/kloki/keymap.c2
-rw-r--r--keyboards/idobao/id67/keymaps/thewerther/config.h1
-rw-r--r--keyboards/input_club/ergodox_infinity/keymaps/default/keymap.c2
-rw-r--r--keyboards/input_club/ergodox_infinity/keymaps/gordon/keymap.c2
-rw-r--r--keyboards/input_club/ergodox_infinity/keymaps/halfkeyboard/keymap.c2
-rw-r--r--keyboards/input_club/ergodox_infinity/keymaps/input_club/keymap.c2
-rw-r--r--keyboards/input_club/ergodox_infinity/keymaps/narze/keymap.c2
-rw-r--r--keyboards/input_club/ergodox_infinity/keymaps/nordic_ergo/keymap.c2
-rw-r--r--keyboards/input_club/ergodox_infinity/keymaps/rask/keymap.c2
-rw-r--r--keyboards/input_club/ergodox_infinity/keymaps/rjhilgefort/keymap.c2
-rw-r--r--keyboards/input_club/ergodox_infinity/keymaps/trulyergonomic/keymap.c2
-rw-r--r--keyboards/input_club/infinity60/keymaps/jpetermans/keymap.c4
-rw-r--r--keyboards/jc65/v32u4/keymaps/gam3cat/keymap.c2
-rw-r--r--keyboards/jones/v03/keymaps/default_jp/config.h1
-rw-r--r--keyboards/jones/v03/keymaps/default_jp/keymap.c15
-rw-r--r--keyboards/jones/v03_1/keymaps/default_ansi/config.h1
-rw-r--r--keyboards/jones/v03_1/keymaps/default_ansi/keymap.c17
-rw-r--r--keyboards/jones/v03_1/keymaps/default_jp/config.h1
-rw-r--r--keyboards/jones/v03_1/keymaps/default_jp/keymap.c17
-rw-r--r--keyboards/kakunpc/angel64/alpha/keymaps/default/keymap.c2
-rw-r--r--keyboards/kakunpc/angel64/rev1/keymaps/kakunpc/keymap.c2
-rw-r--r--keyboards/kakunpc/suihankey/alpha/keymaps/default/keymap.c2
-rw-r--r--keyboards/kakunpc/suihankey/rev1/keymaps/default/keymap.c2
-rw-r--r--keyboards/kbdfans/kbd6x/keymaps/othi/keymap.c3
-rw-r--r--keyboards/kbdfans/kbd75/keymaps/edulpn/keymap.c2
-rw-r--r--keyboards/kbdfans/niu_mini/keymaps/tobias/keymap.c30
-rw-r--r--keyboards/kbdfans/niu_mini/keymaps/xtonhasvim/keymap.c2
-rw-r--r--keyboards/keebio/bdn9/keymaps/vosechu-ksp/keymap.c2
-rw-r--r--keyboards/keebio/bfo9000/keymaps/abstractkb/keymap.c5
-rw-r--r--keyboards/keebio/iris/keymaps/edvorakjp/keymap.c4
-rw-r--r--keyboards/keebio/iris/keymaps/jerryhcooke/keymap.c4
-rw-r--r--keyboards/keebio/iris/keymaps/sq5rix/keymap.c3
-rw-r--r--keyboards/keebio/levinson/keymaps/issmirnov/keymap.c2
-rw-r--r--keyboards/keebio/levinson/keymaps/issmirnov/rgb.c2
-rw-r--r--keyboards/keebio/levinson/keymaps/issmirnov/rgb.h2
-rw-r--r--keyboards/keebio/levinson/keymaps/xtonhasvim/keymap.c2
-rw-r--r--keyboards/keebio/nyquist/keymaps/pitty/keymap.c2
-rw-r--r--keyboards/keebio/quefrency/keymaps/georgepetri/keymap.c2
-rw-r--r--keyboards/keycapsss/o4l_5x12/keymaps/default/keymap.c2
-rw-r--r--keyboards/keychron/q2/config.h3
-rw-r--r--keyboards/keychron/q2/rev_0110/rules.mk3
-rw-r--r--keyboards/keychron/q2/rev_0111/rules.mk3
-rw-r--r--keyboards/keychron/q2/rev_0112/rules.mk3
-rw-r--r--keyboards/keychron/q2/rev_0113/rules.mk3
-rwxr-xr-xkeyboards/keyhive/honeycomb/keymaps/default/keymap.c2
-rw-r--r--keyboards/keyhive/navi10/keymaps/default/keymap.c2
-rw-r--r--keyboards/keyhive/navi10/keymaps/devdev/keymap.c2
-rw-r--r--keyboards/keyhive/navi10/keymaps/emdarcher/keymap.c2
-rw-r--r--keyboards/kinesis/keymaps/milestogo/keymap.c2
-rw-r--r--keyboards/kprepublic/cospad/keymaps/detrus/keymap.c6
-rw-r--r--keyboards/kprepublic/jj50/keymaps/abstractkb/keymap.c2
-rw-r--r--keyboards/kprepublic/jj50/keymaps/abstractkb_gergomatch/keymap.c2
-rw-r--r--keyboards/kprepublic/jj50/keymaps/archetype/config.h1
-rw-r--r--keyboards/kprepublic/jj50/keymaps/archetype/keymap.c11
-rw-r--r--keyboards/ktec/ergodone/keymaps/eozaki/keymap.c2
-rw-r--r--keyboards/ktec/ergodone/keymaps/erovia/keymap.c2
-rw-r--r--keyboards/ktec/ergodone/keymaps/kloki/keymap.c2
-rw-r--r--keyboards/ktec/ergodone/keymaps/vega/keymap.c2
-rw-r--r--keyboards/leeku/finger65/keymaps/madhatter/keymap.c2
-rwxr-xr-xkeyboards/lets_split/keymaps/bbaserdem/keymap.c2
-rw-r--r--keyboards/lets_split/keymaps/cpeters1982/keymap.c2
-rw-r--r--keyboards/lets_split/keymaps/geripgeri/keymap.c2
-rw-r--r--keyboards/lets_split/keymaps/pitty/keymap.c2
-rw-r--r--keyboards/lily58/lib/layer_state_reader.c2
-rw-r--r--keyboards/m10a/keymaps/gam3cat/keymap.c2
-rwxr-xr-xkeyboards/maple_computing/lets_split_eh/keymaps/bbaserdem/keymap.c2
-rw-r--r--keyboards/maple_computing/lets_split_eh/keymaps/romus/keymap.c4
-rw-r--r--keyboards/massdrop/alt/keymaps/pregame/rules.mk1
-rw-r--r--keyboards/massdrop/ctrl/keymaps/endgame/rules.mk1
-rw-r--r--keyboards/massdrop/ctrl/keymaps/matthewrobo/rules.mk1
-rw-r--r--keyboards/massdrop/ctrl/keymaps/xanimos/rules.mk1
-rw-r--r--keyboards/mechkeys/mechmini/v2/keymaps/wsturgiss/keymap.c3
-rw-r--r--keyboards/mechllama/g35/keymaps/default/keymap.c2
-rw-r--r--keyboards/mechlovin/hannah910/hannah910.c6
-rw-r--r--keyboards/mechlovin/hex4b/keymaps/nazzer/keymap.c28
-rw-r--r--keyboards/minimacro5/keymaps/devdev/keymap.c2
-rw-r--r--keyboards/mitosis/keymaps/carvac_dv/keymap.c3
-rw-r--r--keyboards/mitosis/keymaps/datagrok/keymap.c4
-rw-r--r--keyboards/mitosis/keymaps/default/keymap.c5
-rw-r--r--keyboards/mitosis/keymaps/mjt/keymap.c4
-rw-r--r--keyboards/mitosis/keymaps/nzen/keymap.c4
-rw-r--r--keyboards/mlego/m48/keymaps/default/keymap.c8
-rw-r--r--keyboards/mschwingen/modelm/modelm.c4
-rw-r--r--keyboards/mwstudio/mw65_rgb/keymaps/via/keymap.c4
-rw-r--r--keyboards/pearl/keymaps/cijanzen/keymap.c2
-rw-r--r--keyboards/pearl/keymaps/jetpacktuxedo/keymap.c2
-rwxr-xr-xkeyboards/pearl/keymaps/phil/keymap.c2
-rw-r--r--keyboards/pearl/keymaps/rask/keymap.c2
-rw-r--r--keyboards/percent/canoe/keymaps/dhertz/keymap.c4
-rw-r--r--keyboards/phoenix/phoenix.c2
-rw-r--r--keyboards/planck/keymaps/ariccb/config.h1
-rw-r--r--keyboards/planck/keymaps/ariccb/keymap.c13
-rw-r--r--keyboards/planck/keymaps/aviator/keymap.c8
-rw-r--r--keyboards/planck/keymaps/charlesrocket/keymap.c2
-rw-r--r--keyboards/planck/keymaps/default/keymap.c2
-rw-r--r--keyboards/planck/keymaps/grahampheath/keymap.c2
-rw-r--r--keyboards/planck/keymaps/oryx/keymap.c2
-rw-r--r--keyboards/planck/keymaps/roguepullrequest/rules.mk1
-rw-r--r--keyboards/planck/keymaps/rootiest/config.h1
-rw-r--r--keyboards/planck/keymaps/rootiest/keymap.c25
-rw-r--r--keyboards/planck/keymaps/rootiest/rules.mk3
-rw-r--r--keyboards/planck/keymaps/synth_sample/keymap.c8
-rw-r--r--keyboards/planck/keymaps/synth_wavetable/keymap.c8
-rw-r--r--keyboards/planck/keymaps/tom/keymap.c2
-rw-r--r--keyboards/planck/keymaps/tylerwince/keymap.c4
-rw-r--r--keyboards/ploopyco/mouse/keymaps/drashna/config.h2
-rw-r--r--keyboards/preonic/keymaps/default/keymap.c2
-rw-r--r--keyboards/preonic/keymaps/dudeofawesome/keymap.c2
-rw-r--r--keyboards/preonic/keymaps/senseored/keymap.c2
-rw-r--r--keyboards/primekb/prime_e/keymaps/via/keymap.c2
-rw-r--r--keyboards/redox_w/keymaps/italian/keymap.c12
-rw-r--r--keyboards/redscarf_i/redscarf_i.c2
-rw-r--r--keyboards/rgbkb/pan/keymaps/default/keymap.c2
-rw-r--r--keyboards/rgbkb/sol/keymaps/default/keymap.c4
-rw-r--r--keyboards/rgbkb/sol/keymaps/xyverz/keymap.c4
-rw-r--r--keyboards/rgbkb/zen/rev2/rev2.c2
-rw-r--r--keyboards/rgbkb/zygomorph/keymaps/default_oled/keymap.c2
-rw-r--r--keyboards/salicylic_acid3/7skb/keymaps/salicylic/keymap.c4
-rw-r--r--keyboards/salicylic_acid3/7splus/keymaps/salicylic/keymap.c4
-rw-r--r--keyboards/salicylic_acid3/jisplit89/keymaps/salicylic/keymap.c4
-rw-r--r--keyboards/salicylic_acid3/naked60/keymaps/salicylic/keymap.c4
-rw-r--r--keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_nafuda/keymap.c4
-rw-r--r--keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_setta21/keymap.c4
-rw-r--r--keyboards/salicylic_acid3/naked64/keymaps/salicylic/keymap.c4
-rw-r--r--keyboards/salicylic_acid3/naked64/keymaps/salicylic_with_setta21/keymap.c4
-rw-r--r--keyboards/satt/comet46/keymaps/default-rgbled/keymap.c2
-rw-r--r--keyboards/satt/comet46/keymaps/default/keymap.c4
-rw-r--r--keyboards/satt/comet46/keymaps/satt/keymap.c4
-rw-r--r--keyboards/splitkb/kyria/keymaps/j-inc/keymap.c2
-rw-r--r--keyboards/splitkb/kyria/keymaps/j-inc/rules.mk1
-rw-r--r--keyboards/splitkb/kyria/keymaps/ninjonas/oled.c2
-rw-r--r--keyboards/splitkb/kyria/keymaps/thomasbaart/keymap.c4
-rw-r--r--keyboards/splitography/keymaps/jeandeaual/keymap.c2
-rw-r--r--keyboards/splitography/keymaps/multi/keymap.c2
-rwxr-xr-xkeyboards/tetris/keymaps/default/keymap.c4
-rw-r--r--keyboards/thevankeyboards/minivan/keymaps/belak/config.h1
-rw-r--r--keyboards/thevankeyboards/minivan/keymaps/belak/keymap.c21
-rw-r--r--keyboards/thevankeyboards/minivan/keymaps/halvves/config.h1
-rw-r--r--keyboards/thevankeyboards/roadkit/keymaps/flipphone/keymap.c2
-rw-r--r--keyboards/tzarc/djinn/djinn.c2
-rw-r--r--keyboards/v60_type_r/keymaps/xtonhasvim/keymap.c3
-rw-r--r--keyboards/woodkeys/bigseries/1key/keymaps/dudeofawesome/config.h1
-rw-r--r--keyboards/work_louder/work_board/keymaps/default/keymap.c6
-rw-r--r--keyboards/xiudi/xd002/keymaps/tap_dance/config.h1
-rw-r--r--keyboards/xiudi/xd60/keymaps/birkir/keymap.c2
-rw-r--r--keyboards/xiudi/xd60/keymaps/kmontag42/keymap.c2
-rw-r--r--keyboards/xiudi/xd75/keymaps/arpinfidel/keymap.c2
-rw-r--r--keyboards/xiudi/xd75/keymaps/cbbrowne/keymap.c2
-rw-r--r--keyboards/xiudi/xd75/keymaps/kloki/keymap.c2
-rw-r--r--keyboards/xiudi/xd75/keymaps/tdl-jturner/keymap.c2
-rw-r--r--keyboards/zfrontier/big_switch/config.h1
-rw-r--r--layouts/community/66_ansi/xyverz/config.h1
-rw-r--r--layouts/community/ergodox/ab/keymap.c2
-rw-r--r--layouts/community/ergodox/absenth/keymap.c2
-rw-r--r--layouts/community/ergodox/adam/config.h2
-rw-r--r--layouts/community/ergodox/adam/keymap.c2
-rw-r--r--layouts/community/ergodox/adnw_k_o_y/keymap.c2
-rw-r--r--layouts/community/ergodox/alexjj/keymap.c2
-rw-r--r--layouts/community/ergodox/andrew_osx/keymap.c2
-rw-r--r--layouts/community/ergodox/berfarah/keymap.c4
-rw-r--r--layouts/community/ergodox/bryan/keymap.c2
-rw-r--r--layouts/community/ergodox/choromanski/keymap.c42
-rw-r--r--layouts/community/ergodox/colemak/keymap.c2
-rw-r--r--layouts/community/ergodox/colemak_code_friendly/keymap.c20
-rw-r--r--layouts/community/ergodox/colemak_programmer/keymap.c8
-rw-r--r--layouts/community/ergodox/common_nighthawk/keymap.c2
-rw-r--r--layouts/community/ergodox/csharp_dev/keymap.c40
-rw-r--r--layouts/community/ergodox/dave/keymap.c2
-rw-r--r--layouts/community/ergodox/deadcyclo/keymap.c16
-rw-r--r--layouts/community/ergodox/dragon788/keymap.c2
-rw-r--r--layouts/community/ergodox/dvorak/keymap.c2
-rw-r--r--layouts/community/ergodox/dvorak_emacs/keymap.c2
-rw-r--r--layouts/community/ergodox/dvorak_emacs_software/keymap.c2
-rw-r--r--layouts/community/ergodox/dvorak_intl_squisher/keymap.c2
-rw-r--r--layouts/community/ergodox/dvorak_plover/keymap.c2
-rw-r--r--layouts/community/ergodox/dvorak_programmer/keymap.c68
-rw-r--r--layouts/community/ergodox/dvorak_programmer_swe/keymap.c2
-rw-r--r--layouts/community/ergodox/dvorak_spanish/keymap.c43
-rw-r--r--layouts/community/ergodox/dvorak_svorak_a5/keymap.c2
-rw-r--r--layouts/community/ergodox/emacs_osx_dk/keymap.c2
-rw-r--r--layouts/community/ergodox/french_hacker/keymap.c2
-rw-r--r--layouts/community/ergodox/galson/keymap.c4
-rw-r--r--layouts/community/ergodox/german-kinergo/keymap.c2
-rw-r--r--layouts/community/ergodox/german-lukas/keymap.c2
-rw-r--r--layouts/community/ergodox/german-manuneo/compile_keymap.py110
-rw-r--r--layouts/community/ergodox/german-manuneo/keymap.c2
-rw-r--r--layouts/community/ergodox/german/keymap.c2
-rw-r--r--layouts/community/ergodox/haegin/keymap.c2
-rw-r--r--layouts/community/ergodox/ishigoya-jp/keymap.c78
-rw-r--r--layouts/community/ergodox/issmirnov/keymap.c6
-rw-r--r--layouts/community/ergodox/italian/keymap.c4
-rw-r--r--layouts/community/ergodox/j3rn/keymap.c2
-rw-r--r--layouts/community/ergodox/jackhumbert/keymap.c14
-rw-r--r--layouts/community/ergodox/jacobono/keymap.c2
-rw-r--r--layouts/community/ergodox/jafo/keymap.c2
-rw-r--r--layouts/community/ergodox/jgarr/keymap.c2
-rw-r--r--layouts/community/ergodox/josh/keymap.c2
-rw-r--r--layouts/community/ergodox/kastyle/keymap.c4
-rw-r--r--layouts/community/ergodox/kejadlen/keymap.c2
-rw-r--r--layouts/community/ergodox/kines-ish/keymap.c2
-rw-r--r--layouts/community/ergodox/kristian/keymap.c2
-rw-r--r--layouts/community/ergodox/maz/keymap.c2
-rw-r--r--layouts/community/ergodox/mclennon_osx/keymap.c2
-rw-r--r--layouts/community/ergodox/meagerfindings/keymap.c2
-rw-r--r--layouts/community/ergodox/msc/keymap.c2
-rw-r--r--layouts/community/ergodox/naps62/keymap.c2
-rw-r--r--layouts/community/ergodox/neo2_on_qwertz_hardware/keymap.c4
-rw-r--r--layouts/community/ergodox/osx_de/keymap.c197
-rw-r--r--layouts/community/ergodox/osx_de_adnw_koy/keymap.c153
-rw-r--r--layouts/community/ergodox/osx_de_experimental/keymap.c555
-rw-r--r--layouts/community/ergodox/osx_fr/keymap.c2
-rw-r--r--layouts/community/ergodox/osx_kinesis_pnut/keymap.c2
-rw-r--r--layouts/community/ergodox/osx_neo2/keymap.c2
-rw-r--r--layouts/community/ergodox/phoenix/keymap.c2
-rw-r--r--layouts/community/ergodox/plover/keymap.c2
-rw-r--r--layouts/community/ergodox/qwerty_code_friendly/keymap.c2
-rw-r--r--layouts/community/ergodox/reset_eeprom/keymap.c2
-rw-r--r--layouts/community/ergodox/romanzolotarev-norman-plover-osx-hjkl/keymap.c2
-rw-r--r--layouts/community/ergodox/romanzolotarev-norman-plover-osx/keymap.c2
-rw-r--r--layouts/community/ergodox/romanzolotarev-norman-qwerty-osx/keymap.c2
-rw-r--r--layouts/community/ergodox/sethbc/keymap.c2
-rw-r--r--layouts/community/ergodox/siroken3/keymap.c2
-rw-r--r--layouts/community/ergodox/sneako/keymap.c2
-rw-r--r--layouts/community/ergodox/software_neo2/keymap.c2
-rw-r--r--layouts/community/ergodox/swedish-lindhe/keymap.c2
-rw-r--r--layouts/community/ergodox/swedish/keymap.c2
-rw-r--r--layouts/community/ergodox/swissgerman/keymap.c2
-rw-r--r--layouts/community/ergodox/techtomas/keymap.c2
-rw-r--r--layouts/community/ergodox/tkuichooseyou/keymap.c2
-rw-r--r--layouts/community/ergodox/tonyabra_osx/keymap.c2
-rw-r--r--layouts/community/ergodox/townk_osx/keymap.c2
-rw-r--r--layouts/community/ergodox/twentylives_dvorak_with_hebrew/keymap.c22
-rw-r--r--layouts/community/ergodox/win10_writers-block/keymap.c28
-rw-r--r--layouts/community/ergodox/xyverz/keymap.c6
-rw-r--r--layouts/community/ergodox/zweihander-macos/keymap.c2
-rw-r--r--layouts/community/ortho_4x12/peej/keymap.c2
m---------lib/chibios0
-rw-r--r--lib/fnv/Makefile304
-rw-r--r--lib/fnv/README158
-rw-r--r--lib/fnv/fnv.h249
-rw-r--r--lib/fnv/fnv32.c467
-rw-r--r--lib/fnv/fnv64.c591
-rw-r--r--lib/fnv/hash_32.c156
-rw-r--r--lib/fnv/hash_32a.c144
-rw-r--r--lib/fnv/hash_64.c312
-rw-r--r--lib/fnv/hash_64a.c291
-rw-r--r--lib/fnv/have_ulong64.c58
-rw-r--r--lib/fnv/longlong.h18
-rw-r--r--lib/fnv/qmk_fnv_type_validation.c14
-rw-r--r--lib/fnv/test_fnv.c2237
m---------lib/lufa0
m---------lib/pico-sdk0
-rw-r--r--lib/python/qmk/cli/doctor/macos.py2
-rw-r--r--lib/python/qmk/cli/flash.py2
-rwxr-xr-xlib/python/qmk/cli/generate/config_h.py29
-rwxr-xr-xlib/python/qmk/cli/generate/info_json.py8
-rw-r--r--lib/python/qmk/constants.py2
-rw-r--r--lib/python/qmk/git.py4
-rw-r--r--lib/python/qmk/info.py58
-rw-r--r--lib/python/qmk/json_schema.py6
m---------lib/vusb0
-rw-r--r--platforms/arm_atsam/platform.mk2
-rw-r--r--platforms/avr/drivers/i2c_master.c12
-rw-r--r--platforms/avr/drivers/ps2/ps2_usart.c4
-rw-r--r--platforms/avr/platform.mk2
-rw-r--r--platforms/chibios/_pin_defs.h5
-rw-r--r--platforms/chibios/boards/GENERIC_PROMICRO_RP2040/board/board.mk9
-rw-r--r--platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/board.h12
-rw-r--r--platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/chconf.h13
-rw-r--r--platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h62
-rw-r--r--platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/mcuconf.h98
-rw-r--r--platforms/chibios/boards/GENERIC_RP_RP2040/board/board.mk9
-rw-r--r--platforms/chibios/boards/GENERIC_RP_RP2040/configs/board.h12
-rw-r--r--platforms/chibios/boards/GENERIC_RP_RP2040/configs/chconf.h13
-rw-r--r--platforms/chibios/boards/GENERIC_RP_RP2040/configs/mcuconf.h98
-rw-r--r--platforms/chibios/boards/common/ld/RP2040_FLASH_TIMECRIT.ld117
-rw-r--r--platforms/chibios/boards/common/ld/RP2040_rules_data_with_timecrit.ld46
-rw-r--r--platforms/chibios/bootloaders/rp2040.c57
-rw-r--r--platforms/chibios/bootloaders/stm32_dfu.c4
-rw-r--r--platforms/chibios/chibios_config.h21
-rw-r--r--platforms/chibios/drivers/eeprom/eeprom_stm32.c (renamed from platforms/chibios/eeprom_stm32.c)0
-rw-r--r--platforms/chibios/drivers/eeprom/eeprom_stm32.h (renamed from platforms/chibios/eeprom_stm32.h)0
-rw-r--r--platforms/chibios/drivers/eeprom/eeprom_stm32_defs.h (renamed from platforms/chibios/eeprom_stm32_defs.h)0
-rw-r--r--platforms/chibios/drivers/eeprom/eeprom_teensy.c (renamed from platforms/chibios/eeprom_teensy.c)0
-rwxr-xr-xplatforms/chibios/drivers/eeprom/eeprom_teensy.h (renamed from platforms/chibios/eeprom_teensy.h)0
-rw-r--r--platforms/chibios/drivers/flash/flash_stm32.c (renamed from platforms/chibios/flash_stm32.c)0
-rw-r--r--platforms/chibios/drivers/flash/flash_stm32.h (renamed from platforms/chibios/flash_stm32.h)0
-rw-r--r--platforms/chibios/drivers/serial.c15
-rw-r--r--platforms/chibios/drivers/serial_protocol.c164
-rw-r--r--platforms/chibios/drivers/serial_protocol.h49
-rw-r--r--platforms/chibios/drivers/serial_usart.c322
-rw-r--r--platforms/chibios/drivers/serial_usart.h118
-rw-r--r--platforms/chibios/drivers/spi_master.c31
-rw-r--r--platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c457
-rw-r--r--platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c189
-rw-r--r--platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c140
-rw-r--r--platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h50
-rw-r--r--platforms/chibios/drivers/wear_leveling/wear_leveling_legacy.c59
-rw-r--r--platforms/chibios/drivers/wear_leveling/wear_leveling_legacy_config.h67
-rw-r--r--platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c221
-rw-r--r--platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash_config.h32
-rw-r--r--platforms/chibios/flash.mk10
-rw-r--r--platforms/chibios/platform.mk24
-rw-r--r--platforms/chibios/vendors/RP/RP2040.mk287
-rw-r--r--platforms/chibios/vendors/RP/_pin_defs.h37
-rw-r--r--platforms/chibios/vendors/RP/pico_sdk_shims.c13
-rw-r--r--platforms/chibios/vendors/RP/stage2_bootloaders.c178
-rw-r--r--platforms/eeprom.h2
-rw-r--r--platforms/synchronization_util.h34
-rw-r--r--platforms/test/platform.mk2
-rw-r--r--platforms/test/rules.mk5
-rw-r--r--quantum/action.c2
-rw-r--r--quantum/action_layer.h2
-rw-r--r--quantum/action_tapping.c12
-rw-r--r--quantum/audio/song_list.h6
-rw-r--r--quantum/keyboard.c2
-rw-r--r--quantum/keymap.h7
-rw-r--r--quantum/keymap_extras/keymap_steno.h28
-rw-r--r--quantum/keymap_introspection.c25
-rw-r--r--quantum/keymap_introspection.h15
-rw-r--r--quantum/mousekey.c27
-rw-r--r--quantum/mousekey.h4
-rw-r--r--quantum/painter/qp.h4
-rw-r--r--quantum/painter/rules.mk13
-rw-r--r--quantum/pointing_device.c38
-rw-r--r--quantum/pointing_device.h10
-rw-r--r--quantum/pointing_device_drivers.c99
-rw-r--r--quantum/process_keycode/process_steno.c312
-rw-r--r--quantum/process_keycode/process_steno.h24
-rw-r--r--quantum/process_keycode/process_tap_dance.c137
-rw-r--r--quantum/process_keycode/process_tap_dance.h33
-rw-r--r--quantum/process_keycode/process_terminal.c330
-rw-r--r--quantum/quantum.c3
-rw-r--r--quantum/quantum.h6
-rw-r--r--quantum/quantum_keycodes.h6
-rw-r--r--quantum/quantum_keycodes_legacy.h3
-rw-r--r--quantum/rgb_matrix/animations/typing_heatmap_anim.h88
-rw-r--r--quantum/rgb_matrix/rgb_matrix.c11
-rw-r--r--quantum/split_common/split_util.c12
-rw-r--r--quantum/via.c21
-rw-r--r--quantum/wear_leveling/tests/backing_mocks.cpp154
-rw-r--r--quantum/wear_leveling/tests/backing_mocks.hpp210
-rw-r--r--quantum/wear_leveling/tests/rules.mk66
-rw-r--r--quantum/wear_leveling/tests/testlist.mk6
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_2byte.cpp228
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp295
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_4byte.cpp193
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_8byte.cpp178
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_general.cpp204
-rw-r--r--quantum/wear_leveling/wear_leveling.c768
-rw-r--r--quantum/wear_leveling/wear_leveling.h54
-rw-r--r--quantum/wear_leveling/wear_leveling_internal.h151
-rw-r--r--readme.md4
-rw-r--r--tests/tap_dance/config.h (renamed from quantum/process_keycode/process_terminal_nop.h)7
-rw-r--r--tests/tap_dance/examples.c199
-rw-r--r--tests/tap_dance/examples.h (renamed from quantum/process_keycode/process_terminal.h)21
-rw-r--r--tests/tap_dance/test.mk22
-rw-r--r--tests/tap_dance/test_examples.cpp319
-rw-r--r--tmk_core/protocol/arm_atsam/md_rgb_matrix.c2
-rw-r--r--tmk_core/protocol/chibios/usb_main.c106
-rw-r--r--tmk_core/protocol/host.c5
-rw-r--r--tmk_core/protocol/report.h18
-rw-r--r--tmk_core/protocol/usb_descriptor.c15
-rw-r--r--tmk_core/protocol/vusb/vusb.c16
-rw-r--r--users/333fred/333fred.c2
-rw-r--r--users/333fred/rgb.c4
-rw-r--r--users/bbaserdem/bbaserdem.c4
-rw-r--r--users/bcat/rules.mk1
-rw-r--r--users/billypython/billypython.c2
-rw-r--r--users/billypython/billypython.h2
-rw-r--r--users/dhertz/dhertz.c3
-rw-r--r--users/doogle999/doogle999.c6
-rw-r--r--users/edvorakjp/edvorakjp.c2
-rw-r--r--users/edvorakjp/edvorakjp.h2
-rw-r--r--users/edvorakjp/edvorakjp_tap_dance.c13
-rwxr-xr-xusers/ericgebhart/ericgebhart.c2
-rwxr-xr-xusers/ericgebhart/tap_dances.c4
-rw-r--r--users/gourdo1/gourdo1.c2
-rw-r--r--users/hvp/config.h3
-rw-r--r--users/kuchosauronad0/kuchosauronad0.c6
-rw-r--r--users/kuchosauronad0/kuchosauronad0.h4
-rw-r--r--users/kuchosauronad0/rgblight_user.c20
-rw-r--r--users/kuchosauronad0/template.c4
-rw-r--r--users/mnil/config.h1
-rw-r--r--users/mnil/mnil.c4
-rw-r--r--users/mtdjr/mtdjr.c2
-rw-r--r--users/ninjonas/config.h3
-rw-r--r--users/ninjonas/oled.c2
-rw-r--r--users/ninjonas/tap_dances.c16
-rw-r--r--users/pvinis/pvinis.c2
-rw-r--r--users/pvinis/pvinis.h2
-rw-r--r--users/romus/romus.c4
-rw-r--r--users/sigma/sigma.c4
-rw-r--r--users/stanrc85/layer_rgb.c2
-rw-r--r--users/talljoe/talljoe.c2
-rw-r--r--users/tominabox1/tominabox1.c4
-rw-r--r--users/turbomech/backupturbomech.c6
-rw-r--r--users/xulkal/custom_oled.c2
-rw-r--r--users/zer09/zer09.c2
-rwxr-xr-xutil/uf2conv.py3
-rwxr-xr-xutil/update_chibios_mirror.sh2
594 files changed, 15023 insertions, 3322 deletions
diff --git a/.gitmodules b/.gitmodules
index 681693a5a4..48c7035afa 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -18,3 +18,6 @@
[submodule "lib/printf"]
path = lib/printf
url = https://github.com/qmk/printf
+[submodule "lib/pico-sdk"]
+ path = lib/pico-sdk
+ url = https://github.com/qmk/pico-sdk.git
diff --git a/Makefile b/Makefile
index 4c2e6a04dc..fc6d016448 100644
--- a/Makefile
+++ b/Makefile
@@ -401,6 +401,7 @@ ifndef SKIP_GIT
if [ ! -e lib/lufa ]; then git submodule sync lib/lufa && git submodule update --depth 50 --init lib/lufa; fi
if [ ! -e lib/vusb ]; then git submodule sync lib/vusb && git submodule update --depth 50 --init lib/vusb; fi
if [ ! -e lib/printf ]; then git submodule sync lib/printf && git submodule update --depth 50 --init lib/printf; fi
+ if [ ! -e lib/pico-sdk ]; then git submodule sync lib/pico-sdk && git submodule update --depth 50 --init lib/pico-sdk; fi
git submodule status --recursive 2>/dev/null | \
while IFS= read -r x; do \
case "$$x" in \
diff --git a/builddefs/bootloader.mk b/builddefs/bootloader.mk
index eba8e280e4..3d4c03b01c 100644
--- a/builddefs/bootloader.mk
+++ b/builddefs/bootloader.mk
@@ -200,6 +200,10 @@ ifeq ($(strip $(BOOTLOADER)), tinyuf2)
OPT_DEFS += -DBOOTLOADER_TINYUF2
BOOTLOADER_TYPE = tinyuf2
endif
+ifeq ($(strip $(BOOTLOADER)), rp2040)
+ OPT_DEFS += -DBOOTLOADER_RP2040
+ BOOTLOADER_TYPE = rp2040
+endif
ifeq ($(strip $(BOOTLOADER)), halfkay)
OPT_DEFS += -DBOOTLOADER_HALFKAY
BOOTLOADER_TYPE = halfkay
diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk
index dc86b232df..b5616a438f 100644
--- a/builddefs/build_keyboard.mk
+++ b/builddefs/build_keyboard.mk
@@ -13,6 +13,14 @@ endif
include paths.mk
include $(BUILDDEFS_PATH)/message.mk
+# Helper to add defines with a 'QMK_' prefix
+define add_qmk_prefix_defs
+ ifdef $1
+ # Need to cater for 'STM32L4xx+'
+ OPT_DEFS += -DQMK_$(2)="$($1)" -DQMK_$(2)_$(shell echo $($1) | sed -e 's@+@Plus@g' -e 's@[^a-zA-Z0-9]@_@g' | tr '[:lower:]' '[:upper:]')
+ endif
+endef
+
# Set the qmk cli to use
QMK_BIN ?= qmk
@@ -390,10 +398,12 @@ ifneq ("$(KEYMAP_H)","")
CONFIG_H += $(KEYMAP_H)
endif
+OPT_DEFS += -DKEYMAP_C=\"$(KEYMAP_C)\"
+
# project specific files
SRC += \
$(KEYBOARD_SRC) \
- $(KEYMAP_C) \
+ $(QUANTUM_DIR)/keymap_introspection.c \
$(QUANTUM_SRC) \
$(QUANTUM_DIR)/main.c \
@@ -436,6 +446,14 @@ else
include $(TMK_PATH)/protocol/$(PLATFORM_KEY).mk
endif
+# Setup definitions based on the selected MCU
+$(eval $(call add_qmk_prefix_defs,MCU_ORIG,MCU))
+$(eval $(call add_qmk_prefix_defs,MCU_ARCH,MCU_ARCH))
+$(eval $(call add_qmk_prefix_defs,MCU_PORT_NAME,MCU_PORT_NAME))
+$(eval $(call add_qmk_prefix_defs,MCU_FAMILY,MCU_FAMILY))
+$(eval $(call add_qmk_prefix_defs,MCU_SERIES,MCU_SERIES))
+$(eval $(call add_qmk_prefix_defs,BOARD,BOARD))
+
# TODO: remove this bodge?
PROJECT_DEFS := $(OPT_DEFS)
PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYBOARD_PATHS)
@@ -469,6 +487,19 @@ check-size: build
check-md5: build
objs-size: build
+ifeq ($(strip $(TOP_SYMBOLS)),yes)
+all: top-symbols
+check-size: top-symbols
+top-symbols: build
+ echo "###########################################"
+ echo "# Highest flash usage:"
+ $(NM) -Crtd --size-sort $(BUILD_DIR)/$(TARGET).elf | grep -i ' [t] ' | head -n10 | sed -e 's#^0000000# #g' -e 's#^000000# #g' -e 's#^00000# #g' -e 's#^0000# #g' -e 's#^000# #g' -e 's#^00# #g' -e 's#^0# #g'
+ echo "###########################################"
+ echo "# Highest RAM usage:"
+ $(NM) -Crtd --size-sort $(BUILD_DIR)/$(TARGET).elf | grep -i ' [dbv] ' | head -n10 | sed -e 's#^0000000# #g' -e 's#^000000# #g' -e 's#^00000# #g' -e 's#^0000# #g' -e 's#^000# #g' -e 's#^00# #g' -e 's#^0# #g'
+ echo "###########################################"
+endif
+
include $(BUILDDEFS_PATH)/show_options.mk
include $(BUILDDEFS_PATH)/common_rules.mk
diff --git a/builddefs/build_test.mk b/builddefs/build_test.mk
index 5ad33b19c5..bd9b372c33 100644
--- a/builddefs/build_test.mk
+++ b/builddefs/build_test.mk
@@ -42,7 +42,7 @@ VPATH += \
all: elf
-VPATH += $(COMMON_VPATH)
+VPATH += $(TEST_PATH) $(COMMON_VPATH)
PLATFORM:=TEST
PLATFORM_KEY:=test
BOOTLOADER_TYPE:=none
@@ -63,6 +63,7 @@ include $(TMK_PATH)/protocol.mk
include $(QUANTUM_PATH)/debounce/tests/rules.mk
include $(QUANTUM_PATH)/encoder/tests/rules.mk
include $(QUANTUM_PATH)/sequencer/tests/rules.mk
+include $(QUANTUM_PATH)/wear_leveling/tests/rules.mk
include $(PLATFORM_PATH)/test/rules.mk
ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include $(BUILDDEFS_PATH)/build_full_test.mk
diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk
index c976b8296d..c11e5688e3 100644
--- a/builddefs/common_features.mk
+++ b/builddefs/common_features.mk
@@ -92,10 +92,29 @@ ifeq ($(MUSIC_ENABLE), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_music.c
endif
+VALID_STENO_PROTOCOL_TYPES := geminipr txbolt all
+STENO_PROTOCOL ?= all
ifeq ($(strip $(STENO_ENABLE)), yes)
- OPT_DEFS += -DSTENO_ENABLE
- VIRTSER_ENABLE ?= yes
- SRC += $(QUANTUM_DIR)/process_keycode/process_steno.c
+ ifeq ($(filter $(STENO_PROTOCOL),$(VALID_STENO_PROTOCOL_TYPES)),)
+ $(call CATASTROPHIC_ERROR,Invalid STENO_PROTOCOL,STENO_PROTOCOL="$(STENO_PROTOCOL)" is not a valid stenography protocol)
+ else
+ OPT_DEFS += -DSTENO_ENABLE
+ VIRTSER_ENABLE ?= yes
+
+ ifeq ($(strip $(STENO_PROTOCOL)), geminipr)
+ OPT_DEFS += -DSTENO_ENABLE_GEMINI
+ endif
+ ifeq ($(strip $(STENO_PROTOCOL)), txbolt)
+ OPT_DEFS += -DSTENO_ENABLE_BOLT
+ endif
+ ifeq ($(strip $(STENO_PROTOCOL)), all)
+ OPT_DEFS += -DSTENO_ENABLE_ALL
+ OPT_DEFS += -DSTENO_ENABLE_GEMINI
+ OPT_DEFS += -DSTENO_ENABLE_BOLT
+ endif
+
+ SRC += $(QUANTUM_DIR)/process_keycode/process_steno.c
+ endif
endif
ifeq ($(strip $(VIRTSER_ENABLE)), yes)
@@ -154,33 +173,36 @@ ifeq ($(strip $(QUANTUM_PAINTER_ENABLE)), yes)
include $(QUANTUM_DIR)/painter/rules.mk
endif
-VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c spi
+VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c spi wear_leveling
EEPROM_DRIVER ?= vendor
ifeq ($(filter $(EEPROM_DRIVER),$(VALID_EEPROM_DRIVER_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid EEPROM_DRIVER,EEPROM_DRIVER="$(EEPROM_DRIVER)" is not a valid EEPROM driver)
else
OPT_DEFS += -DEEPROM_ENABLE
+ COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/eeprom
+ COMMON_VPATH += $(DRIVER_PATH)/eeprom
+ COMMON_VPATH += $(PLATFORM_COMMON_DIR)
ifeq ($(strip $(EEPROM_DRIVER)), custom)
# Custom EEPROM implementation -- only needs to implement init/erase/read_block/write_block
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_CUSTOM
- COMMON_VPATH += $(DRIVER_PATH)/eeprom
SRC += eeprom_driver.c
+ else ifeq ($(strip $(EEPROM_DRIVER)), wear_leveling)
+ # Wear-leveling EEPROM implementation
+ OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_WEAR_LEVELING
+ SRC += eeprom_driver.c eeprom_wear_leveling.c
else ifeq ($(strip $(EEPROM_DRIVER)), i2c)
# External I2C EEPROM implementation
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_I2C
- COMMON_VPATH += $(DRIVER_PATH)/eeprom
QUANTUM_LIB_SRC += i2c_master.c
SRC += eeprom_driver.c eeprom_i2c.c
else ifeq ($(strip $(EEPROM_DRIVER)), spi)
# External SPI EEPROM implementation
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_SPI
- COMMON_VPATH += $(DRIVER_PATH)/eeprom
QUANTUM_LIB_SRC += spi_master.c
SRC += eeprom_driver.c eeprom_spi.c
else ifeq ($(strip $(EEPROM_DRIVER)), transient)
# Transient EEPROM implementation -- no data storage but provides runtime area for it
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT
- COMMON_VPATH += $(DRIVER_PATH)/eeprom
SRC += eeprom_driver.c eeprom_transient.c
else ifeq ($(strip $(EEPROM_DRIVER)), vendor)
# Vendor-implemented EEPROM
@@ -191,17 +213,18 @@ else
ifneq ($(filter STM32F3xx_% STM32F1xx_% %_STM32F401xC %_STM32F401xE %_STM32F405xG %_STM32F411xE %_STM32F072xB %_STM32F042x6 %_GD32VF103xB %_GD32VF103x8, $(MCU_SERIES)_$(MCU_LDSCRIPT)),)
# Emulated EEPROM
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_STM32_FLASH_EMULATED
- COMMON_VPATH += $(DRIVER_PATH)/eeprom
- SRC += eeprom_driver.c
- SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
- SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
+ COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/flash
+ COMMON_VPATH += $(DRIVER_PATH)/flash
+ SRC += eeprom_driver.c eeprom_stm32.c flash_stm32.c
else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),)
# True EEPROM on STM32L0xx, L1xx
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_STM32_L0_L1
- COMMON_VPATH += $(DRIVER_PATH)/eeprom
- COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/eeprom
- SRC += eeprom_driver.c
- SRC += eeprom_stm32_L0_L1.c
+ SRC += eeprom_driver.c eeprom_stm32_L0_L1.c
+ else ifneq ($(filter $(MCU_SERIES),RP2040),)
+ # Wear-leveling EEPROM implementation, backed by RP2040 flash
+ OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_WEAR_LEVELING
+ SRC += eeprom_driver.c eeprom_wear_leveling.c
+ WEAR_LEVELING_DRIVER = rp2040_flash
else ifneq ($(filter $(MCU_SERIES),KL2x K20x),)
# Teensy EEPROM implementations
OPT_DEFS += -DEEPROM_TEENSY
@@ -209,32 +232,64 @@ else
else
# Fall back to transient, i.e. non-persistent
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT
- COMMON_VPATH += $(DRIVER_PATH)/eeprom
SRC += eeprom_driver.c eeprom_transient.c
endif
else ifeq ($(PLATFORM),ARM_ATSAM)
# arm_atsam EEPROM
OPT_DEFS += -DEEPROM_SAMD
- SRC += $(PLATFORM_COMMON_DIR)/eeprom_samd.c
+ SRC += eeprom_samd.c
else ifeq ($(PLATFORM),TEST)
# Test harness "EEPROM"
OPT_DEFS += -DEEPROM_TEST_HARNESS
- SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
+ SRC += eeprom.c
+ endif
+ endif
+endif
+
+VALID_WEAR_LEVELING_DRIVER_TYPES := custom embedded_flash spi_flash rp2040_flash legacy
+WEAR_LEVELING_DRIVER ?= none
+ifneq ($(strip $(WEAR_LEVELING_DRIVER)),none)
+ ifeq ($(filter $(WEAR_LEVELING_DRIVER),$(VALID_WEAR_LEVELING_DRIVER_TYPES)),)
+ $(call CATASTROPHIC_ERROR,Invalid WEAR_LEVELING_DRIVER,WEAR_LEVELING_DRIVER="$(WEAR_LEVELING_DRIVER)" is not a valid wear leveling driver)
+ else
+ FNV_ENABLE := yes
+ OPT_DEFS += -DWEAR_LEVELING_ENABLE
+ OPT_DEFS += -DWEAR_LEVELING_$(strip $(shell echo $(WEAR_LEVELING_DRIVER) | tr '[:lower:]' '[:upper:]'))
+ COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/wear_leveling
+ COMMON_VPATH += $(DRIVER_PATH)/wear_leveling
+ COMMON_VPATH += $(QUANTUM_DIR)/wear_leveling
+ SRC += wear_leveling.c
+ ifeq ($(strip $(WEAR_LEVELING_DRIVER)), embedded_flash)
+ OPT_DEFS += -DHAL_USE_EFL
+ SRC += wear_leveling_efl.c
+ POST_CONFIG_H += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/wear_leveling/wear_leveling_efl_config.h
+ else ifeq ($(strip $(WEAR_LEVELING_DRIVER)), spi_flash)
+ FLASH_DRIVER := spi
+ SRC += wear_leveling_flash_spi.c
+ POST_CONFIG_H += $(DRIVER_PATH)/wear_leveling/wear_leveling_flash_spi_config.h
+ else ifeq ($(strip $(WEAR_LEVELING_DRIVER)), rp2040_flash)
+ SRC += wear_leveling_rp2040_flash.c
+ POST_CONFIG_H += $(DRIVER_PATH)/wear_leveling/wear_leveling_rp2040_flash_config.h
+ else ifeq ($(strip $(WEAR_LEVELING_DRIVER)), legacy)
+ COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/flash
+ SRC += flash_stm32.c wear_leveling_legacy.c
+ POST_CONFIG_H += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/wear_leveling/wear_leveling_legacy_config.h
endif
endif
endif
VALID_FLASH_DRIVER_TYPES := spi
-FLASH_DRIVER ?= no
-ifneq ($(strip $(FLASH_DRIVER)), no)
+FLASH_DRIVER ?= none
+ifneq ($(strip $(FLASH_DRIVER)), none)
ifeq ($(filter $(FLASH_DRIVER),$(VALID_FLASH_DRIVER_TYPES)),)
- $(error FLASH_DRIVER="$(FLASH_DRIVER)" is not a valid FLASH driver)
+ $(call CATASTROPHIC_ERROR,Invalid FLASH_DRIVER,FLASH_DRIVER="$(FLASH_DRIVER)" is not a valid flash driver)
else
OPT_DEFS += -DFLASH_ENABLE
- ifeq ($(strip $(FLASH_DRIVER)), spi)
+ ifeq ($(strip $(FLASH_DRIVER)),spi)
OPT_DEFS += -DFLASH_DRIVER -DFLASH_SPI
COMMON_VPATH += $(DRIVER_PATH)/flash
SRC += flash_spi.c
+ QUANTUM_LIB_SRC += spi_master.c
endif
endif
endif
@@ -500,7 +555,7 @@ ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
endif
endif
-VALID_WS2812_DRIVER_TYPES := bitbang pwm spi i2c
+VALID_WS2812_DRIVER_TYPES := bitbang pwm spi i2c vendor
WS2812_DRIVER ?= bitbang
ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
@@ -542,12 +597,6 @@ ifeq ($(strip $(LED_TABLES)), yes)
SRC += $(QUANTUM_DIR)/led_tables.c
endif
-ifeq ($(strip $(TERMINAL_ENABLE)), yes)
- SRC += $(QUANTUM_DIR)/process_keycode/process_terminal.c
- OPT_DEFS += -DTERMINAL_ENABLE
- OPT_DEFS += -DUSER_PRINT
-endif
-
ifeq ($(strip $(VIA_ENABLE)), yes)
DYNAMIC_KEYMAP_ENABLE := yes
RAW_ENABLE := yes
@@ -595,6 +644,14 @@ ifneq ($(strip $(DEBOUNCE_TYPE)), custom)
QUANTUM_SRC += $(QUANTUM_DIR)/debounce/$(strip $(DEBOUNCE_TYPE)).c
endif
+
+VALID_SERIAL_DRIVER_TYPES := bitbang usart vendor
+
+SERIAL_DRIVER ?= bitbang
+ifeq ($(filter $(SERIAL_DRIVER),$(VALID_SERIAL_DRIVER_TYPES)),)
+ $(call CATASTROPHIC_ERROR,Invalid SERIAL_DRIVER,SERIAL_DRIVER="$(SERIAL_DRIVER)" is not a valid SERIAL driver)
+endif
+
ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
POST_CONFIG_H += $(QUANTUM_DIR)/split_common/post_config.h
OPT_DEFS += -DSPLIT_KEYBOARD
@@ -619,11 +676,11 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
endif
endif
- SERIAL_DRIVER ?= bitbang
OPT_DEFS += -DSERIAL_DRIVER_$(strip $(shell echo $(SERIAL_DRIVER) | tr '[:lower:]' '[:upper:]'))
ifeq ($(strip $(SERIAL_DRIVER)), bitbang)
QUANTUM_LIB_SRC += serial.c
else
+ QUANTUM_LIB_SRC += serial_protocol.c
QUANTUM_LIB_SRC += serial_$(strip $(SERIAL_DRIVER)).c
endif
endif
@@ -635,6 +692,12 @@ ifeq ($(strip $(CRC_ENABLE)), yes)
SRC += crc.c
endif
+ifeq ($(strip $(FNV_ENABLE)), yes)
+ OPT_DEFS += -DFNV_ENABLE
+ VPATH += $(LIB_PATH)/fnv
+ SRC += qmk_fnv_type_validation.c hash_32a.c hash_64a.c
+endif
+
ifeq ($(strip $(HAPTIC_ENABLE)),yes)
COMMON_VPATH += $(DRIVER_PATH)/haptic
diff --git a/builddefs/common_rules.mk b/builddefs/common_rules.mk
index d3acddc87b..6573257c78 100644
--- a/builddefs/common_rules.mk
+++ b/builddefs/common_rules.mk
@@ -1,19 +1,5 @@
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
-# WinAVR Makefile Template written by Eric B. Weddington, Jî’šg Wunsch, et al.
-#
-# Released to the Public Domain
-#
-# Additional material for this makefile was written by:
-# Peter Fleury
-# Tim Henigan
-# Colin O'Flynn
-# Reiner Patommel
-# Markus Pfaff
-# Sander Pool
-# Frederik Rouleau
-# Carlos Lamas
-#
# Enable vpath seraching for source files only
# Without this, output files, could be read from the wrong .build directories
@@ -38,36 +24,15 @@ NO_LTO_OBJ := $(filter %.a,$(OBJ))
MASTER_OUTPUT := $(firstword $(OUTPUTS))
-
-
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Optimization level, can be [0, 1, 2, 3, s].
-# 0 = turn off optimization. s = optimize for size.
-# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT ?= s
-# Compiler flag to set the C Standard level.
-# c89 = "ANSI" C
-# gnu89 = c89 plus GCC extensions
-# c99 = ISO C99 standard (not yet fully implemented)
-# gnu99 = c99 plus GCC extensions
-CSTANDARD = -std=gnu99
-
-
-# Place -D or -U options here for C sources
-#CDEFS +=
-
-
-# Place -D or -U options here for ASM sources
-#ADEFS +=
-
-
-# Place -D or -U options here for C++ sources
-#CXXDEFS += -D__STDC_LIMIT_MACROS
-#CXXDEFS += -D__STDC_CONSTANT_MACROS
-#CXXDEFS +=
+# Compiler flag to set the C and C++ language standard level
+CSTANDARD = -std=gnu11
+CXXSTANDARD = -std=gnu++14
# Speed up recompilations by opt-in usage of ccache
USE_CCACHE ?= no
@@ -75,12 +40,8 @@ ifneq ($(USE_CCACHE),no)
CC_PREFIX ?= ccache
endif
-#---------------- Compiler Options C ----------------
-# -g*: generate debugging information
-# -O*: optimization level
-# -f...: tuning, see GCC manual and avr-libc documentation
-# -Wall...: warning level
-# -Wa,...: tell GCC to pass this to the assembler.
+#---------------- C Compiler Options ----------------
+
ifeq ($(strip $(LTO_ENABLE)), yes)
ifeq ($(PLATFORM),ARM_ATSAM)
$(info Enabling LTO on arm_atsam-targeting boards is known to have a high likelihood of failure.)
@@ -111,23 +72,14 @@ CFLAGS += -Wstrict-prototypes
ifneq ($(strip $(ALLOW_WARNINGS)), yes)
CFLAGS += -Werror
endif
-#CFLAGS += -mshort-calls
-#CFLAGS += -fno-unit-at-a-time
-#CFLAGS += -Wundef
-#CFLAGS += -Wunreachable-code
-#CFLAGS += -Wsign-compare
CFLAGS += $(CSTANDARD)
# This fixes lots of keyboards linking errors but SHOULDN'T BE A FINAL SOLUTION
# Fixing of multiple variable definitions must be made.
CFLAGS += -fcommon
-#---------------- Compiler Options C++ ----------------
-# -g*: generate debugging information
-# -O*: optimization level
-# -f...: tuning, see GCC manual and avr-libc documentation
-# -Wall...: warning level
-# -Wa,...: tell GCC to pass this to the assembler.
+#---------------- C++ Compiler Options ----------------
+
ifeq ($(strip $(DEBUG_ENABLE)),yes)
CXXFLAGS += -g$(DEBUG)
endif
@@ -141,57 +93,17 @@ CXXFLAGS += -Wundef
ifneq ($(strip $(ALLOW_WARNINGS)), yes)
CXXFLAGS += -Werror
endif
-#CXXFLAGS += -mshort-calls
-#CXXFLAGS += -fno-unit-at-a-time
-#CXXFLAGS += -Wstrict-prototypes
-#CXXFLAGS += -Wunreachable-code
-#CXXFLAGS += -Wsign-compare
-#CXXFLAGS += $(CSTANDARD)
#---------------- Assembler Options ----------------
+
ASFLAGS += $(ADEFS)
ifeq ($(VERBOSE_AS_CMD),yes)
ASFLAGS += -v
endif
-#---------------- Library Options ----------------
-# Minimalistic printf version
-PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
-
-# Floating point printf version (requires MATH_LIB = -lm below)
-PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
-
-# If this is left blank, then it will use the Standard printf version.
-PRINTF_LIB =
-#PRINTF_LIB = $(PRINTF_LIB_MIN)
-#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
-
-
-# Minimalistic scanf version
-SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
-
-# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
-SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
-
-# If this is left blank, then it will use the Standard scanf version.
-SCANF_LIB =
-#SCANF_LIB = $(SCANF_LIB_MIN)
-#SCANF_LIB = $(SCANF_LIB_FLOAT)
-
-
-MATH_LIB = -lm
-CREATE_MAP ?= yes
-
-
#---------------- Linker Options ----------------
-# -Wl,...: tell GCC to pass this to linker.
-# -Map: create map file
-# --cref: add cross reference to map file
-#
-# Comennt out "--relax" option to avoid a error such:
-# (.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12'
-#
+CREATE_MAP ?= yes
ifeq ($(CREATE_MAP),yes)
LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref
endif
@@ -201,20 +113,11 @@ endif
#LDFLAGS += -Wl,--relax
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
-LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
-#LDFLAGS += -T linker_script.x
+LDFLAGS += -lm
# You can give EXTRALDFLAGS at 'make' command line.
LDFLAGS += $(EXTRALDFLAGS)
#---------------- Assembler Listings ----------------
-# -Wa,...: tell GCC to pass this to the assembler.
-# -adhlns: create listing
-# -gstabs: have the assembler create line number information; note that
-# for use in COFF files, additional information about filenames
-# and function names needs to be present in the assembler source
-# files -- see avr-libc docs [FIXME: not yet described there]
-# -listing-cont-lines: Sets the maximum number of continuation lines of hex
-# dump that will be displayed for a given single line of source input.
ADHLNS_ENABLE ?= no
ifeq ($(ADHLNS_ENABLE),yes)
diff --git a/builddefs/mcu_selection.mk b/builddefs/mcu_selection.mk
index d5fb731e08..135f663c14 100644
--- a/builddefs/mcu_selection.mk
+++ b/builddefs/mcu_selection.mk
@@ -116,6 +116,41 @@ ifneq ($(findstring MK66FX1M0, $(MCU)),)
BOARD ?= PJRC_TEENSY_3_6
endif
+ifneq ($(findstring RP2040, $(MCU)),)
+ # Cortex version
+ MCU = cortex-m0plus
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ CHIBIOS_PORT = ARMv6-M-RP2
+
+ ## chip/board settings
+ # - the next two should match the directories in
+ # <chibios[-contrib]>/os/hal/ports/$(MCU_PORT_NAME)/$(MCU_SERIES)
+ # OR
+ # <chibios[-contrib]>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = RP
+ MCU_SERIES = RP2040
+
+ # Linker script to use
+ # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # or <keyboard_dir>/ld/
+ STARTUPLD_CONTRIB = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/ld
+ MCU_LDSCRIPT ?= RP2040_FLASH_TIMECRIT
+ LDFLAGS += -L $(STARTUPLD_CONTRIB)
+
+ # Startup code to use
+ # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP ?= rp2040
+
+ # Board: it should exist either in <chibios>/os/hal/boards/,
+ # <keyboard_dir>/boards/, or drivers/boards/
+ BOARD ?= GENERIC_PROMICRO_RP2040
+
+ # Default UF2 Bootloader settings
+ UF2_FAMILY ?= RP2040
+ FIRMWARE_FORMAT ?= uf2
+endif
+
ifneq ($(findstring STM32F042, $(MCU)),)
# Cortex version
MCU = cortex-m0
diff --git a/builddefs/show_options.mk b/builddefs/show_options.mk
index f67d009191..98537e6da2 100644
--- a/builddefs/show_options.mk
+++ b/builddefs/show_options.mk
@@ -5,7 +5,6 @@ BUILD_OPTION_NAMES = \
CONSOLE_ENABLE \
COMMAND_ENABLE \
NKRO_ENABLE \
- TERMINAL_ENABLE \
CUSTOM_MATRIX \
DEBOUNCE_TYPE \
SPLIT_KEYBOARD \
@@ -46,6 +45,7 @@ OTHER_OPTION_NAMES = \
LEADER_ENABLE \
PRINTING_ENABLE \
STENO_ENABLE \
+ STENO_PROTOCOL \
TAP_DANCE_ENABLE \
VIRTSER_ENABLE \
OLED_ENABLE \
diff --git a/builddefs/testlist.mk b/builddefs/testlist.mk
index b8d22bce80..8a30a44972 100644
--- a/builddefs/testlist.mk
+++ b/builddefs/testlist.mk
@@ -4,6 +4,7 @@ FULL_TESTS := $(notdir $(TEST_LIST))
include $(QUANTUM_PATH)/debounce/tests/testlist.mk
include $(QUANTUM_PATH)/encoder/tests/testlist.mk
include $(QUANTUM_PATH)/sequencer/tests/testlist.mk
+include $(QUANTUM_PATH)/wear_leveling/tests/testlist.mk
include $(PLATFORM_PATH)/test/testlist.mk
define VALIDATE_TEST_LIST
diff --git a/data/mappings/info_config.json b/data/mappings/info_config.json
index 5f0d903bd7..fcceb98025 100644
--- a/data/mappings/info_config.json
+++ b/data/mappings/info_config.json
@@ -12,6 +12,7 @@
"AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "bool"},
"BACKLIGHT_BREATHING": {"info_key": "backlight.breathing", "value_type": "bool"},
"BREATHING_PERIOD": {"info_key": "backlight.breathing_period", "value_type": "int"},
+ "BACKLIGHT_ON_STATE": {"info_key": "backlight.on_state", "value_type": "int"},
"BACKLIGHT_PIN": {"info_key": "backlight.pin"},
"BOTH_SHIFTS_TURNS_ON_CAPS_WORD": {"info_key": "caps_word.both_shifts_turns_on", "value_type": "bool"},
"CAPS_WORD_IDLE_TIMEOUT": {"info_key": "caps_word.idle_timeout", "value_type": "int"},
@@ -35,6 +36,9 @@
"LED_CAPS_LOCK_PIN": {"info_key": "indicators.caps_lock"},
"LED_NUM_LOCK_PIN": {"info_key": "indicators.num_lock"},
"LED_SCROLL_LOCK_PIN": {"info_key": "indicators.scroll_lock"},
+ "LED_COMPOSE_PIN": {"info_key": "indicators.compose"},
+ "LED_KANA_PIN": {"info_key": "indicators.kana"},
+ "LED_PIN_ON_STATE": {"info_key": "indicators.on_state", "value_type": "int"},
"MANUFACTURER": {"info_key": "manufacturer"},
"MATRIX_HAS_GHOST": {"info_key": "matrix_pins.ghost", "value_type": "bool"},
"MATRIX_IO_DELAY": {"info_key": "matrix_pins.io_delay", "value_type": "int"},
diff --git a/data/mappings/info_rules.json b/data/mappings/info_rules.json
index d4eec37ba0..279b5ac213 100644
--- a/data/mappings/info_rules.json
+++ b/data/mappings/info_rules.json
@@ -13,6 +13,7 @@
"BOOTLOADER": {"info_key": "bootloader", "warn_duplicate": false},
"BLUETOOTH": {"info_key": "bluetooth.driver"},
"CAPS_WORD_ENABLE": {"info_key": "caps_word.enabled", "value_type": "bool"},
+ "ENCODER_ENABLE": {"info_key": "encoder.enabled", "value_type": "bool"},
"FIRMWARE_FORMAT": {"info_key": "build.firmware_format"},
"KEYBOARD_SHARED_EP": {"info_key": "usb.shared_endpoint.keyboard", "value_type": "bool"},
"MOUSE_SHARED_EP": {"info_key": "usb.shared_endpoint.mouse", "value_type": "bool"},
@@ -27,6 +28,8 @@
"SPLIT_KEYBOARD": {"info_key": "split.enabled", "value_type": "bool"},
"SPLIT_TRANSPORT": {"info_key": "split.transport.protocol", "to_c": false},
"WAIT_FOR_USB": {"info_key": "usb.wait_for", "value_type": "bool"},
+ "STENO_ENABLE": {"info_key": "stenography.enabled", "value_type": "bool"},
+ "STENO_PROTOCOL": {"info_key": "stenography.protocol"},
# Items we want flagged in lint
"CTPC": {"info_key": "_deprecated.ctpc", "deprecated": true},
diff --git a/data/schemas/definitions.jsonschema b/data/schemas/definitions.jsonschema
index 1bdfbbeb03..8b68a58482 100644
--- a/data/schemas/definitions.jsonschema
+++ b/data/schemas/definitions.jsonschema
@@ -1,5 +1,5 @@
{
- "$schema": "http://json-schema.org/draft-07/schema#",
+ "$schema": "https://json-schema.org/draft/2020-12/schema#",
"$id": "qmk.definitions.v1",
"title": "Common definitions used across QMK's jsonschemas.",
"type": "object",
@@ -65,8 +65,7 @@
]
},
"key_unit": {
- "type": "number",
- "min": 0.25
+ "type": "number"
},
"keyboard": {
"oneOf": [
@@ -103,8 +102,11 @@
"pattern": "^LINE_PIN\\d{1,2}$"
},
{
- "type": "number",
- "multipleOf": 1
+ "type": "string",
+ "pattern": "^GP\\d{1,2}$"
+ },
+ {
+ "type": "integer"
},
{
"type": "null"
@@ -115,14 +117,12 @@
"type": "number"
},
"signed_int": {
- "type": "number",
- "multipleOf": 1
+ "type": "integer"
},
"signed_int_8": {
- "type": "number",
- "min": -127,
- "max": 127,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": -127,
+ "maximum": 127
},
"string_array": {
"type": "array",
@@ -138,17 +138,20 @@
},
"unsigned_decimal": {
"type": "number",
- "min": 0
+ "minimum": 0
},
"unsigned_int": {
- "type": "number",
- "min": 0,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": 0
},
"unsigned_int_8": {
- "type": "number",
- "min": 0,
- "max": 255,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 255
+ },
+ "bit": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 1
}
}
diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema
index fd60920578..8aca807e38 100644
--- a/data/schemas/keyboard.jsonschema
+++ b/data/schemas/keyboard.jsonschema
@@ -1,7 +1,27 @@
{
- "$schema": "http://json-schema.org/draft-07/schema#",
+ "$schema": "https://json-schema.org/draft/2020-12/schema#",
"$id": "qmk.keyboard.v1",
"title": "Keyboard Information",
+ "definitions": {
+ "encoder_config": {
+ "type": "object",
+ "properties": {
+ "rotary": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["pin_a", "pin_b"],
+ "properties": {
+ "pin_a": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+ "pin_b": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+ "resolution": {"$ref": "qmk.definitions.v1#/unsigned_int"}
+ }
+ }
+ }
+ }
+ }
+ },
"type": "object",
"properties": {
"keyboard_name": {"$ref": "qmk.definitions.v1#/text_identifier"},
@@ -22,7 +42,7 @@
},
"processor": {
"type": "string",
- "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66FX1M0", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F405", "STM32F407", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L412", "STM32L422", "STM32L432", "STM32L433", "STM32L442", "STM32L443", "GD32VF103", "WB32F3G71", "WB32FQ95", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"]
+ "enum": ["cortex-m0", "cortex-m0plus", "cortex-m3", "cortex-m4", "MKL26Z64", "MK20DX128", "MK20DX256", "MK66FX1M0", "RP2040", "STM32F042", "STM32F072", "STM32F103", "STM32F303", "STM32F401", "STM32F405", "STM32F407", "STM32F411", "STM32F446", "STM32G431", "STM32G474", "STM32L412", "STM32L422", "STM32L432", "STM32L433", "STM32L442", "STM32L443", "GD32VF103", "WB32F3G71", "WB32FQ95", "atmega16u2", "atmega32u2", "atmega16u4", "atmega32u4", "at90usb162", "at90usb646", "at90usb647", "at90usb1286", "at90usb1287", "atmega32a", "atmega328p", "atmega328", "attiny85", "unknown"]
},
"audio": {
"type": "object",
@@ -40,12 +60,12 @@
"breathing": {"type": "boolean"},
"breathing_period": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"levels": {
- "type": "number",
- "min": 1,
- "max": 31,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 31
},
- "pin": {"$ref": "qmk.definitions.v1#/mcu_pin"}
+ "pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+ "on_state": {"$ref": "qmk.definitions.v1#/bit"}
}
},
"bluetooth": {
@@ -66,7 +86,7 @@
},
"bootloader": {
"type": "string",
- "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "custom", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "md-boot", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "gd32v-dfu", "wb32-dfu", "unknown", "usbasploader", "USBasp", "tinyuf2"],
+ "enum": ["atmel-dfu", "bootloadhid", "bootloadHID", "custom", "caterina", "halfkay", "kiibohd", "lufa-dfu", "lufa-ms", "md-boot", "qmk-dfu", "qmk-hid", "stm32-dfu", "stm32duino", "gd32v-dfu", "wb32-dfu", "unknown", "usbasploader", "USBasp", "tinyuf2", "rp2040"],
},
"bootloader_instructions": {
"type": "string",
@@ -113,13 +133,22 @@
"type": "array",
"items": {"$ref": "qmk.definitions.v1#/filename"}
},
+ "encoder": {
+ "$ref": "#/definitions/encoder_config",
+ "properties": {
+ "enabled": {"type": "boolean"}
+ }
+ },
"features": {"$ref": "qmk.definitions.v1#/boolean_array"},
"indicators": {
"type": "object",
"properties": {
"caps_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"num_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"},
- "scroll_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"}
+ "scroll_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+ "compose": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+ "kana": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+ "on_state": {"$ref": "qmk.definitions.v1#/bit"}
}
},
"layout_aliases": {
@@ -154,12 +183,11 @@
"minItems": 2,
"maxItems": 2,
"items": {
- "type": "number",
- "min": 0,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": 0
}
},
- "r": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
+ "r": {"$ref": "qmk.definitions.v1#/signed_decimal"},
"rx": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
"ry": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
"h": {"$ref": "qmk.definitions.v1#/key_unit"},
@@ -230,14 +258,13 @@
"minItems": 2,
"maxItems": 2,
"items": {
- "type": "number",
- "min": 0,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": 0
}
},
"x": {"$ref": "qmk.definitions.v1#/key_unit"},
"y": {"$ref": "qmk.definitions.v1#/key_unit"},
- "flags": {"$ref": "qmk.definitions.v1#/unsigned_decimal"}
+ "flags": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
}
}
}
@@ -258,14 +285,13 @@
"minItems": 2,
"maxItems": 2,
"items": {
- "type": "number",
- "min": 0,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": 0
}
},
"x": {"$ref": "qmk.definitions.v1#/key_unit"},
"y": {"$ref": "qmk.definitions.v1#/key_unit"},
- "flags": {"$ref": "qmk.definitions.v1#/unsigned_decimal"}
+ "flags": {"$ref": "qmk.definitions.v1#/unsigned_int_8"}
}
}
}
@@ -290,10 +316,9 @@
"blink": {"type": "boolean"},
"enabled": {"type": "boolean"},
"max": {
- "type": "number",
- "min": 1,
- "max": 32,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 32
},
"override_rgb": {"type": "boolean"}
}
@@ -307,8 +332,8 @@
"split": {"type": "boolean"},
"split_count": {
"type": "array",
- "minLength": 2,
- "maxLength": 2,
+ "minItems": 2,
+ "maxItems": 2,
"items": {"$ref": "qmk.definitions.v1#/unsigned_int"}
}
}
@@ -322,21 +347,31 @@
"idle_timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"unlock_sequence": {
"type": "array",
- "minLength": 1,
- "maxLength": 5,
+ "minItems": 1,
+ "maxItems": 5,
"items": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": {
- "type": "number",
- "min": 0,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": 0
}
}
}
}
},
+ "stenography": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "enabled": {"type": "boolean"},
+ "protocol": {
+ "type": "string",
+ "enum": ["all", "geminipr", "txbolt"]
+ }
+ }
+ },
"split": {
"type": "object",
"additionalProperties": false,
@@ -365,16 +400,24 @@
}
}
},
+ "encoder": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "right": {
+ "$ref": "#/definitions/encoder_config"
+ }
+ }
+ },
"main": {
"type": "string",
"enum": ["eeprom", "left", "matrix_grid", "pin", "right"]
},
"soft_serial_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
"soft_serial_speed": {
- "type": "number",
- "min": 0,
- "max": 5,
- "multipleOf": 1
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 5
},
"transport": {
"type": "object",
@@ -428,7 +471,7 @@
"force_nkro": {"type": "boolean"},
"pid": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
"vid": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
- "max_power": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "max_power": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"no_startup_check": {"type": "boolean"},
"polling_interval": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
"shared_endpoint": {
@@ -439,7 +482,7 @@
"mouse": {"type": "boolean"}
}
},
- "suspend_wakeup_delay": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "suspend_wakeup_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"},
"wait_for": {"type": "boolean"},
}
},
@@ -448,8 +491,8 @@
"additionalProperties": false,
"properties": {
"keys_per_scan": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
- "tap_keycode_delay": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
- "tap_capslock_delay": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+ "tap_keycode_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"},
+ "tap_capslock_delay": {"$ref": "qmk.definitions.v1#/unsigned_int"},
}
},
"qmk_lufa_bootloader": {
diff --git a/data/schemas/keymap.jsonschema b/data/schemas/keymap.jsonschema
index 3803301a66..92a1ce533d 100644
--- a/data/schemas/keymap.jsonschema
+++ b/data/schemas/keymap.jsonschema
@@ -1,5 +1,5 @@
{
- "$schema": "http://json-schema.org/draft-07/schema#",
+ "$schema": "https://json-schema.org/draft/2020-12/schema#",
"$id": "qmk.keymap.v1",
"title": "Keymap Information",
"type": "object",
@@ -50,8 +50,7 @@
},
"config": {"$ref": "qmk.keyboard.v1"},
"notes": {
- "type": "string",
- "description": "asdf"
+ "type": "string"
}
},
"required": [
diff --git a/docs/_summary.md b/docs/_summary.md
index 11f5e1dd51..da007bccb6 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -88,7 +88,6 @@
* [Swap Hands](feature_swap_hands.md)
* [Tap Dance](feature_tap_dance.md)
* [Tap-Hold Configuration](tap_hold.md)
- * [Terminal](feature_terminal.md)
* [Unicode](feature_unicode.md)
* [Userspace](feature_userspace.md)
* [WPM Calculation](feature_wpm.md)
@@ -147,6 +146,7 @@
* [SPI Driver](spi_driver.md)
* [WS2812 Driver](ws2812_driver.md)
* [EEPROM Driver](eeprom_driver.md)
+ * [Flash Driver](flash_driver.md)
* ['serial' Driver](serial_driver.md)
* [UART Driver](uart_driver.md)
* [GPIO Controls](gpio_control.md)
@@ -165,6 +165,7 @@
* Arm/ChibiOS
* [Selecting an MCU](platformdev_selecting_arm_mcu.md)
* [Early initialization](platformdev_chibios_earlyinit.md)
+ * [Raspberry Pi RP2040](platformdev_rp2040.md)
* QMK Reference
* [Contributing to QMK](contributing.md)
diff --git a/docs/compatible_microcontrollers.md b/docs/compatible_microcontrollers.md
index cee8986829..a594fe0620 100644
--- a/docs/compatible_microcontrollers.md
+++ b/docs/compatible_microcontrollers.md
@@ -65,6 +65,12 @@ You can also use any ARM chip with USB that [ChibiOS](https://www.chibios.org) s
* [MK66FX1M0](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/k-series-cortex-m4/k6x-ethernet/kinetis-k66-180-mhz-dual-high-speed-full-speed-usbs-2mb-flash-microcontrollers-mcus-based-on-arm-cortex-m4-core:K66_180)
* PJRC Teensy 3.6
+### Raspberry Pi
+
+* [RP2040](https://www.raspberrypi.com/documentation/microcontrollers/rp2040.html)
+
+For a detailed overview about the RP2040 support by QMK see the [dedicated RP2040 page](platformdev_rp2040.md).
+
## Atmel ATSAM
There is limited support for one of Atmel's ATSAM microcontrollers, that being the [ATSAMD51J18A](https://www.microchip.com/wwwproducts/en/ATSAMD51J18A) used by the [Massdrop keyboards](https://github.com/qmk/qmk_firmware/tree/master/keyboards/massdrop). However, it is not recommended to design a board with this microcontroller as the support is quite specialized to Massdrop hardware.
diff --git a/docs/config_options.md b/docs/config_options.md
index 8227a0e074..c35227a407 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -141,7 +141,7 @@ If you define these options you will enable the associated feature, which may in
## Behaviors That Can Be Configured
* `#define TAPPING_TERM 200`
- * how long before a tap becomes a hold, if set above 500, a key tapped during the tapping term will turn it into a hold too
+ * how long before a key press becomes a hold
* `#define TAPPING_TERM_PER_KEY`
* enables handling for per key `TAPPING_TERM` settings
* `#define RETRO_TAPPING`
@@ -174,6 +174,8 @@ If you define these options you will enable the associated feature, which may in
* sets the timer for leader key chords to run on each key press rather than overall
* `#define LEADER_KEY_STRICT_KEY_PROCESSING`
* Disables keycode filtering for Mod-Tap and Layer-Tap keycodes. Eg, if you enable this, you would need to specify `MT(MOD_CTL, KC_A)` if you want to use `KC_A`.
+* `#define MOUSE_EXTENDED_REPORT`
+ * Enables support for extended reports (-32767 to 32767, instead of -127 to 127), which may allow for smoother reporting, and prevent maxing out of the reports. Applies to both Pointing Device and Mousekeys.
* `#define ONESHOT_TIMEOUT 300`
* how long before oneshot times out
* `#define ONESHOT_TAP_TOGGLE 2`
diff --git a/docs/eeprom_driver.md b/docs/eeprom_driver.md
index 6dcf10c04d..50d8bcb7b3 100644
--- a/docs/eeprom_driver.md
+++ b/docs/eeprom_driver.md
@@ -2,12 +2,15 @@
The EEPROM driver can be swapped out depending on the needs of the keyboard, or whether extra hardware is present.
+Selecting the EEPROM driver is done in your keyboard's `rules.mk`:
+
Driver | Description
-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`EEPROM_DRIVER = vendor` (default) | Uses the on-chip driver provided by the chip manufacturer. For AVR, this is provided by avr-libc. This is supported on ARM for a subset of chips -- STM32F3xx, STM32F1xx, and STM32F072xB will be emulated by writing to flash. STM32L0xx and STM32L1xx will use the onboard dedicated true EEPROM. Other chips will generally act as "transient" below.
`EEPROM_DRIVER = i2c` | Supports writing to I2C-based 24xx EEPROM chips. See the driver section below.
`EEPROM_DRIVER = spi` | Supports writing to SPI-based 25xx EEPROM chips. See the driver section below.
`EEPROM_DRIVER = transient` | Fake EEPROM driver -- supports reading/writing to RAM, and will be discarded when power is lost.
+`EEPROM_DRIVER = wear_leveling` | Frontend driver for the wear_leveling system, allowing for EEPROM emulation on top of flash -- both in-MCU and external SPI NOR flash.
## Vendor Driver Configuration :id=vendor-eeprom-driver-configuration
@@ -43,8 +46,9 @@ Module | Equivalent `#define` | Source
-----------------|---------------------------------|------------------------------------------
CAT24C512 EEPROM | `#define EEPROM_I2C_CAT24C512` | <https://www.sparkfun.com/products/14764>
RM24C512C EEPROM | `#define EEPROM_I2C_RM24C512C` | <https://www.sparkfun.com/products/14764>
-24LC64 EEPROM | `#define EEPROM_I2C_24LC64` | <https://www.microchip.com/wwwproducts/en/24LC64>
-24LC128 EEPROM | `#define EEPROM_I2C_24LC128` | <https://www.microchip.com/wwwproducts/en/24LC128>
+24LC32A EEPROM | `#define EEPROM_I2C_24LC32A` | <https://www.microchip.com/en-us/product/24LC32A>
+24LC64 EEPROM | `#define EEPROM_I2C_24LC64` | <https://www.microchip.com/en-us/product/24LC64>
+24LC128 EEPROM | `#define EEPROM_I2C_24LC128` | <https://www.microchip.com/en-us/product/24LC128>
24LC256 EEPROM | `#define EEPROM_I2C_24LC256` | <https://www.sparkfun.com/products/525>
MB85RC256V FRAM | `#define EEPROM_I2C_MB85RC256V` | <https://www.adafruit.com/product/1895>
@@ -54,13 +58,13 @@ MB85RC256V FRAM | `#define EEPROM_I2C_MB85RC256V` | <https://www.adafruit.com/p
Currently QMK supports 25xx-series chips over SPI. As such, requires a working spi_master driver configuration. You can override the driver configuration via your config.h:
-`config.h` override | Description | Default Value
------------------------------------------------|--------------------------------------------------------------------------------------|--------------
-`#define EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN` | SPI Slave select pin in order to inform that the EEPROM is currently being addressed | _none_
-`#define EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR` | Clock divisor used to divide the peripheral clock to derive the SPI frequency | `64`
-`#define EXTERNAL_EEPROM_BYTE_COUNT` | Total size of the EEPROM in bytes | 8192
-`#define EXTERNAL_EEPROM_PAGE_SIZE` | Page size of the EEPROM in bytes, as specified in the datasheet | 32
-`#define EXTERNAL_EEPROM_ADDRESS_SIZE` | The number of bytes to transmit for the memory location within the EEPROM | 2
+`config.h` override | Default Value | Description
+-----------------------------------------------|---------------|-------------------------------------------------------------------------------------
+`#define EXTERNAL_EEPROM_SPI_SLAVE_SELECT_PIN` | _none_ | SPI Slave select pin in order to inform that the EEPROM is currently being addressed
+`#define EXTERNAL_EEPROM_SPI_CLOCK_DIVISOR` | `64` | Clock divisor used to divide the peripheral clock to derive the SPI frequency
+`#define EXTERNAL_EEPROM_BYTE_COUNT` | `8192` | Total size of the EEPROM in bytes
+`#define EXTERNAL_EEPROM_PAGE_SIZE` | `32` | Page size of the EEPROM in bytes, as specified in the datasheet
+`#define EXTERNAL_EEPROM_ADDRESS_SIZE` | `2` | The number of bytes to transmit for the memory location within the EEPROM
!> There's no way to determine if there is an SPI EEPROM actually responding. Generally, this will result in reads of nothing but zero.
@@ -73,3 +77,84 @@ The only configurable item for the transient EEPROM driver is its size:
`#define TRANSIENT_EEPROM_SIZE` | Total size of the EEPROM storage in bytes | 64
Default values and extended descriptions can be found in `drivers/eeprom/eeprom_transient.h`.
+
+## Wear-leveling Driver Configuration :id=wear_leveling-eeprom-driver-configuration
+
+The wear-leveling driver uses an algorithm to minimise the number of erase cycles on the underlying MCU flash memory.
+
+There is no specific configuration for this driver, but the wear-leveling system used by this driver may need configuration. See the [wear-leveling configuration](#wear_leveling-configuration) section for more information.
+
+# Wear-leveling Configuration :id=wear_leveling-configuration
+
+The wear-leveling driver has a few possible _backing stores_ that may be used by adding to your keyboard's `rules.mk` file:
+
+Driver | Description
+----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+`WEAR_LEVELING_DRIVER = embedded_flash` | This driver is used for emulating EEPROM by writing to embedded flash on the MCU.
+`WEAR_LEVELING_DRIVER = spi_flash` | This driver is used to address external SPI NOR Flash peripherals.
+`WEAR_LEVELING_DRIVER = rp2040_flash` | This driver is used to write to the same storage the RP2040 executes code from.
+`WEAR_LEVELING_DRIVER = legacy` | This driver is the "legacy" emulated EEPROM provided in historical revisions of QMK. Currently used for STM32F0xx and STM32F4x1, but slated for deprecation and removal once `embedded_flash` support for those MCU families is complete.
+
+!> All wear-leveling drivers require an amount of RAM equivalent to the selected logical EEPROM size. Increasing the size to 32kB of EEPROM requires 32kB of RAM, which a significant number of MCUs simply do not have.
+
+## Wear-leveling Embedded Flash Driver Configuration :id=wear_leveling-efl-driver-configuration
+
+This driver performs writes to the embedded flash storage embedded in the MCU. In most circumstances, the last few of sectors of flash are used in order to minimise the likelihood of collision with program code.
+
+Configurable options in your keyboard's `config.h`:
+
+`config.h` override | Default | Description
+-----------------------------------------|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+`#define WEAR_LEVELING_EFL_FIRST_SECTOR` | _unset_ | The first sector on the MCU to use. By default this is not defined and calculated at runtime based on the MCU. However, different flash sizes on MCUs may require custom configuration.
+`#define WEAR_LEVELING_EFL_FLASH_SIZE` | _unset_ | Allows overriding the flash size available for use for wear-leveling. Under normal circumstances this is automatically calculated and should not need to be overridden. Specifying a size larger than the amount actually available in flash will usually prevent the MCU from booting.
+`#define WEAR_LEVELING_LOGICAL_SIZE` | `1024` | Number of bytes "exposed" to the rest of QMK and denotes the size of the usable EEPROM.
+`#define WEAR_LEVELING_BACKING_SIZE` | `2048` | Number of bytes used by the wear-leveling algorithm for its underlying storage, and needs to be a multiple of the logical size.
+`#define BACKING_STORE_WRITE_SIZE` | _automatic_ | The byte width of the underlying write used on the MCU, and is usually automatically determined from the selected MCU family. If an error occurs in the auto-detection, you'll need to consult the MCU's datasheet and determine this value, specifying it directly.
+
+!> If your MCU does not boot after swapping to the EFL wear-leveling driver, it's likely that the flash size is incorrectly detected, usually as an MCU with larger flash and may require overriding.
+
+## Wear-leveling SPI Flash Driver Configuration :id=wear_leveling-flash_spi-driver-configuration
+
+This driver performs writes to an external SPI NOR Flash peripheral. It also requires a working configuration for the SPI NOR Flash peripheral -- see the [flash driver](flash_driver.md) documentation for more information.
+
+Configurable options in your keyboard's `config.h`:
+
+`config.h` override | Default | Description
+----------------------------------------------------|--------------------------------|--------------------------------------------------------------------------------------------------------------------------------
+`#define WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT` | `1` | Number of blocks in the external flash used by the wear-leveling algorithm.
+`#define WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET` | `0` | The index first block in the external flash used by the wear-leveling algorithm.
+`#define WEAR_LEVELING_LOGICAL_SIZE` | `((block_count*block_size)/2)` | Number of bytes "exposed" to the rest of QMK and denotes the size of the usable EEPROM. Result must be <= 64kB.
+`#define WEAR_LEVELING_BACKING_SIZE` | `(block_count*block_size)` | Number of bytes used by the wear-leveling algorithm for its underlying storage, and needs to be a multiple of the logical size.
+`#define BACKING_STORE_WRITE_SIZE` | `8` | The write width used whenever a write is performed on the external flash peripheral.
+
+!> There is currently a limit of 64kB for the EEPROM subsystem within QMK, so using a larger flash is not going to be beneficial as the logical size cannot be increased beyond 65536. The backing size may be increased to a larger value, but erase timing may suffer as a result.
+
+## Wear-leveling RP2040 Driver Configuration :id=wear_leveling-rp2040-driver-configuration
+
+This driver performs writes to the same underlying storage that the RP2040 executes its code.
+
+Configurable options in your keyboard's `config.h`:
+
+`config.h` override | Default | Description
+------------------------------------------|----------------------------|--------------------------------------------------------------------------------------------------------------------------------
+`#define WEAR_LEVELING_RP2040_FLASH_SIZE` | `PICO_FLASH_SIZE_BYTES` | Number of bytes of flash on the board.
+`#define WEAR_LEVELING_RP2040_FLASH_BASE` | `(flash_size-sector_size)` | The byte-wise location that the backing storage should be located.
+`#define WEAR_LEVELING_LOGICAL_SIZE` | `4096` | Number of bytes "exposed" to the rest of QMK and denotes the size of the usable EEPROM.
+`#define WEAR_LEVELING_BACKING_SIZE` | `8192` | Number of bytes used by the wear-leveling algorithm for its underlying storage, and needs to be a multiple of the logical size as well as the sector size.
+`#define BACKING_STORE_WRITE_SIZE` | `2` | The write width used whenever a write is performed on the external flash peripheral.
+
+## Wear-leveling Legacy EEPROM Emulation Driver Configuration :id=wear_leveling-legacy-driver-configuration
+
+This driver performs writes to the embedded flash storage embedded in the MCU much like the normal Embedded Flash Driver, and is only for use with STM32F0xx and STM32F4x1 devices. This flash implementation is still currently provided as the EFL driver is currently non-functional for the previously mentioned families.
+
+By default, `1024` bytes of emulated EEPROM is provided:
+
+MCU | EEPROM Provided | Flash Used
+----------|-----------------|--------------
+STM32F042 | `1024` bytes | `2048` bytes
+STM32F070 | `1024` bytes | `2048` bytes
+STM32F072 | `1024` bytes | `2048` bytes
+STM32F401 | `1024` bytes | `16384` bytes
+STM32F411 | `1024` bytes | `16384` bytes
+
+Under normal circumstances configuration of this driver requires intimate knowledge of the MCU's flash structure -- reconfiguration is at your own risk and will require referring to the code.
diff --git a/docs/feature_mouse_keys.md b/docs/feature_mouse_keys.md
index 905da36e43..8e474c4245 100644
--- a/docs/feature_mouse_keys.md
+++ b/docs/feature_mouse_keys.md
@@ -87,9 +87,9 @@ This is an extension of the accelerated mode. The kinetic mode uses a quadratic
|`MK_KINETIC_SPEED` |undefined|Enable kinetic mode |
|`MOUSEKEY_DELAY` |5 |Delay between pressing a movement key and cursor movement |
|`MOUSEKEY_INTERVAL` |10 |Time between cursor movements in milliseconds |
-|`MOUSEKEY_MOVE_DELTA` |5 |Step size for accelerating from initial to base speed |
+|`MOUSEKEY_MOVE_DELTA` |16 |Step size for accelerating from initial to base speed |
|`MOUSEKEY_INITIAL_SPEED` |100 |Initial speed of the cursor in pixel per second |
-|`MOUSEKEY_BASE_SPEED` |1000 |Maximum cursor speed at which acceleration stops |
+|`MOUSEKEY_BASE_SPEED` |5000 |Maximum cursor speed at which acceleration stops |
|`MOUSEKEY_DECELERATED_SPEED` |400 |Decelerated cursor speed |
|`MOUSEKEY_ACCELERATED_SPEED` |3000 |Accelerated cursor speed |
|`MOUSEKEY_WHEEL_INITIAL_MOVEMENTS` |16 |Initial number of movements of the mouse wheel |
@@ -100,7 +100,7 @@ This is an extension of the accelerated mode. The kinetic mode uses a quadratic
Tips:
* The smoothness of the cursor movement depends on the `MOUSEKEY_INTERVAL` setting. The shorter the interval is set the smoother the movement will be. Setting the value too low makes the cursor unresponsive. Lower settings are possible if the micro processor is fast enough. For example: At an interval of `8` milliseconds, `125` movements per second will be initiated. With a base speed of `1000` each movement will move the cursor by `8` pixels.
-* Mouse wheel movements are implemented differently from cursor movements. While it's okay for the cursor to move multiple pixels at once for the mouse wheel this would lead to jerky movements. Instead, the mouse wheel operates at step size `1`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
+* Mouse wheel movements are implemented differently from cursor movements. While it's okay for the cursor to move multiple pixels at once for the mouse wheel this would lead to jerky movements. Instead, the mouse wheel operates at step size `2`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
### Constant mode
diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md
index 02c1e64a31..264362ea77 100644
--- a/docs/feature_pointing_device.md
+++ b/docs/feature_pointing_device.md
@@ -72,7 +72,6 @@ The Analog Joystick is an analog (ADC) driven sensor. There are a variety of jo
|`ANALOG_JOYSTICK_SPEED_MAX` | (Optional) The maximum value used for motion. | `2` |
|`ANALOG_JOYSTICK_CLICK_PIN` | (Optional) The pin wired up to the press switch of the analog stick. | _not defined_ |
-
### Cirque Trackpad
To use the Cirque Trackpad sensor, add this to your `rules.mk`:
@@ -90,30 +89,42 @@ POINTING_DEVICE_DRIVER = cirque_pinnacle_spi
This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the TM040040, TM035035 and the TM023023 trackpads. These are I2C or SPI compatible, and both configurations are supported.
-| Setting | Description | Default |
-|---------------------------------|---------------------------------------------------------------------------------|-----------------------|
-|`CIRQUE_PINNACLE_X_LOWER` | (Optional) The minimum reachable X value on the sensor. | `127` |
-|`CIRQUE_PINNACLE_X_UPPER` | (Optional) The maximum reachable X value on the sensor. | `1919` |
-|`CIRQUE_PINNACLE_Y_LOWER` | (Optional) The minimum reachable Y value on the sensor. | `63` |
-|`CIRQUE_PINNACLE_Y_UPPER` | (Optional) The maximum reachable Y value on the sensor. | `1471` |
-|`CIRQUE_PINNACLE_TAPPING_TERM` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` |
-|`CIRQUE_PINNACLE_TOUCH_DEBOUNCE` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` |
+| Setting | Description | Default |
+|-------------------------------- |-----------------------------------------------------------------------|--------------------- |
+|`CIRQUE_PINNACLE_X_LOWER` | (Optional) The minimum reachable X value on the sensor. | `127` |
+|`CIRQUE_PINNACLE_X_UPPER` | (Optional) The maximum reachable X value on the sensor. | `1919` |
+|`CIRQUE_PINNACLE_Y_LOWER` | (Optional) The minimum reachable Y value on the sensor. | `63` |
+|`CIRQUE_PINNACLE_Y_UPPER` | (Optional) The maximum reachable Y value on the sensor. | `1471` |
+|`CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `ADC_ATTENUATE_4X` |
+|`CIRQUE_PINNACLE_TAPPING_TERM` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` |
+|`CIRQUE_PINNACLE_TOUCH_DEBOUNCE` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` |
+
+**`CIRQUE_PINNACLE_ATTENUATION`** is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be.
+
+Default attenuation is set to 4X, although if you are using a thicker overlay (such as the curved overlay) you will want a lower attenuation such as 2X. The possible values are:
+* `ADC_ATTENUATE_4X`: Least sensitive
+* `ADC_ATTENUATE_3X`
+* `ADC_ATTENUATE_2X`
+* `ADC_ATTENUATE_1X`: Most sensitive
| I2C Setting | Description | Default |
|--------------------------|---------------------------------------------------------------------------------|---------|
|`CIRQUE_PINNACLE_ADDR` | (Required) Sets the I2C Address for the Cirque Trackpad | `0x2A` |
|`CIRQUE_PINNACLE_TIMEOUT` | (Optional) The timeout for i2c communication with the trackpad in milliseconds. | `20` |
-| SPI Setting | Description | Default |
-|-------------------------------|------------------------------------------------------------------------|---------------|
-|`CIRQUE_PINNACLE_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `1000000` |
-|`CIRQUE_PINNACLE_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
-|`CIRQUE_PINNACLE_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `1` |
-|`CIRQUE_PINNACLE_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
-|`CIRQUE_PINNACLE_SPI_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
+| SPI Setting | Description | Default |
+|-------------------------------|------------------------------------------------------------------------|----------------|
+|`CIRQUE_PINNACLE_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `1000000` |
+|`CIRQUE_PINNACLE_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
+|`CIRQUE_PINNACLE_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `1` |
+|`CIRQUE_PINNACLE_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
+|`CIRQUE_PINNACLE_SPI_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
Default Scaling/CPI is 1024.
+Also see the `POINTING_DEVICE_TASK_THROTTLE_MS`, which defaults to 10ms when using Cirque Pinnacle, which matches the internal update rate of the position registers (in standard configuration). Advanced configuration for pen/stylus usage might require lower values.
+
+
### Pimoroni Trackball
To use the Pimoroni Trackball module, add this to your `rules.mk`:
@@ -259,6 +270,7 @@ The following configuration options are only available when using `SPLIT_POINTIN
|`POINTING_DEVICE_ROTATION_270_RIGHT` | (Optional) Rotates the X and Y data by 270 degrees. | _not defined_ |
|`POINTING_DEVICE_INVERT_X_RIGHT` | (Optional) Inverts the X axis report. | _not defined_ |
|`POINTING_DEVICE_INVERT_Y_RIGHT` | (Optional) Inverts the Y axis report. | _not defined_ |
+|`MOUSE_EXTENDED_REPORT` | (Optional) Enables support for extended mouse reports. (-32767 to 32767, instead of just -127 to 127) |
!> If there is a `_RIGHT` configuration option or callback, the [common configuration](feature_pointing_device.md?id=common-configuration) option will work for the left. For correct left/right detection you should setup a [handedness option](feature_split_keyboard?id=setting-handedness), `EE_HANDS` is usually a good option for an existing board that doesn't do handedness by hardware.
diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md
index 295e610fc4..247b77bcb1 100644
--- a/docs/feature_rgb_matrix.md
+++ b/docs/feature_rgb_matrix.md
@@ -86,6 +86,7 @@ You can use between 1 and 4 IS31FL3733 IC's. Do not specify `DRIVER_ADDR_<N>` de
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3733B only | 0 |
+| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
@@ -172,6 +173,7 @@ Configure the hardware via your `config.h`:
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3737B only | 0 |
+| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
@@ -409,6 +411,7 @@ You can use up to 2 AW20216 IC's. Do not specify `DRIVER_<N>_xxx` defines for IC
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `AW_SCALING_MAX` | (Optional) LED current scaling value (0-255, higher values mean LED is brighter at full PWM) | 150 |
| `AW_GLOBAL_CURRENT_MAX` | (Optional) Driver global current limit (0-255, higher values means the driver may consume more power) | 150 |
+| `AW_SPI_MODE` | (Optional) Mode for SPI communication (0-3, defines polarity and phase of the clock) | 3 |
| `AW_SPI_DIVISOR` | (Optional) Clock divisor for SPI communication (powers of 2, smaller numbers means faster communication, should not be less than 4) | 4 |
Here is an example using 2 drivers.
@@ -665,7 +668,22 @@ In order to change the delay of temperature decrease define `RGB_MATRIX_TYPING_H
#define RGB_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS 50
```
-Heatmap effect may not light up the correct adjacent LEDs for certain key matrix layout such as split keyboards. The following define will limit the effect to pressed keys only:
+As heatmap uses the physical position of the leds set in the g_led_config, you may need to tweak the following options to get the best effect for your keyboard. Note the size of this grid is `224x64`.
+
+Limit the distance the effect spreads to surrounding keys.
+
+```c
+#define RGB_MATRIX_TYPING_HEATMAP_SPREAD 40
+```
+
+Limit how hot surrounding keys get from each press.
+
+```c
+#define RGB_MATRIX_TYPING_HEATMAP_AREA_LIMIT 16
+```
+
+Remove the spread effect entirely.
+
```c
#define RGB_MATRIX_TYPING_HEATMAP_SLIM
```
diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md
index eefafdbf75..e53b3525cb 100644
--- a/docs/feature_split_keyboard.md
+++ b/docs/feature_split_keyboard.md
@@ -143,6 +143,9 @@ Next, you will have to flash the EEPROM files once for the correct hand to the c
* ARM controllers with a DFU compatible bootloader (e.g. Proton-C):
* `:dfu-util-split-left`
* `:dfu-util-split-right`
+* ARM controllers with a UF2 compatible bootloader:
+ * `:uf2-split-left`
+ * `:uf2-split-right`
Example:
@@ -367,7 +370,7 @@ There are some settings that you may need to configure, based on how the hardwar
#define MATRIX_COL_PINS_RIGHT { <col pins> }
```
-This allows you to specify a different set of pins for the matrix on the right side. This is useful if you have a board with differently-shaped halves that requires a different configuration (such as Keebio's Quefrency).
+This allows you to specify a different set of pins for the matrix on the right side. This is useful if you have a board with differently-shaped halves that requires a different configuration (such as Keebio's Quefrency). The number of pins in the right and left matrices must be the same, if you have a board with a different number of rows or columns on one side, pad out the extra spaces with `NO_PIN` and make sure you add the unused rows or columns to your matrix.
```c
#define DIRECT_PINS_RIGHT { { F1, F0, B0, C7 }, { F4, F5, F6, F7 } }
diff --git a/docs/feature_stenography.md b/docs/feature_stenography.md
index 2b52bb17a6..e13fe845c5 100644
--- a/docs/feature_stenography.md
+++ b/docs/feature_stenography.md
@@ -8,46 +8,107 @@ The [Open Steno Project](https://www.openstenoproject.org/) has built an open-so
Plover can work with any standard QWERTY keyboard, although it is more efficient if the keyboard supports NKRO (n-key rollover) to allow Plover to see all the pressed keys at once. An example keymap for Plover can be found in `planck/keymaps/default`. Switching to the `PLOVER` layer adjusts the position of the keyboard to support the number bar.
-To use Plover with QMK just enable NKRO and optionally adjust your layout if you have anything other than a standard layout. You may also want to purchase some steno-friendly keycaps to make it easier to hit multiple keys.
+To enable NKRO, add `NKRO_ENABLE = yes` in your `rules.mk` and make sure to press `NK_ON` to turn it on because `NKRO_ENABLE = yes` merely adds the possibility of switching to NKRO mode but it doesn't automatically switch to it. If you want to automatically switch, add `#define FORCE_NKRO` in your `config.h`.
+
+You may also need to adjust your layout, either in QMK or in Plover, if you have anything other than a standard layout. You may also want to purchase some steno-friendly keycaps to make it easier to hit multiple keys.
## Plover with Steno Protocol :id=plover-with-steno-protocol
-Plover also understands the language of several steno machines. QMK can speak a couple of these languages, TX Bolt and GeminiPR. An example layout can be found in `planck/keymaps/steno`.
+Plover also understands the language of several steno machines. QMK can speak a couple of these languages: TX Bolt and GeminiPR. An example layout can be found in `planck/keymaps/steno`.
+
+When QMK speaks to Plover over a steno protocol, Plover will not use the keyboard as input. This means that you can switch back and forth between a standard keyboard and your steno keyboard, or even switch layers from Plover to standard and back without needing to activate/deactivate Plover.
+
+In this mode, Plover expects to speak with a steno machine over a serial port so QMK will present itself to the operating system as a virtual serial port in addition to a keyboard.
-When QMK speaks to Plover over a steno protocol Plover will not use the keyboard as input. This means that you can switch back and forth between a standard keyboard and your steno keyboard, or even switch layers from Plover to standard and back without needing to activate/deactivate Plover.
+> Note: Due to hardware limitations, you might not be able to run both a virtual serial port and mouse emulation at the same time.
-In this mode Plover expects to speak with a steno machine over a serial port so QMK will present itself to the operating system as a virtual serial port in addition to a keyboard. By default QMK will speak the TX Bolt protocol but can be switched to GeminiPR; the last protocol used is stored in non-volatile memory so QMK will use the same protocol on restart.
+!> Serial stenography protocols are not supported on [V-USB keyboards](compatible_microcontrollers#atmel-avr).
-> Note: Due to hardware limitations you may not be able to run both a virtual serial port and mouse emulation at the same time.
+To enable stenography protocols, add the following lines to your `rules.mk`:
+```mk
+STENO_ENABLE = yes
+```
### TX Bolt :id=tx-bolt
-TX Bolt communicates the status of 24 keys over a very simple protocol in variable-sized (1-5 byte) packets.
+TX Bolt communicates the status of 24 keys over a simple protocol in variable-sized (1&ndash;4 bytes) packets.
-### GeminiPR :id=geminipr
+To select TX Bolt, add the following lines to your `rules.mk`:
+```mk
+STENO_ENABLE = yes
+STENO_PROTOCOL = txbolt
+```
-GeminiPR encodes 42 keys into a 6-byte packet. While TX Bolt contains everything that is necessary for standard stenography, GeminiPR opens up many more options, including supporting non-English theories.
+Each byte of the packet represents a different group of steno keys. Determining the group of a certain byte of the packet is done by checking the first two bits, the remaining bits are set if the corresponding steno key was pressed for the stroke. The last set of keys (as indicated by leading `11`) needs to keep track of less keys than there are bits so one of the bits is constantly 0.
-## Configuring QMK for Steno :id=configuring-qmk-for-steno
+The start of a new packet can be detected by comparing the group “ID†(the two MSBs) of the current byte to that of the previously received byte. If the group “ID†of the current byte is smaller or equal to that of the previous byte, it means that the current byte is the beginning of a new packet.
-Firstly, enable steno in your keymap's Makefile. You may also need disable mousekeys, extra keys, or another USB endpoint to prevent conflicts. The builtin USB stack for some processors only supports a certain number of USB endpoints and the virtual serial port needed for steno fills 3 of them.
+The format of TX Bolt packets is shown below.
+```
+00HWPKTS 01UE*OAR 10GLBPRF 110#ZDST
+```
+
+Examples of steno strokes and the associated packet:
+- `EUBG` = `01110000 10101000`
+- `WAZ` = `00010000 01000010 11001000`
+- `PHAPBGS` = `00101000 01000010 10101100 11000010`
+
+### GeminiPR :id=geminipr
+
+GeminiPR encodes 42 keys into a 6-byte packet. While TX Bolt contains everything that is necessary for standard stenography, GeminiPR opens up many more options, including differentiating between top and bottom `S-`, and supporting non-English theories.
-```make
+To select GeminiPR, add the following lines to your `rules.mk`:
+```mk
STENO_ENABLE = yes
-MOUSEKEY_ENABLE = no
+STENO_PROTOCOL = geminipr
```
-In your keymap create a new layer for Plover. You will need to include `keymap_steno.h`. See `planck/keymaps/steno/keymap.c` for an example. Remember to create a key to switch to the layer as well as a key for exiting the layer. If you would like to switch modes on the fly you can use the keycodes `QK_STENO_BOLT` and `QK_STENO_GEMINI`. If you only want to use one of the protocols you may set it up in your initialization function:
+All packets in the GeminiPR protocol consist of exactly six bytes, used as bit-arrays for different groups of keys. The beginning of a packet is indicated by setting the most significant bit (MSB) to 1 while setting the MSB of the remaining five bytes to 0.
-```c
-void eeconfig_init_user() {
- steno_set_mode(STENO_MODE_GEMINI); // or STENO_MODE_BOLT
-}
+The format of GeminiPR packets is shown below.
+```
+1 Fn #1 #2 #3 #4 #5 #6
+0 S1- S2- T- K- P- W- H-
+0 R- A- O- *1 *2 res1 res2
+0 pwr *3 *4 -E -U -F -R
+0 -P -B -L -G -T -S -D
+0 #7 #8 #9 #A #B #C -Z
```
-Once you have your keyboard flashed launch Plover. Click the 'Configure...' button. In the 'Machine' tab select the Stenotype Machine that corresponds to your desired protocol. Click the 'Configure...' button on this tab and enter the serial port or click 'Scan'. Baud rate is fine at 9600 (although you should be able to set as high as 115200 with no issues). Use the default settings for everything else (Data Bits: 8, Stop Bits: 1, Parity: N, no flow control).
+Examples of steno strokes and the associated packet:
+- `EUBG` = `10000000 00000000 00000000 00001100 00101000 00000000`
+- `WAZ` = `10000000 00000010 00100000 00000000 00000000 00000001`
+- `PHAPBGS` = `10000000 00000101 00100000 00000000 01101010 00000000`
-On the display tab click 'Open stroke display'. With Plover disabled you should be able to hit keys on your keyboard and see them show up in the stroke display window. Use this to make sure you have set up your keymap correctly. You are now ready to steno!
+### Switching protocols on the fly :id=switching-protocols-on-the-fly
+
+If you wish to switch the serial protocol used to transfer the steno chords without having to recompile your keyboard firmware every time, you can press the `QK_STENO_BOLT` and `QK_STENO_GEMINI` keycodes in order to switch protocols on the fly.
+
+To enable these special keycodes, add the following lines to your `rules.mk`:
+```mk
+STENO_ENABLE = yes
+STENO_PROTOCOL = all
+```
+
+If you want to switch protocols programatically, as part of a custom macro for example, don't use `tap_code(QK_STENO_*)`, as `tap_code` only supports [basic keycodes](keycodes_basic). Instead, you should use `steno_set_mode(STENO_MODE_*)`, whose valid arguments are `STENO_MODE_BOLT` and `STENO_MODE_GEMINI`.
+
+The default protocol is Gemini PR but the last protocol used is stored in non-volatile memory so QMK will remember your choice between reboots of your keyboard &mdash; assuming that your keyboard features (emulated) EEPROM.
+
+Naturally, this option takes the most amount of firmware space as it needs to compile the code for all the available stenography protocols. In most cases, compiling a single stenography protocol is sufficient.
+
+The default value for `STENO_PROTOCOL` is `all`.
+
+## Configuring QMK for Steno :id=configuring-qmk-for-steno
+
+After enabling stenography and optionally selecting a protocol, you may also need disable mouse keys, extra keys, or another USB endpoint to prevent conflicts. The builtin USB stack for some processors only supports a certain number of USB endpoints and the virtual serial port needed for steno fills 3 of them.
+
+!> If you had *explicitly* set `VIRSTER_ENABLE = no`, none of the serial stenography protocols (GeminiPR, TX Bolt) will work properly. You are expected to either set it to `yes`, remove the line from your `rules.mk` or send the steno chords yourself in an alternative way using the [provided interceptable hooks](#interfacing-with-the-code).
+
+In your keymap, create a new layer for Plover, that you can fill in with the [steno keycodes](#keycode-reference) (you will need to include `keymap_steno.h`, see `planck/keymaps/steno/keymap.c` for an example). Remember to create a key to switch to the layer as well as a key for exiting the layer.
+
+Once you have your keyboard flashed, launch Plover. Click the 'Configure...' button. In the 'Machine' tab, select the Stenotype Machine that corresponds to your desired protocol. Click the 'Configure...' button on this tab and enter the serial port or click 'Scan'. Baud rate is fine at 9600 (although you should be able to set as high as 115200 with no issues). Use the default settings for everything else (Data Bits: 8, Stop Bits: 1, Parity: N, no flow control).
+
+To test your keymap, you can chord keys on your keyboard and either look at the output of the 'paper tape' (Tools > Paper Tape) or that of the 'layout display' (Tools > Layout Display). If your strokes correctly show up, you are now ready to steno!
## Learning Stenography :id=learning-stenography
@@ -60,7 +121,7 @@ On the display tab click 'Open stroke display'. With Plover disabled you should
The steno code has three interceptable hooks. If you define these functions, they will be called at certain points in processing; if they return true, processing continues, otherwise it's assumed you handled things.
```c
-bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]);
+bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE]);
```
This function is called when a chord is about to be sent. Mode will be one of `STENO_MODE_BOLT` or `STENO_MODE_GEMINI`. This represents the actual chord that would be sent via whichever protocol. You can modify the chord provided to alter what gets sent. Remember to return true if you want the regular sending process to happen.
@@ -72,15 +133,23 @@ bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; }
This function is called when a keypress has come in, before it is processed. The keycode should be one of `QK_STENO_BOLT`, `QK_STENO_GEMINI`, or one of the `STN_*` key values.
```c
-bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[6], int8_t pressed);
+bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE], int8_t n_pressed_keys);
```
-This function is called after a key has been processed, but before any decision about whether or not to send a chord. If `IS_PRESSED(record->event)` is false, and `pressed` is 0 or 1, the chord will be sent shortly, but has not yet been sent. This is where to put hooks for things like, say, live displays of steno chords or keys.
+This function is called after a key has been processed, but before any decision about whether or not to send a chord. This is where to put hooks for things like, say, live displays of steno chords or keys.
+
+If `IS_PRESSED(record->event)` is false, and `n_pressed_keys` is 0 or 1, the chord will be sent shortly, but has not yet been sent. This relieves you of the need of keeping track of where a packet ends and another begins.
+
+The `chord` argument contains the packet of the current chord as specified by the protocol in use. This is *NOT* simply a list of chorded steno keys of the form `[STN_E, STN_U, STN_BR, STN_GR]`. Refer to the appropriate protocol section of this document to learn more about the format of the packets in your steno protocol/mode of choice.
+The `n_pressed_keys` argument is the number of physical keys actually being held down.
+This is not always equal to the number of bits set to 1 (aka the [Hamming weight](https://en.wikipedia.org/wiki/Hamming_weight)) in `chord` because it is possible to simultaneously press down four keys, then release three of those four keys and then press yet another key while the fourth finger is still holding down its key.
+At the end of this scenario given as an example, `chord` would have five bits set to 1 but
+`n_pressed_keys` would be set to 2 because there are only two keys currently being pressed down.
## Keycode Reference :id=keycode-reference
-As defined in `keymap_steno.h`.
+You must include `keymap_steno.h` to your `keymap.c` with `#include "keymap_steno.h"` before you can use these keycodes
> Note: TX Bolt does not support the full set of keys. The TX Bolt implementation in QMK will map the GeminiPR keys to the nearest TX Bolt key so that one key map will work for both.
@@ -124,10 +193,10 @@ As defined in `keymap_steno.h`.
|`STN_SR`|`STN_SR`| `-S`|
|`STN_DR`|`STN_DR`| `-D`|
|`STN_ZR`|`STN_ZR`| `-Z`|
-|`STN_FN`|| (GeminiPR only)|
-|`STN_RES1`||(GeminiPR only)|
-|`STN_RES2`||(GeminiPR only)|
-|`STN_PWR`||(GeminiPR only)|
+|`STN_FN`|| (Function)|
+|`STN_RES1`||(Reset 1)|
+|`STN_RES2`||(Reset 2)|
+|`STN_PWR`||(Power)|
If you do not want to hit two keys with one finger combined keycodes can be used. These are also defined in `keymap_steno.h`, and causes both keys to be reported as pressed or released. To use these keycodes define `STENO_COMBINEDMAP` in your `config.h` file.
diff --git a/docs/feature_tap_dance.md b/docs/feature_tap_dance.md
index c055a9989a..05134ec229 100644
--- a/docs/feature_tap_dance.md
+++ b/docs/feature_tap_dance.md
@@ -14,55 +14,48 @@ Optionally, you might want to set a custom `TAPPING_TERM` time by adding somethi
```c
#define TAPPING_TERM 175
+#define TAPPING_TERM_PER_KEY
```
-The `TAPPING_TERM` time is the maximum time allowed between taps of your Tap Dance key, and is measured in milliseconds. For example, if you used the above `#define` statement and set up a Tap Dance key that sends `Space` on single-tap and `Enter` on double-tap, then this key will send `ENT` only if you tap this key twice in less than 175ms. If you tap the key, wait more than 175ms, and tap the key again you'll end up sending `SPC SPC` instead.
+The `TAPPING_TERM` time is the maximum time allowed between taps of your Tap Dance key, and is measured in milliseconds. For example, if you used the above `#define` statement and set up a Tap Dance key that sends `Space` on single-tap and `Enter` on double-tap, then this key will send `ENT` only if you tap this key twice in less than 175ms. If you tap the key, wait more than 175ms, and tap the key again you'll end up sending `SPC SPC` instead. The `TAPPING_TERM_PER_KEY` definition is only needed if you control the tapping term through a [custom `get_tapping_term` function](tap_hold.md#tapping_term), which may be needed because `TAPPING_TERM` affects not just tap-dance keys.
-Next, you will want to define some tap-dance keys, which is easiest to do with the `TD()` macro, that takes a number which will later be used as an index into the `tap_dance_actions` array.
+Next, you will want to define some tap-dance keys, which is easiest to do with the `TD()` macro. That macro takes a number which will later be used as an index into the `tap_dance_actions` array and turns it into a tap-dance keycode.
After this, you'll want to use the `tap_dance_actions` array to specify what actions shall be taken when a tap-dance key is in action. Currently, there are five possible options:
* `ACTION_TAP_DANCE_DOUBLE(kc1, kc2)`: Sends the `kc1` keycode when tapped once, `kc2` otherwise. When the key is held, the appropriate keycode is registered: `kc1` when pressed and held, `kc2` when tapped once, then pressed and held.
* `ACTION_TAP_DANCE_LAYER_MOVE(kc, layer)`: Sends the `kc` keycode when tapped once, or moves to `layer`. (this functions like the `TO` layer keycode).
- * This is the same as `ACTION_TAP_DANCE_DUAL_ROLE`, but renamed to something that is clearer about its functionality. Both names will work.
* `ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer)`: Sends the `kc` keycode when tapped once, or toggles the state of `layer`. (this functions like the `TG` layer keycode).
* `ACTION_TAP_DANCE_FN(fn)`: Calls the specified function - defined in the user keymap - with the final tap count of the tap dance action.
* `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn)`: Calls the first specified function - defined in the user keymap - on every tap, the second function when the dance action finishes (like the previous option), and the last function when the tap dance action resets.
-* ~~`ACTION_TAP_DANCE_FN_ADVANCED_TIME(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn, tap_specific_tapping_term)`~~: This functions identically to the `ACTION_TAP_DANCE_FN_ADVANCED` function, but uses a custom tapping term for it, instead of the predefined `TAPPING_TERM`.
- * This is deprecated in favor of the Per Key Tapping Term functionality, as outlined [here](tap_hold.md#tapping-term). You'd want to check for the specific `TD()` macro that you want to use (such as `TD(TD_ESC_CAPS)`) instead of using this specific Tap Dance function.
The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise.
!> Keep in mind that only [basic keycodes](keycodes_basic.md) are supported here. Custom keycodes are not supported.
-Similar to the first option, the second option is good for simple layer-switching cases.
+Similar to the first option, the second and third option are good for simple layer-switching cases.
-For more complicated cases, use the third or fourth options (examples of each are listed below).
-
-Finally, the fifth option is particularly useful if your non-Tap-Dance keys start behaving weirdly after adding the code for your Tap Dance keys. The likely problem is that you changed the `TAPPING_TERM` time to make your Tap Dance keys easier for you to use, and that this has changed the way your other keys handle interrupts.
+For more complicated cases, like blink the LEDs, fiddle with the backlighting, and so on, use the fourth or fifth option. Examples of each are listed below.
## Implementation Details :id=implementation
Well, that's the bulk of it! You should now be able to work through the examples below, and to develop your own Tap Dance functionality. But if you want a deeper understanding of what's going on behind the scenes, then read on for the explanation of how it all works!
-The main entry point is `process_tap_dance()`, called from `process_record_quantum()`, which is run for every keypress, and our handler gets to run early. This function checks whether the key pressed is a tap-dance key. If it is not, and a tap-dance was in action, we handle that first, and enqueue the newly pressed key. If it is a tap-dance key, then we check if it is the same as the already active one (if there's one active, that is). If it is not, we fire off the old one first, then register the new one. If it was the same, we increment the counter and reset the timer.
-
-This means that you have `TAPPING_TERM` time to tap the key again; you do not have to input all the taps within a single `TAPPING_TERM` timeframe. This allows for longer tap counts, with minimal impact on responsiveness.
+Let's go over the three functions mentioned in `ACTION_TAP_DANCE_FN_ADVANCED` in a little more detail. They all receive the same too arguments: a pointer to a structure that holds all dance related state information, and a pointer to a use case specific state variable. The three functions differ in when they are called. The first, `on_each_tap_fn()`, is called every time the tap dance key is *pressed*. Before it is called, the counter is incremented and the timer is reset. The second function, `on_dance_finished_fn()`, is called when the tap dance is interrupted or ends because `TAPPING_TERM` milliseconds have passed since the last tap. When the `finished` field of the dance state structure is set to `true`, the `on_dance_finished_fn()` is skipped. After `on_dance_finished_fn()` was called or would have been called, but no sooner than when the tap dance key is *released*, `on_dance_reset_fn()` is called. It is possible to end a tap dance immediately, skipping `on_dance_finished_fn()`, but not `on_dance_reset_fn`, by calling `reset_tap_dance(state)`.
-Our next stop is `tap_dance_task()`. This handles the timeout of tap-dance keys.
+To accomplish this logic, the tap dance mechanics use three entry points. The main entry point is `process_tap_dance()`, called from `process_record_quantum()` *after* `process_record_kb()` and `process_record_user()`. This function is responsible for calling `on_each_tap_fn()` and `on_dance_reset_fn()`. In order to handle interruptions of a tap dance, another entry point, `preprocess_tap_dance()` is run right at the beginning of `process_record_quantum()`. This function checks whether the key pressed is a tap-dance key. If it is not, and a tap-dance was in action, we handle that first, and enqueue the newly pressed key. If it is a tap-dance key, then we check if it is the same as the already active one (if there's one active, that is). If it is not, we fire off the old one first, then register the new one. Finally, `tap_dance_task()` periodically checks whether `TAPPING_TERM` has passed since the last key press and finishes a tap dance if that is the case.
-For the sake of flexibility, tap-dance actions can be either a pair of keycodes, or a user function. The latter allows one to handle higher tap counts, or do extra things, like blink the LEDs, fiddle with the backlighting, and so on. This is accomplished by using an union, and some clever macros.
+This means that you have `TAPPING_TERM` time to tap the key again; you do not have to input all the taps within a single `TAPPING_TERM` timeframe. This allows for longer tap counts, with minimal impact on responsiveness.
## Examples :id=examples
-### Simple Example :id=simple-example
+### Simple Example: Send `ESC` on Single Tap, `CAPS_LOCK` on Double Tap :id=simple-example
Here's a simple example for a single definition:
1. In your `rules.mk`, add `TAP_DANCE_ENABLE = yes`
-2. In your `config.h` (which you can copy from `qmk_firmware/keyboards/planck/config.h` to your keymap directory), add `#define TAPPING_TERM 200`
-3. In your `keymap.c` file, define the variables and definitions, then add to your keymap:
+2. In your `keymap.c` file, define the variables and definitions, then add to your keymap:
```c
// Tap Dance declarations
@@ -92,40 +85,15 @@ All the enums used in the examples are declared like this:
```c
// Enums defined for all examples:
enum {
- CT_SE,
- CT_CLN,
+ TD_ESC_CAPS,
CT_EGG,
CT_FLSH,
- X_TAP_DANCE
-};
-```
-
-#### Example 1: Send `:` on Single Tap, `;` on Double Tap :id=example-1
-
-```c
-void dance_cln_finished(qk_tap_dance_state_t *state, void *user_data) {
- if (state->count == 1) {
- register_code16(KC_COLN);
- } else {
- register_code(KC_SCLN);
- }
-}
-
-void dance_cln_reset(qk_tap_dance_state_t *state, void *user_data) {
- if (state->count == 1) {
- unregister_code16(KC_COLN);
- } else {
- unregister_code(KC_SCLN);
- }
-}
-
-// All tap dance functions would go here. Only showing this one.
-qk_tap_dance_action_t tap_dance_actions[] = {
- [CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_cln_finished, dance_cln_reset),
+ CT_CLN,
+ X_CTL,
};
```
-#### Example 2: Send "Safety Dance!" After 100 Taps :id=example-2
+#### Example 1: Send "Safety Dance!" After 100 Taps :id=example-1
```c
void dance_egg(qk_tap_dance_state_t *state, void *user_data) {
@@ -140,7 +108,7 @@ qk_tap_dance_action_t tap_dance_actions[] = {
};
```
-#### Example 3: Turn LED Lights On Then Off, One at a Time :id=example-3
+#### Example 2: Turn LED Lights On Then Off, One at a Time :id=example-2
```c
// On each tap, light up one LED, from right to left
@@ -181,15 +149,74 @@ void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
ergodox_right_led_3_off();
}
-// All tap dances now put together. Example 3 is "CT_FLASH"
+// All tap dances now put together. Example 2 is "CT_FLSH"
qk_tap_dance_action_t tap_dance_actions[] = {
- [CT_SE] = ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT),
- [CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_cln_finished, dance_cln_reset),
+ [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
[CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg),
[CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset)
};
```
+#### Example 3: Send `:` on Tap, `;` on Hold :id=example-3
+
+With a little effort, powerful tap-hold configurations can be implemented as tap dances. To emit taps as early as possible, we need to act on releases of the tap dance key. There is no callback for this in the tap dance framework, so we use `process_record_user()`.
+
+```c
+typedef struct {
+ uint16_t tap;
+ uint16_t hold;
+ uint16_t held;
+} tap_dance_tap_hold_t;
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ qk_tap_dance_action_t *action;
+
+ switch (keycode) {
+ case TD(CT_CLN): // list all tap dance keycodes with tap-hold configurations
+ action = &tap_dance_actions[TD_INDEX(keycode)];
+ if (!record->event.pressed && action->state.count && !action->state.finished) {
+ tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
+ tap_code16(tap_hold->tap);
+ }
+ }
+ return true;
+}
+
+void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) {
+ tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
+
+ if (state->pressed) {
+ if (state->count == 1
+#ifndef PERMISSIVE_HOLD
+ && !state->interrupted
+#endif
+ ) {
+ register_code16(tap_hold->hold);
+ tap_hold->held = tap_hold->hold;
+ } else {
+ register_code16(tap_hold->tap);
+ tap_hold->held = tap_hold->tap;
+ }
+ }
+}
+
+void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) {
+ tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
+
+ if (tap_hold->held) {
+ unregister_code16(tap_hold->held);
+ tap_hold->held = 0;
+ }
+}
+
+#define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \
+ { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), }
+
+qk_tap_dance_action_t tap_dance_actions[] = {
+ [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN),
+};
+```
+
#### Example 4: 'Quad Function Tap-Dance' :id=example-4
By [DanielGGordon](https://github.com/danielggordon)
@@ -329,7 +356,7 @@ And then simply use `TD(X_CTL)` anywhere in your keymap.
If you want to implement this in your userspace, then you may want to check out how [DanielGGordon](https://github.com/qmk/qmk_firmware/tree/master/users/gordon) has implemented this in their userspace.
-> In this configuration "hold" takes place **after** tap dance timeout (see `ACTION_TAP_DANCE_FN_ADVANCED_TIME`). To achieve instant hold, remove `state->interrupted` checks in conditions. As a result you may use comfortable longer tapping periods to have more time for taps and not to wait too long for holds (try starting with doubled `TAPPING_TERM`).
+> In this configuration "hold" takes place **after** tap dance timeout. To achieve instant hold, remove `state->interrupted` checks in conditions. As a result you may use comfortable longer tapping periods to have more time for taps and not to wait too long for holds (try starting with doubled `TAPPING_TERM`).
#### Example 5: Using tap dance for advanced mod-tap and layer-tap keys :id=example-5
@@ -511,8 +538,18 @@ void ql_reset(qk_tap_dance_state_t *state, void *user_data) {
// Associate our tap dance key with its functionality
qk_tap_dance_action_t tap_dance_actions[] = {
- [QUOT_LAYR] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, ql_finished, ql_reset, 275)
+ [QUOT_LAYR] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ql_finished, ql_reset)
};
+
+// Set a long-ish tapping term for tap-dance keys
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
+ return 275;
+ default:
+ return TAPPING_TERM;
+ }
+}
```
The above code is similar to that used in previous examples. The one point to note is that we need to be able to check which layers are active at any time so we can toggle them if needed. To do this we use the `layer_state_is(layer)` function which returns `true` if the given `layer` is active.
@@ -521,6 +558,6 @@ The use of `cur_dance()` and `ql_tap_state` mirrors the above examples.
The `case: TD_SINGLE_TAP` in `ql_finished` is similar to the above examples. The `TD_SINGLE_HOLD` case works in conjunction with `ql_reset()` to switch to `_MY_LAYER` while the tap dance key is held, and to switch away from `_MY_LAYER` when the key is released. This mirrors the use of `MO(_MY_LAYER)`. The `TD_DOUBLE_TAP` case works by checking whether `_MY_LAYER` is the active layer, and toggling it on or off accordingly. This mirrors the use of `TG(_MY_LAYER)`.
-`tap_dance_actions[]` works similar to the above examples. Note that I used `ACTION_TAP_DANCE_FN_ADVANCED_TIME()` instead of `ACTION_TAP_DANCE_FN_ADVANCED()`. This is because I like my `TAPPING_TERM` to be short (\~175ms) for my non-tap-dance keys but find that this is too quick for me to reliably complete tap dance actions - thus the increased time of 275ms here.
+`tap_dance_actions[]` works similar to the above examples. Note that, additionally, I set a longer tapping term for the tap dance keys. This is because I like my `TAPPING_TERM` to be short (\~175ms) for my non-tap-dance keys but find that this is too quick for me to reliably complete tap dance actions - thus the increased time of 275ms here. In order for the per-key tapping terms to take effect, `TAPPING_TERM_PER_KEY` must be defined in your `config.h`.
Finally, to get this tap dance key working, be sure to include `TD(QUOT_LAYR)` in your `keymaps[]`.
diff --git a/docs/feature_terminal.md b/docs/feature_terminal.md
deleted file mode 100644
index f850622165..0000000000
--- a/docs/feature_terminal.md
+++ /dev/null
@@ -1,107 +0,0 @@
-# Terminal
-
-> This feature is currently *huge*, and should probably only be put on boards with a lot of memory, or for fun.
-
-The terminal feature is a command-line-like interface designed to communicate through a text editor with keystrokes. It's beneficial to turn off auto-indent features in your editor.
-
-To enable, stick this in your `rules.mk` or `Makefile`:
-
- TERMINAL_ENABLE = yes
-
-And use the `TERM_ON` and `TERM_OFF` keycodes to turn it on or off.
-
-When enabled, a `> ` prompt will appear, where you'll be able to type, backspace (a bell will ding if you reach the beginning and audio is enabled), and hit enter to send the command. Arrow keys are currently disabled so it doesn't get confused. Moving your cursor around with the mouse is discouraged.
-
-`#define TERMINAL_HELP` enables some other output helpers that aren't really needed with this page.
-
-Pressing "up" and "down" will allow you to cycle through the past 5 commands entered.
-
-## Future Ideas
-
-* Keyboard/user-extensible commands
-* Smaller footprint
-* Arrow key support
-* Command history - Done
-* SD card support
-* LCD support for buffer display
-* Keycode -> name string LUT
-* Layer status
-* *Analog/digital port read/write*
-* RGB mode stuff
-* Macro definitions
-* EEPROM read/write
-* Audio control
-
-## Current Commands
-
-### `about`
-
-Prints out the current version of QMK with a build date:
-
-```
-> about
-QMK Firmware
- v0.5.115-7-g80ed73-dirty
- Built: 2017-08-29-20:24:44
-```
-
-
-### `print-buffer`
-
-Outputs the last 5 commands entered
-
-```
-> print-buffer
-0. print-buffer
-1. help
-2. about
-3. keymap 0
-4. help
-5. flush-buffer
-```
-
-### `flush-buffer`
-
-Clears command buffer
-```
-> flush-buffer
-Buffer cleared!
-```
-
-
-### `help`
-
-
-Prints out the available commands:
-
-```
-> help
-commands available:
- about help keycode keymap exit print-buffer flush-buffer
-```
-
-### `keycode <layer> <row> <col>`
-
-Prints out the keycode value of a certain layer, row, and column:
-
-```
-> keycode 0 1 0
-0x29 (41)
-```
-
-### `keymap <layer>`
-
-Prints out the entire keymap for a certain layer
-
-```
-> keymap 0
-0x002b, 0x0014, 0x001a, 0x0008, 0x0015, 0x0017, 0x001c, 0x0018, 0x000c, 0x0012, 0x0013, 0x002a,
-0x0029, 0x0004, 0x0016, 0x0007, 0x0009, 0x000a, 0x000b, 0x000d, 0x000e, 0x000f, 0x0033, 0x0034,
-0x00e1, 0x001d, 0x001b, 0x0006, 0x0019, 0x0005, 0x0011, 0x0010, 0x0036, 0x0037, 0x0038, 0x0028,
-0x5cd6, 0x00e0, 0x00e2, 0x00e3, 0x5cd4, 0x002c, 0x002c, 0x5cd5, 0x0050, 0x0051, 0x0052, 0x004f,
->
-```
-
-### `exit`
-
-Exits the terminal - same as `TERM_OFF`.
diff --git a/docs/flashing.md b/docs/flashing.md
index 271e15b13c..5e5dcb34e4 100644
--- a/docs/flashing.md
+++ b/docs/flashing.md
@@ -358,3 +358,46 @@ CLI Flashing sequence:
2. Wait for the OS to detect the device
3. Flash via QMK CLI eg. `qmk flash --keyboard handwired/onekey/blackpill_f411_tinyuf2 --keymap default`
4. Wait for the keyboard to become available
+
+### `make` Targets
+
+* `:uf2-split-left` and `:uf2-split-right`: Flashes the firmware but also sets the handedness setting in EEPROM by generating a side specific firmware.
+
+## Raspberry Pi RP2040 UF2
+
+The `rules.mk` setting for this bootloader is `rp2040`, and can be specified at the keymap or user level.
+
+To ensure compatibility with the rp2040 bootloader, make sure this block is present in your `rules.mk`:
+
+```make
+# Bootloader selection
+BOOTLOADER = rp2040
+```
+
+Compatible flashers:
+
+* Any application able to copy a file from one place to another, such as _macOS Finder_ or _Windows Explorer_.
+
+Flashing sequence:
+
+1. Enter the bootloader using any of the following methods:
+ * Tap the `QK_BOOTLOADER` keycode
+ * Hold the `BOOTSEL` button on the PCB while plugin in the usb cable.
+ * Double-tap the `RESET` button on the PCB<sup>1</sup>.
+2. Wait for the OS to detect the device
+3. Copy the .uf2 file to the new USB disk
+4. Wait for the keyboard to become available
+
+or
+
+CLI Flashing sequence:
+
+1. Enter the bootloader using any of the following methods:
+ * Tap the `QK_BOOTLOADER` keycode
+ * Hold the `BOOTSEL` button on the PCB while plugin in the usb cable.
+ * Double-tap the `RESET` button on the PCB<sup>1</sup>.
+2. Wait for the OS to detect the device
+3. Flash via QMK CLI eg. `qmk flash --keyboard handwired/onekey/rpi_pico --keymap default`
+4. Wait for the keyboard to become available
+
+<sup>1</sup>: This works only if QMK was compiled with `RP2040_BOOTLOADER_DOUBLE_TAP_RESET` defined.
diff --git a/docs/ja/_summary.md b/docs/ja/_summary.md
index 81b5756c27..8516a5eaaa 100644
--- a/docs/ja/_summary.md
+++ b/docs/ja/_summary.md
@@ -85,7 +85,6 @@
* [スワップãƒãƒ³ãƒ‰](ja/feature_swap_hands.md)
* [タップダンス](ja/feature_tap_dance.md)
* [タップホールド設定](ja/tap_hold.md)
- * [ターミナル](ja/feature_terminal.md)
* [ユニコード](ja/feature_unicode.md)
* [ユーザスペース](ja/feature_userspace.md)
* [WPM 計算](ja/feature_wpm.md)
diff --git a/docs/ja/config_options.md b/docs/ja/config_options.md
index fb43d015f2..42dd9d502a 100644
--- a/docs/ja/config_options.md
+++ b/docs/ja/config_options.md
@@ -144,7 +144,7 @@ QMK ã§ã®å…¨ã¦ã®åˆ©ç”¨å¯èƒ½ãªè¨­å®šã«ã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãŒã‚ã‚Šã¾ã™ã€‚ã
## 設定å¯èƒ½ãªæŒ™å‹• :id=behaviors-that-can-be-configured
* `#define TAPPING_TERM 200`
- * タップãŒãƒ›ãƒ¼ãƒ«ãƒ‰ã«ãªã‚‹ã¾ã§ã®æ™‚間。500以上ã«è¨­å®šã•ã‚ŒãŸå ´åˆã€ã‚¿ãƒƒãƒ—期間中ã«ã‚¿ãƒƒãƒ—ã•ã‚ŒãŸã‚­ãƒ¼ã‚‚ホールドã«ãªã‚Šã¾ã™ã€‚(訳注: PERMISSIVE_HOLDã‚‚å‚ç…§)
+ * タップãŒãƒ›ãƒ¼ãƒ«ãƒ‰ã«ãªã‚‹ã¾ã§ã®æ™‚間。
* `#define TAPPING_TERM_PER_KEY`
* キーã”ã¨ã® `TAPPING_TERM` 設定ã®å‡¦ç†ã‚’有効ã«ã—ã¾ã™
* `#define RETRO_TAPPING`
diff --git a/docs/ja/feature_tap_dance.md b/docs/ja/feature_tap_dance.md
index a6d108f1e9..762816f21b 100644
--- a/docs/ja/feature_tap_dance.md
+++ b/docs/ja/feature_tap_dance.md
@@ -28,7 +28,6 @@
* `ACTION_TAP_DANCE_DOUBLE(kc1, kc2)`: 1回タップã™ã‚‹ã¨ `kc1` キーコードをé€ä¿¡ã—ã€2回タップã™ã‚‹ã¨ `kc2` キーコードをé€ä¿¡ã—ã¾ã™ã€‚キーを押ã—続ã‘ã¦ã„ã‚‹ã¨ãã¯ã€é©åˆ‡ãªã‚­ãƒ¼ã‚³ãƒ¼ãƒ‰ãŒç™»éŒ²ã•ã‚Œã¾ã™: キーを押ã—続ã‘ãŸå ´åˆã¯ `kc1`ã€ä¸€åº¦ã‚¿ãƒƒãƒ—ã—ã¦ã‹ã‚‰ç¶šã‘ã¦ã‚‚ã†ä¸€åº¦ã‚­ãƒ¼ã‚’押ã—ã¦ãã®ã¾ã¾æŠ¼ã—続ã‘ãŸã¨ãã¯ã€ `kc2` ãŒç™»éŒ²ã•ã‚Œã¾ã™ã€‚
* `ACTION_TAP_DANCE_LAYER_MOVE(kc, layer)`: 1回タップã™ã‚‹ã¨ `kc` キーコードãŒé€ä¿¡ã•ã‚Œã€2回タップã™ã‚‹ã¨ `layer` レイヤーã«ç§»å‹•ã—ã¾ã™(ã“れ㯠`TO` レイヤーキーコードã®ã‚ˆã†ã«æ©Ÿèƒ½ã—ã¾ã™)。
- * ã“ã®æ©Ÿèƒ½ã¯ `ACTION_TAP_DANCE_DUAL_ROLE` ã¨åŒã˜ã§ã™ãŒã€æ©Ÿèƒ½ãŒæ˜Žç¢ºã«ãªã‚‹ã‚ˆã†ã«é–¢æ•°åを変更ã—ã¾ã—ãŸã€‚ã©ã¡ã‚‰ã®é–¢æ•°åã§ã‚‚実行ã§ãã¾ã™ã€‚
* `ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer)`: 1回タップã™ã‚‹ã¨ `kc` キーコードãŒé€ä¿¡ã•ã‚Œã€2回タップã™ã‚‹ã¨ `layer` ã®çŠ¶æ…‹ã‚’トグルã—ã¾ã™(ã“れ㯠`TG` レイヤーキーコードã®ã‚ˆã†ã«æ©Ÿèƒ½ã—ã¾ã™)。
* `ACTION_TAP_DANCE_FN(fn)`: ユーザーキーマップã«å®šç¾©ã—ãŸæŒ‡å®šã®é–¢æ•°ãŒå‘¼ã³å‡ºã•ã‚Œã¾ã™ã€‚タップダンス実行ã®å›žæ•°åˆ†ã‚¿ãƒƒãƒ—ã™ã‚‹ã¨ã€æœ€å¾Œã®æ™‚点ã§å‘¼ã³å‡ºã•ã‚Œã¾ã™ã€‚
* `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn)`: タップã™ã‚‹åº¦ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚­ãƒ¼ãƒžãƒƒãƒ—ã«å®šç¾©ã—ãŸæœ€åˆã®é–¢æ•°ãŒå‘¼ã³å‡ºã•ã‚Œã¾ã™ã€‚タップダンスã®å®Ÿè¡ŒãŒçµ‚ã‚ã£ãŸæ™‚点ã§2番目ã®é–¢æ•°ãŒå‘¼ã³å‡ºã•ã‚Œã€ã‚¿ãƒƒãƒ—ダンスã®å®Ÿè¡Œã‚’リセットã™ã‚‹ã¨ãã«æœ€å¾Œã®é–¢æ•°ãŒå‘¼ã³å‡ºã•ã‚Œã¾ã™ã€‚
diff --git a/docs/ja/feature_terminal.md b/docs/ja/feature_terminal.md
deleted file mode 100644
index 8e125ecee0..0000000000
--- a/docs/ja/feature_terminal.md
+++ /dev/null
@@ -1,112 +0,0 @@
-# ターミナル
-
-<!---
- original document: 0.8.147:docs/feature_terminal.md
- git diff 0.8.147 HEAD -- docs/feature_terminal.md | cat
--->
-
-> ã“ã®æ©Ÿèƒ½ã¯ç¾åœ¨ã®ã¨ã“ã‚*巨大*ã§ã‚ã‚Šã€ãŠãらã大é‡ã®ãƒ¡ãƒ¢ãƒªã‚’æ­è¼‰ã—ãŸã‚­ãƒ¼ãƒœãƒ¼ãƒ‰ã€ã¾ãŸã¯æ¥½ã—ã¿ã®ãŸã‚ã«ã®ã¿é…ç½®ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
-
-ターミナル機能ã¯ãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒ‡ã‚£ã‚¿ã‚’介ã—ã¦ã‚­ãƒ¼ã‚¹ãƒˆãƒ­ãƒ¼ã‚¯ã§é€šä¿¡ã™ã‚‹ã‚ˆã†ã«è¨­è¨ˆã•ã‚ŒãŸã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã®ã‚ˆã†ãªã‚¤ãƒ³ã‚¿ãƒ•ã‚§ãƒ¼ã‚¹ã§ã™ã€‚エディタã§è‡ªå‹•ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆæ©Ÿèƒ½ã‚’オフã«ã™ã‚‹ã“ã¨ã¯æœ‰ç›Šã§ã™ã€‚
-
-有効ã«ã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã‚’ `rules.mk` ã¾ãŸã¯ `Makefile` ã«è²¼ã‚Šä»˜ã‘ã¾ã™:
-
- TERMINAL_ENABLE = yes
-
-ãã—ã¦ã€ã‚ªãƒ³ã¾ãŸã¯ã‚ªãƒ•ã«ã™ã‚‹ãŸã‚ã«ã€`TERM_ON` ãŠã‚ˆã³ `TERM_OFF` キーコードを使ã„ã¾ã™ã€‚
-
-有効ãªå ´åˆã€`> ` プロンプトãŒç¾ã‚Œã€ã“ã“ã§ã‚³ãƒžãƒ³ãƒ‰ã‚„ãƒãƒƒã‚¯ã‚¹ãƒšãƒ¼ã‚¹(オーディオãŒæœ‰åŠ¹ãªå ´åˆã¯ã€å…ˆé ­ã«åˆ°é”ã™ã‚‹ã¨ãƒ™ãƒ«ãŒé³´ã‚Šã¾ã™)を入力ã™ã‚‹ã“ã¨ãŒã§ãã€ã‚¨ãƒ³ã‚¿ãƒ¼ã‚’入力ã™ã‚‹ã¨ã‚³ãƒžãƒ³ãƒ‰ã‚’é€ä¿¡ã—ã¾ã™ã€‚矢å°ã‚­ãƒ¼ã¯ç¾åœ¨ã®ã¨ã“ã‚無効ãªãŸã‚ã€æ··ä¹±ã™ã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。マウスã§ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã™ã‚‹ã“ã¨ã¯ãŠå‹§ã‚ã—ã¾ã›ã‚“。
-
-`#define TERMINAL_HELP` ã¯ã€ã“ã®ãƒšãƒ¼ã‚¸ã§ã¯å®Ÿéš›ã«ã¯å¿…è¦ã®ãªã„ä»–ã®å‡ºåŠ›ãƒ˜ãƒ«ãƒ‘ーを有効ã«ã—ã¾ã™ã€‚
-
-"上矢å°" ãŠã‚ˆã³ "下矢å°" ã«ã‚ˆã‚Šã€éŽåŽ»ã«å…¥åŠ›ã—ãŸ5ã¤ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’é †ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-
-## 今後ã®ã‚¢ã‚¤ãƒ‡ã‚¢
-
-* キーボード/ユーザ拡張å¯èƒ½ãªã‚³ãƒžãƒ³ãƒ‰
-* よりå°ã•ãªãƒ•ãƒƒãƒˆãƒ—リント
-* 矢å°ã‚­ãƒ¼ã®ã‚µãƒãƒ¼ãƒˆ
-* コマンド履歴 - 完了
-* SD カードã®ã‚µãƒãƒ¼ãƒˆ
-* ãƒãƒƒãƒ•ã‚¡ãƒ‡ã‚£ã‚¹ãƒ—レイã®ãŸã‚ã® LCD サãƒãƒ¼ãƒˆ
-* キーコード -> å称ã®å¯¾å¿œè¡¨
-* レイヤー状態
-* *アナログ/デジタル ãƒãƒ¼ãƒˆã®èª­ã¿è¾¼ã¿/書ãè¾¼ã¿*
-* RGB モード関連機能
-* マクロ定義
-* EEPROM ã®èª­ã¿è¾¼ã¿/書ãè¾¼ã¿
-* オーディオ制御
-
-## ç¾åœ¨ã®ã‚³ãƒžãƒ³ãƒ‰
-
-### `about`
-
-ç¾åœ¨ã® QMK ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¨ãƒ“ルドã—ãŸæ—¥ã®å‡ºåŠ›:
-
-```
-> about
-QMK Firmware
- v0.5.115-7-g80ed73-dirty
- Built: 2017-08-29-20:24:44
-```
-
-
-### `print-buffer`
-
-最後ã«å…¥åŠ›ã—ãŸ5ã¤ã®ã‚³ãƒžãƒ³ãƒ‰ã®å‡ºåŠ›
-
-```
-> print-buffer
-0. print-buffer
-1. help
-2. about
-3. keymap 0
-4. help
-5. flush-buffer
-```
-
-### `flush-buffer`
-
-コマンドãƒãƒƒãƒ•ã‚¡ã‚’クリア
-```
-> flush-buffer
-Buffer cleared!
-```
-
-
-### `help`
-
-
-利用å¯èƒ½ãªã‚³ãƒžãƒ³ãƒ‰ã®å‡ºåŠ›:
-
-```
-> help
-commands available:
- about help keycode keymap exit print-buffer flush-buffer
-```
-
-### `keycode <layer> <row> <col>`
-
-特定ã®ãƒ¬ã‚¤ãƒ¤ãƒ¼ã€è¡ŒãŠã‚ˆã³åˆ—ã®ã‚­ãƒ¼ã‚³ãƒ¼ãƒ‰å€¤ã®å‡ºåŠ›:
-
-```
-> keycode 0 1 0
-0x29 (41)
-```
-
-### `keymap <layer>`
-
-特定ã®ãƒ¬ã‚¤ãƒ¤ãƒ¼ã®å…¨ã¦ã®ã‚­ãƒ¼ãƒžãƒƒãƒ—ã®å‡ºåŠ›
-
-```
-> keymap 0
-0x002b, 0x0014, 0x001a, 0x0008, 0x0015, 0x0017, 0x001c, 0x0018, 0x000c, 0x0012, 0x0013, 0x002a,
-0x0029, 0x0004, 0x0016, 0x0007, 0x0009, 0x000a, 0x000b, 0x000d, 0x000e, 0x000f, 0x0033, 0x0034,
-0x00e1, 0x001d, 0x001b, 0x0006, 0x0019, 0x0005, 0x0011, 0x0010, 0x0036, 0x0037, 0x0038, 0x0028,
-0x5cd6, 0x00e0, 0x00e2, 0x00e3, 0x5cd4, 0x002c, 0x002c, 0x5cd5, 0x0050, 0x0051, 0x0052, 0x004f,
->
-```
-
-### `exit`
-
-ターミナルã®çµ‚了 - `TERM_OFF` ã¨åŒã˜ã€‚
diff --git a/docs/ja/understanding_qmk.md b/docs/ja/understanding_qmk.md
index 1654f8e002..550ee3a7c0 100644
--- a/docs/ja/understanding_qmk.md
+++ b/docs/ja/understanding_qmk.md
@@ -161,7 +161,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* [`bool process_combo(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_combo.c#L115)
* [`bool process_printer(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_printer.c#L77)
* [`bool process_auto_shift(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_auto_shift.c#L94)
- * [`bool process_terminal(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_terminal.c#L264)
* [Quantum 固有ã®ã‚­ãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’識別ã—ã¦å‡¦ç†ã™ã‚‹](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L291)
ã“ã®ä¸€é€£ã®ã‚¤ãƒ™ãƒ³ãƒˆã®ä¸­ã®ä»»æ„ã®ã‚¹ãƒ†ãƒƒãƒ—㧠(`process_record_kb()` ã®ã‚ˆã†ãª)関数㯠`false` ã‚’è¿”ã—ã¦ã€ä»¥é™ã®å‡¦ç†ã‚’åœæ­¢ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
diff --git a/docs/platformdev_chibios_earlyinit.md b/docs/platformdev_chibios_earlyinit.md
index aaa91ba438..e1256f2714 100644
--- a/docs/platformdev_chibios_earlyinit.md
+++ b/docs/platformdev_chibios_earlyinit.md
@@ -20,7 +20,7 @@ As such, if you wish to override this API consider limiting use to writing to lo
| `#define STM32_BOOTLOADER_DUAL_BANK` | Relevant for dual-bank STM32 MCUs, signifies that a GPIO is to be toggled in order to enter bootloader mode. | `FALSE` |
| `#define STM32_BOOTLOADER_DUAL_BANK_GPIO` | Relevant for dual-bank STM32 MCUs, the pin to toggle when attempting to enter bootloader mode, e.g. `B8` | `<none>` |
| `#define STM32_BOOTLOADER_DUAL_BANK_POLARITY` | Relevant for dual-bank STM32 MCUs, the value to set the pin to in order to trigger charging of the RC circuit. e.g. `0` or `1`. | `0` |
-| `#define STM32_BOOTLOADER_DUAL_BANK_DELAY` | Relevant for dual-bank STM32 MCUs, an arbitrary measurement of time to delay before resetting the MCU. Increasing number increases the delay. | `100000` |
+| `#define STM32_BOOTLOADER_DUAL_BANK_DELAY` | Relevant for dual-bank STM32 MCUs, an arbitrary measurement of time to delay before resetting the MCU. Increasing number increases the delay. | `100` |
Kinetis MCUs have no configurable options.
diff --git a/docs/platformdev_rp2040.md b/docs/platformdev_rp2040.md
new file mode 100644
index 0000000000..d690ebebf8
--- /dev/null
+++ b/docs/platformdev_rp2040.md
@@ -0,0 +1,125 @@
+# Raspberry Pi RP2040
+
+The following table shows the current driver status for peripherals on RP2040 MCUs:
+
+| System | Support |
+| ---------------------------------------------------------------- | ---------------------------------------------- |
+| [ADC driver](adc_driver.md) | Support planned (no ETA) |
+| [Audio](audio_driver.md) | Support planned (no ETA) |
+| [I2C driver](i2c_driver.md) | :heavy_check_mark: |
+| [SPI driver](spi_driver.md) | :heavy_check_mark: |
+| [WS2812 driver](ws2812_driver.md) | :heavy_check_mark: using `PIO` driver |
+| [External EEPROMs](eeprom_driver.md) | :heavy_check_mark: using `I2C` or `SPI` driver |
+| [EEPROM emulation](eeprom_driver.md#wear_leveling-configuration) | :heavy_check_mark: |
+| [serial driver](serial_driver.md) | :heavy_check_mark: using `SIO` or `PIO` driver |
+| [UART driver](uart_driver.md) | Support planned (no ETA) |
+
+## GPIO
+
+<img alt="Raspberry Pi Pico pinout" src="https://i.imgur.com/nLaiYDE.jpg" width="48%"/>
+<img alt="Sparkfun RP2040 Pro Micro pinout" src="https://i.imgur.com/1TPAhrs.jpg" width="48%"/>
+
+!> The GPIO pins of the RP2040 are not 5V tolerant!
+
+### Pin nomenclature
+
+To address individual pins on the RP2040, QMK uses the `GPx` abbreviation -- where the `x` stands for the GPIO number of the pin. This number can likely be found on the official pinout diagram of your board. Note that these GPIO numbers match the RP2040 MCU datasheet, and don't necessarily match the number you see printed on the board. For instance the Raspberry Pi Pico uses numbers from 1 to 40 for their pins, but these are not identical to the RP2040's GPIO numbers. So if you want to use the pin 11 of the Pico for your keyboard, you would refer to it as `GP8` in the config files.
+
+### Alternate functions
+
+The RP2040 features flexible GPIO function multiplexing, this means that every pin can be connected to nearly all the internal peripherals like I2C, SPI, UART or PWM. This allows for flexible PCB designs that are much less restricted in the selection of GPIO pins. To find out which pin can use which peripheral refer to the official [Raspberry PI RP2040 datasheet](https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#page=14) section 1.4.3 GPIO functions.
+
+## Selecting hardware peripherals and drivers
+
+QMK RP2040 support builds upon ChibiOS and thus follows their convention for activating drivers and associated hardware peripherals. These tables only give a quick overview which values have to be used, please refer to the ChibiOS specific sections on the driver pages.
+
+### I2C Driver
+
+| RP2040 Peripheral | `mcuconf.h` values | `I2C_DRIVER` |
+| ----------------- | ------------------ | ------------ |
+| `I2C0` | `RP_I2C_USE_I2C0` | `I2CD1` |
+| `I2C1` | `RP_I2C_USE_I2C1` | `I2CD2` |
+
+To configure the I2C driver please read the [ChibiOS/ARM](i2c_driver.md#arm-configuration) section.
+
+### SPI Driver
+
+| RP2040 Peripheral | `mcuconf.h` values | `SPI_DRIVER` |
+| ----------------- | ------------------ | ------------ |
+| `SPI0` | `RP_SPI_USE_SPI0` | `SPID0` |
+| `SPI1` | `RP_SPI_USE_SPI1` | `SPID1` |
+
+To configure the SPI driver please read the [ChibiOS/ARM](spi_driver.md#chibiosarm-configuration) section.
+
+## Double-tap reset boot-loader entry :id=double-tap
+
+The double-tap reset mechanism is an alternate way in QMK to enter the embedded mass storage UF2 boot-loader of the RP2040. It enables bootloader entry by a fast double-tap of the reset pin on start up, which is similar to the behavior of AVR Pro Micros. This feature activated by default for the Pro Micro RP2040 board, but has to be configured for other boards. To activate it, add the following options to your keyboards `config.h` file:
+
+```c
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET // Activates the double-tap behavior
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 200U // Timeout window in ms in which the double tap can occur.
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED_MASK 0U // Specify a optional status led which blinks when entering the bootloader
+```
+
+## Pre-defined RP2040 boards
+
+QMK defines two boards that you can choose from to base your RP2040 powered keyboard upon. These boards provide pre-configured default pins and drivers.
+
+### Generic Pro Micro RP2040
+
+This is the default board that is chosen, unless any other RP2040 board is selected in your keyboards `rules.mk` file. It assumes a pin layout for the I2C, SPI and Serial drivers which is identical to the Sparkfun Pro Micro RP2040, however all values can be overwritten by defining them in your keyboards `config.h` file. The [double-tap](#double-tap) reset to enter boot-loader behavior is activated by default.
+
+
+| Driver configuration define | Value |
+| -------------------------------------------------------------------------- | ------------------------------------ |
+| **I2C driver** | |
+| `I2C_DRIVER` | `I2CD2` |
+| `I2C1_SDA_PIN` | `GP2` |
+| `I2C1_SCL_PIN` | `GP3` |
+| **SPI driver** | |
+| `SPI_DRIVER` | `SPID0` |
+| `SPI_SCK_PIN` | `GP18` |
+| `SPI_MISO_PIN` | `GP20` |
+| `SPI_MOSI_PIN` | `GP19` |
+| **Serial driver** | |
+| `SERIAL_USART_DRIVER` ([SIO Driver](serial_driver.md#the-sio-driver) only) | `SIOD0` |
+| `SOFT_SERIAL_PIN` | undefined, use `SERIAL_USART_TX_PIN` |
+| `SERIAL_USART_TX_PIN` | `GP0` |
+| `SERIAL_USART_RX_PIN` | `GP1` |
+
+?> The pin-outs of Adafruit's KB2040 and Boardsource's Blok both deviate from the Sparkfun Pro Micro RP2040. Lookup the pin-out of these boards and adjust your keyboards pin definition accordingly if you want to use these boards.
+
+### Generic RP2040 board
+
+This board can be chosen as a base for RP2040 keyboards which configure all necessary pins and drivers themselves and do not wish to leverage the configuration matching the Generic Pro Micro RP2040 board. Thus it doesn't provide any pre-configured pins or drivers. To select this board add the following line to your keyboards `rules.mk` file.
+
+```make
+BOARD = GENERIC_RP_RP2040
+```
+
+## Split keyboard support
+
+Split keyboards are fully supported using the [serial driver](serial_driver.md) in both full-duplex and half-duplex configurations. Two driver subsystems are supported by the RP2040, the hardware UART based `SIO` and the Programmable IO based `PIO` driver.
+
+| Feature | [SIO Driver](serial_driver.md#the-sio-driver) | [PIO Driver](serial_driver.md#the-pio-driver) |
+| ----------------------------- | --------------------------------------------- | --------------------------------------------- |
+| Half-Duplex operation | | :heavy_check_mark: |
+| Full-Duplex operation | :heavy_check_mark: | :heavy_check_mark: |
+| `TX` and `RX` pin swapping | | :heavy_check_mark: |
+| Any GPIO as `TX` and `RX` pin | Only UART capable pins | :heavy_check_mark: |
+| Simple configuration | | :heavy_check_mark: |
+
+The `PIO` driver is much more flexible then the `SIO` driver, the only "downside" is the usage of `PIO` resources which in turn are not available for advanced user programs. Under normal circumstances, this resource allocation will be a non-issue.
+
+## RP2040 second stage bootloader selection
+
+As the RP2040 does not have any internal flash memory it depends on an external SPI flash memory chip to store and execute instructions from. To successfully interact with a wide variety of these chips a second stage bootloader that is compatible with the chosen external flash memory has to be supplied with each firmware image. By default an `W25Q080` compatible bootloader is assumed, but others can be chosen by adding one of the defines listed in the table below to your keyboards `config.h` file.
+
+| Compatible with flash chip | Selection |
+| :------------------------- | ---------------------------------- |
+| W25Q080 | Selected by default |
+| AT25SF128A | `#define RP2040_FLASH_AT25SF128A` |
+| GD25Q64CS | `#define RP2040_FLASH_GD25Q64CS` |
+| W25X10CL | `#define RP2040_FLASH_W25X10CL` |
+| IS25LP080 | `#define RP2040_FLASH_IS25LP080` |
+| Generic 03H flash | `#define RP2040_FLASH_GENERIC_03H` |
diff --git a/docs/quantum_painter.md b/docs/quantum_painter.md
index a3705b62ce..2386a70933 100644
--- a/docs/quantum_painter.md
+++ b/docs/quantum_painter.md
@@ -24,6 +24,7 @@ Hardware supported:
| GC9A01 | RGB LCD (circular) | 240x240 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS = gc9a01_spi` |
| ILI9163 | RGB LCD | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS = ili9163_spi` |
| ILI9341 | RGB LCD | 240x320 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS = ili9341_spi` |
+| ILI9488 | RGB LCD | 320x480 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS = ili9488_spi` |
| SSD1351 | RGB OLED | 128x128 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS = ssd1351_spi` |
| ST7789 | RGB LCD | 240x320, 240x240 | SPI + D/C + RST | `QUANTUM_PAINTER_DRIVERS = st7789_spi` |
@@ -654,6 +655,30 @@ The maximum number of displays can be configured by changing the following in yo
#define ILI9341_NUM_DEVICES 3
```
+### ILI9488 :id=qp-driver-ili9488
+
+Enabling support for the ILI9488 in Quantum Painter is done by adding the following to `rules.mk`:
+
+```make
+QUANTUM_PAINTER_ENABLE = yes
+QUANTUM_PAINTER_DRIVERS = ili9488_spi
+```
+
+Creating a ILI9488 device in firmware can then be done with the following API:
+
+```c
+painter_device_t qp_ili9488_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode);
+```
+
+The device handle returned from the `qp_ili9488_make_spi_device` function can be used to perform all other drawing operations.
+
+The maximum number of displays can be configured by changing the following in your `config.h` (default is 1):
+
+```c
+// 3 displays:
+#define ILI9488_NUM_DEVICES 3
+```
+
### SSD1351 :id=qp-driver-ssd1351
Enabling support for the SSD1351 in Quantum Painter is done by adding the following to `rules.mk`:
diff --git a/docs/reference_info_json.md b/docs/reference_info_json.md
index 90b28689d0..d2e9346ee3 100644
--- a/docs/reference_info_json.md
+++ b/docs/reference_info_json.md
@@ -187,3 +187,39 @@ Example:
```
The device version is a BCD (binary coded decimal) value, in the format `MMmr`, so the below value would look like `0x0100` in the generated code. This also means the maximum valid values for each part are `99.9.9`, despite it being a hexadecimal value under the hood.
+
+### Encoders
+
+This section controls the basic [rotary encoder](feature_encoders.md) support.
+
+The following items can be set. Not every value is required.
+
+* `pin_a`
+ * __Required__. A pad definition
+* `pin_b`
+ * __Required__. B pad definition
+* `resolution`
+ * How many pulses the encoder registers between each detent
+
+Examples:
+
+```json
+{
+ "encoder": {
+ "rotary": [
+ { "pin_a": "B5", "pin_b": "A2" }
+ ]
+ }
+}
+```
+
+```json
+{
+ "encoder": {
+ "rotary": [
+ { "pin_a": "B5", "pin_b": "A2", "resolution": 4 }
+ { "pin_a": "B6", "pin_b": "A3", "resolution": 2 }
+ ]
+ }
+}
+```
diff --git a/docs/serial_driver.md b/docs/serial_driver.md
index 3e89deffad..fff63109a1 100644
--- a/docs/serial_driver.md
+++ b/docs/serial_driver.md
@@ -1,129 +1,301 @@
# 'serial' Driver
-This driver powers the [Split Keyboard](feature_split_keyboard.md) feature.
+
+The serial driver powers the [Split Keyboard](feature_split_keyboard.md) feature. Several implementations are available, depending on the platform of your split keyboard. Note that none of the drivers support split keyboards with more then two halves.
+
+| Driver | AVR | ARM | Connection between halves |
+| --------------------------------------- | ------------------ | ------------------ | --------------------------------------------------------------------------------------------- |
+| [Bitbang](#bitbang) | :heavy_check_mark: | :heavy_check_mark: | Single wire communication. One wire is used for reception and transmission. |
+| [USART Half-duplex](#usart-half-duplex) | | :heavy_check_mark: | Efficient single wire communication. One wire is used for reception and transmission. |
+| [USART Full-duplex](#usart-full-duplex) | | :heavy_check_mark: | Efficient two wire communication. Two distinct wires are used for reception and transmission. |
?> Serial in this context should be read as **sending information one bit at a time**, rather than implementing UART/USART/RS485/RS232 standards.
-Drivers in this category have the following characteristics:
-* bit bang and USART Half-duplex provide data and signaling over a single conductor
-* USART Full-duplex provide data and signaling over two conductors
-* They are all limited to single master and single slave communication scheme
+<hr>
+
+## Bitbang
+
+This is the Default driver, the absence of configuration assumes this driver. It works by [bit banging](https://en.wikipedia.org/wiki/Bit_banging) a GPIO pin using the CPU. It is therefore not as efficient as a dedicated hardware peripheral, which the Half-duplex and Full-duplex drivers use.
-## Supported Driver Types
+!> On ARM platforms the bitbang driver causes connection issues when using it together with the bitbang WS2812 driver. Choosing alternate drivers for both serial and WS2812 (instead of bitbang) is strongly recommended.
-| | AVR | ARM |
-| ----------------- | ------------------ | ------------------ |
-| bit bang | :heavy_check_mark: | :heavy_check_mark: |
-| USART Half-duplex | | :heavy_check_mark: |
-| USART Full-duplex | | :heavy_check_mark: |
+### Pin configuration
+
+```
+ LEFT RIGHT
++-------+ SERIAL +-------+
+| SSP |-----------------| SSP |
+| | VDD | |
+| |-----------------| |
+| | GND | |
+| |-----------------| |
++-------+ +-------+
+```
-## Driver configuration
+One GPIO pin is needed for the bitbang driver, as only one wire is used for receiving and transmitting data. This pin is referred to as the `SOFT_SERIAL_PIN` (SSP) in the configuration. A simple TRS or USB cable provides enough conductors for this driver to work.
-### Bitbang
-Default driver, the absence of configuration assumes this driver. To configure it, add this to your rules.mk:
+### Setup
+
+To use the bitbang driver follow these steps to activate it.
+
+1. Change the `SERIAL_DRIVER` to `bitbang` in your keyboards `rules.mk` file:
```make
SERIAL_DRIVER = bitbang
```
-Configure the driver via your config.h:
+2. Configure the GPIO pin of your keyboard via the `config.h` file:
+
```c
#define SOFT_SERIAL_PIN D0 // or D1, D2, D3, E6
-#define SELECT_SOFT_SERIAL_SPEED 1 // or 0, 2, 3, 4, 5
- // 0: about 189kbps (Experimental only)
- // 1: about 137kbps (default)
- // 2: about 75kbps
- // 3: about 39kbps
- // 4: about 26kbps
- // 5: about 20kbps
```
-#### ARM
+3. On ARM platforms you must turn on ChibiOS `PAL_USE_CALLBACKS` feature:
+
+* In `halconf.h` add the line `#define PAL_USE_CALLBACKS TRUE`.
+
+<hr>
+
+## USART Half-duplex
+
+Targeting ARM boards based on ChibiOS, where communication is offloaded to a USART hardware device that supports Half-duplex operation. The advantages over bitbanging are fast, accurate timings and reduced CPU usage. Therefore it is advised to choose this driver or the Full-duplex driver whenever possible.
+
+### Pin configuration
+
+```
+ LEFT RIGHT
++-------+ | | +-------+
+| | R R | |
+| | | SERIAL | | |
+| TX |-----------------| TX |
+| | VDD | |
+| |-----------------| |
+| | GND | |
+| |-----------------| |
++-------+ +-------+
+```
+
+Only one GPIO pin is needed for the Half-duplex driver, as only one wire is used for receiving and transmitting data. This pin is referred to as the `SERIAL_USART_TX_PIN` in the configuration. Take care that the pin you chose can act as the TX pin of the USART peripheral. A simple TRS or USB cable provides enough conductors for this driver to work. As the split connection is configured to work in open-drain mode, an **external pull-up resistor is needed to keep the line high**. Resistor values of 1.5kΩ to 8.2kΩ are known to work.
-!> The bitbang driver causes connection issues with bitbang WS2812 driver
+### Setup
-Along with the generic options above, you must also turn on the `PAL_USE_CALLBACKS` feature in your halconf.h.
+To use the Half-duplex driver follow these steps to activate it. If you target the Raspberry Pi RP2040 PIO implementation skip step 1.
-### USART Half-duplex
-Targeting STM32 boards where communication is offloaded to a USART hardware device. The advantage over bitbang is that this provides fast and accurate timings. `SERIAL_PIN_TX` for this driver is the configured USART TX pin. As this Pin is configured in open-drain mode an **external pull-up resistor is needed to keep the line high** (resistor values of 1.5k to 8.2k are known to work). To configure it, add this to your rules.mk:
+1. Change the `SERIAL_DRIVER` to `usart` in your keyboards `rules.mk` file:
```make
SERIAL_DRIVER = usart
```
-Configure the hardware via your config.h:
+2. (RP2040 PIO only!) Change the `SERIAL_DRIVER` to `vendor` in your keyboards `rules.mk` file:
+
+```make
+SERIAL_DRIVER = vendor
+```
+
+3. Configure the hardware of your keyboard via the `config.h` file:
+
+```c
+#define SERIAL_USART_TX_PIN B6 // The GPIO pin that is used split communication.
+```
+
+For STM32 MCUs several GPIO configuration options can be changed as well. See the section ["Alternate Functions for selected STM32 MCUs"](alternate-functions-for-selected-stm32-mcus).
+
```c
-#define SOFT_SERIAL_PIN B6 // USART TX pin
-//#define USART1_REMAP // Remap USART TX and RX pins on STM32F103 MCUs, see table below.
-#define SELECT_SOFT_SERIAL_SPEED 1 // or 0, 2, 3, 4, 5
- // 0: about 460800 baud
- // 1: about 230400 baud (default)
- // 2: about 115200 baud
- // 3: about 57600 baud
- // 4: about 38400 baud
- // 5: about 19200 baud
-#define SERIAL_USART_DRIVER SD1 // USART driver of TX pin. default: SD1
+#define USART1_REMAP // Remap USART TX and RX pins on STM32F103 MCUs, see table below.
#define SERIAL_USART_TX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
-#define SERIAL_USART_TIMEOUT 20 // USART driver timeout. default 20
```
-You must also enable the ChibiOS `SERIAL` feature:
-* In your board's halconf.h: `#define HAL_USE_SERIAL TRUE`
-* In your board's mcuconf.h: `#define STM32_SERIAL_USE_USARTn TRUE` (where 'n' matches the peripheral number of your selected USART on the MCU)
+1. Decide either for `SERIAL`, `SIO` or `PIO` subsystem, see the section ["Choosing a driver subsystem"](#choosing-a-driver-subsystem).
-Do note that the configuration required is for the `SERIAL` peripheral, not the `UART` peripheral.
+<hr>
-### USART Full-duplex
-Targeting STM32 boards where communication is offloaded to a USART hardware device. The advantage over bitbang is that this provides fast and accurate timings. USART Full-Duplex requires two conductors **without** pull-up resistors instead of one conductor with a pull-up resistor unlike the Half-duplex driver. Due to its internal design it is more efficent, which can result in even faster transmission speeds.
+## USART Full-duplex
-#### Pin configuration
+Targeting ARM boards based on ChibiOS where communication is offloaded to an USART hardware device. The advantages over bitbanging are fast, accurate timings and reduced CPU usage. Therefore it is advised to choose this driver or the Full-duplex driver whenever possible. Due to its internal design it is slightly more efficient then the Half-duplex driver, but it should be primarily chosen if Half-duplex operation is not supported by the USART peripheral.
-`SERIAL_USART_TX_PIN` is the USART `TX` pin, `SERIAL_USART_RX_PIN` is the USART `RX` pin. No external pull-up resistors are needed as the `TX` pin operates in push-pull mode. To use this driver the usart peripherals `TX` and `RX` pins must be configured with the correct Alternate-functions. If you are using a Proton-C everything is already setup, same is true for STM32F103 MCUs. For MCUs which are using a modern flexible GPIO configuration you have to specify these by setting `SERIAL_USART_TX_PAL_MODE` and `SERIAL_USART_RX_PAL_MODE`. Refeer to the corresponding datasheets of your MCU or find those settings in the table below.
+### Pin configuration
+
+```
+ LEFT RIGHT
++-------+ +-------+
+| | SERIAL | |
+| TX |-----------------| RX |
+| | SERIAL | |
+| RX |-----------------| TX |
+| | VDD | |
+| |-----------------| |
+| | GND | |
+| |-----------------| |
++-------+ +-------+
+```
-#### Connecting the halves and Pin Swap
-Please note that `TX` of the master half has to be connected with the `RX` pin of the slave half and `RX` of the master half has to be connected with the `TX` pin of the slave half! Usually this pin swap has to be done outside of the MCU e.g. with cables or on the pcb. Some MCUs like the STM32F303 used on the Proton-C allow this pin swap directly inside the MCU, this feature can be enabled using `#define SERIAL_USART_PIN_SWAP` in your config.h.
+Two GPIO pins are needed for the Full-duplex driver, as two distinct wires are used for receiving and transmitting data. The pin transmitting data is the `TX` pin and refereed to as the `SERIAL_USART_TX_PIN`, the pin receiving data is the `RX` pin and refereed to as the `SERIAL_USART_RX_PIN` in this configuration. Please note that `TX` pin of the master half has to be connected with the `RX` pin of the slave half and the `RX` pin of the master half has to be connected with the `TX` pin of the slave half! Usually this pin swap has to be done outside of the MCU e.g. with cables or on the PCB. Some MCUs like the STM32F303 used on the Proton-C allow this pin swap directly inside the MCU. A simple TRRS or USB cable provides enough conductors for this driver to work.
-#### Setup
-To use the driver, add this to your rules.mk:
+To use this driver the usart peripherals `TX` and `RX` pins must be configured with the correct Alternate-functions. If you are using a Proton-C everything is already setup, same is true for STM32F103 MCUs. For MCUs which are using a modern flexible GPIO configuration you have to specify these by setting `SERIAL_USART_TX_PAL_MODE` and `SERIAL_USART_RX_PAL_MODE`. Refer to the corresponding datasheets of your MCU or find those settings in the section ["Alternate Functions for selected STM32 MCUs"](#alternate-functions-for-selected-stm32-mcus).
+
+### Setup
+
+To use the Full-duplex driver follow these steps to activate it. If you target the Raspberry Pi RP2040 PIO implementation skip step 1.
+
+1. Change the `SERIAL_DRIVER` to `usart` in your keyboards `rules.mk` file:
```make
SERIAL_DRIVER = usart
```
-Next configure the hardware via your config.h:
+2. (RP2040 PIO only!) Change the `SERIAL_DRIVER` to `vendor` in your keyboards `rules.mk` file:
+
+```make
+SERIAL_DRIVER = vendor
+```
+
+3. Configure the hardware of your keyboard via the `config.h` file:
```c
#define SERIAL_USART_FULL_DUPLEX // Enable full duplex operation mode.
#define SERIAL_USART_TX_PIN B6 // USART TX pin
#define SERIAL_USART_RX_PIN B7 // USART RX pin
-//#define USART1_REMAP // Remap USART TX and RX pins on STM32F103 MCUs, see table below.
-//#define SERIAL_USART_PIN_SWAP // Swap TX and RX pins if keyboard is master halve.
- // Check if this feature is necessary with your keyboard design and available on the mcu.
-#define SELECT_SOFT_SERIAL_SPEED 1 // or 0, 2, 3, 4, 5
- // 0: 460800 baud
- // 1: 230400 baud (default)
- // 2: 115200 baud
- // 3: 57600 baud
- // 4: 38400 baud
- // 5: 19200 baud
-#define SERIAL_USART_DRIVER SD1 // USART driver of TX and RX pin. default: SD1
+```
+
+For STM32 MCUs several GPIO configuration options, including the ability for `TX` to `RX` pin swapping, can be changed as well. See the section ["Alternate Functions for selected STM32 MCUs"](alternate-functions-for-selected-stm32-mcus).
+
+```c
+#define SERIAL_USART_PIN_SWAP // Swap TX and RX pins if keyboard is master halve. (Only available on some MCUs)
+#define USART1_REMAP // Remap USART TX and RX pins on STM32F103 MCUs, see table below.
#define SERIAL_USART_TX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
-#define SERIAL_USART_RX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
+```
+
+1. Decide either for `SERIAL`, `SIO` or `PIO` subsystem, see the section ["Choosing a driver subsystem"](#choosing-a-driver-subsystem).
+
+<hr>
+
+## Choosing a driver subsystem
+
+### The `SERIAL` driver
+
+The `SERIAL` Subsystem is supported for the majority of ChibiOS MCUs and should be used whenever supported. Follow these steps in order to activate it:
+
+1. In your keyboards `halconf.h` add:
+
+```c
+#define HAL_USE_SERIAL TRUE
+```
+
+2. In your keyboards `mcuconf.h`: activate the USART peripheral that is used on your MCU. The shown example is for an STM32 MCU, so this will not work on MCUs by other manufacturers. You can find the correct names in the `mcuconf.h` files of your MCU that ship with ChibiOS.
+
+Just below `#include_next <mcuconf.h>` add:
+
+```c
+#include_next <mcuconf.h>
+
+#undef STM32_SERIAL_USE_USARTn
+#define STM32_SERIAL_USE_USARTn TRUE
+```
+
+Where 'n' matches the peripheral number of your selected USART on the MCU.
+
+3. In you keyboards `config.h`: override the default USART `SERIAL` driver if you use a USART peripheral that does not belong to the default selected `SD1` driver. For instance, if you selected `STM32_SERIAL_USE_USART3` the matching driver would be `SD3`.
+
+```c
+ #define SERIAL_USART_DRIVER SD3
+ ```
+
+### The `SIO` driver
+
+The `SIO` Subsystem was added to ChibiOS with the 21.11 release and is only supported on selected MCUs. It should only be chosen when the `SERIAL` subsystem is not supported by your MCU.
+
+Follow these steps in order to activate it:
+
+1. In your keyboards `halconf.h` add:
+
+```c
+#define HAL_USE_SIO TRUE
+```
+
+2. In your keyboards `mcuconf.h:` activate the USART peripheral that is used on your MCU. The shown example is for an STM32 MCU, so this will not work on MCUs by other manufacturers. You can find the correct names in the `mcuconf.h` files of your MCU that ship with ChibiOS.
+
+Just below `#include_next <mcuconf.h>` add:
+
+```c
+#include_next <mcuconf.h>
+
+#undef STM32_SIO_USE_USARTn
+#define STM32_SIO_USE_USARTn TRUE
+```
+
+Where 'n' matches the peripheral number of your selected USART on the MCU.
+
+3. In you keyboards `config.h`: override the default USART `SIO` driver if you use a USART peripheral that does not belong to the default selected `SIOD1` driver. For instance, if you selected `STM32_SERIAL_USE_USART3` the matching driver would be `SIOD3`.
+
+```c
+ #define SERIAL_USART_DRIVER SIOD3
+ ```
+
+### The `PIO` driver
+
+The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using the integrated PIO peripheral and is therefore only available on this MCU. Because of the flexible nature of the PIO peripherals, **any** GPIO pin can be used as a `TX` or `RX` pin. Half-duplex and Full-duplex operation is fully supported. The Half-duplex operation mode uses the built-in pull-ups and GPIO manipulation on the RP2040 to drive the line high by default. An external pull-up is therefore not necessary.
+
+Configure the hardware via your config.h:
+```c
+#define SERIAL_PIO_USE_PIO1 // Force the usage of PIO1 peripheral, by default the Serial implementation uses the PIO0 peripheral
+```
+
+The Serial PIO program uses 2 state machines, 13 instructions and the complete interrupt handler of the PIO peripheral it is running on.
+
+<hr>
+
+## Advanced Configuration
+
+There are several advanced configuration options that can be defined in your keyboards `config.h` file:
+
+### Baudrate
+
+If you're having issues or need a higher baudrate with serial communication, you can change the baudrate which in turn controls the communication speed for serial. You want to lower the baudrate if you experience failed transactions.
+
+```c
+#define SELECT_SOFT_SERIAL_SPEED {#}
+```
+
+| Speed | Bitbang | Half-duplex and Full-duplex |
+| ----- | -------------------------- | --------------------------- |
+| `0` | 189000 baud (experimental) | 460800 baud |
+| `1` | 137000 baud (default) | 230400 baud (default) |
+| `2` | 75000 baud | 115200 baud |
+| `3` | 39000 baud | 57600 baud |
+| `4` | 26000 baud | 38400 baud |
+| `5` | 20000 baud | 19200 baud |
+
+Alternatively you can specify the baudrate directly by defining `SERIAL_USART_SPEED`.
+
+### Timeout
+
+This is the default time window in milliseconds in which a successful communication has to complete. Usually you don't want to change this value. But you can do so anyways by defining an alternate one in your keyboards `config.h` file:
+
+```c
#define SERIAL_USART_TIMEOUT 20 // USART driver timeout. default 20
```
-You must also enable the ChibiOS `SERIAL` feature:
-* In your board's halconf.h: `#define HAL_USE_SERIAL TRUE`
-* In your board's mcuconf.h: `#define STM32_SERIAL_USE_USARTn TRUE` (where 'n' matches the peripheral number of your selected USART on the MCU)
+<hr>
+
+## Troubleshooting
+
+If you're having issues withe serial communication, you can enable debug messages that will give you insights which part of the communication failed. The enable these messages add to your keyboards `config.h` file:
+
+```c
+#define SERIAL_DEBUG
+```
+
+?> The messages will be printed out to the `CONSOLE` output. For additional information, refer to [Debugging/Troubleshooting QMK](faq_debug.md).
-Do note that the configuration required is for the `SERIAL` peripheral, not the `UART` peripheral.
+## Alternate Functions for selected STM32 MCUs
-#### Pins for USART Peripherals with Alternate Functions for selected STM32 MCUs
+Pins for USART Peripherals with
-##### STM32F303 / Proton-C [Datasheet](https://www.st.com/resource/en/datasheet/stm32f303cc.pdf)
+### STM32F303 / Proton-C [Datasheet](https://www.st.com/resource/en/datasheet/stm32f303cc.pdf)
Pin Swap available: :heavy_check_mark:
-| Pin | Function | Mode |
+| Pin | Function | Mode |
| ---------- | -------- | ---- |
| **USART1** | | |
| PA9 | TX | AF7 |
@@ -151,11 +323,11 @@ Pin Swap available: :heavy_check_mark:
| PD8 | TX | AF7 |
| PD9 | RX | AF7 |
-##### STM32F072 [Datasheet](https://www.st.com/resource/en/datasheet/stm32f072c8.pdf)
+### STM32F072 [Datasheet](https://www.st.com/resource/en/datasheet/stm32f072c8.pdf)
Pin Swap available: :heavy_check_mark:
-| Pin | Function | Mode |
+| Pin | Function | Mode |
| ------ | -------- | ---- |
| USART1 | | |
| PA9 | TX | AF1 |
@@ -180,7 +352,7 @@ Pin Swap available: :heavy_check_mark:
| PA0 | TX | AF4 |
| PA1 | RX | AF4 |
-##### STM32F103 Medium Density (C8-CB) [Datasheet](https://www.st.com/resource/en/datasheet/stm32f103c8.pdf)
+### STM32F103 Medium Density (C8-CB) [Datasheet](https://www.st.com/resource/en/datasheet/stm32f103c8.pdf)
Pin Swap available: N/A
@@ -190,7 +362,7 @@ Pin remapping:
The pins of USART Peripherals use default Pins that can be remapped to use other pins using the AFIO registers. Default pins are marked **bold**. Add the appropriate defines to your config.h file.
-| Pin | Function | Mode | USART_REMAP |
+| Pin | Function | Mode | USART_REMAP |
| ---------- | -------- | ---- | ------------------- |
| **USART1** | | | |
| **PA9** | TX | AFPP | |
diff --git a/docs/understanding_qmk.md b/docs/understanding_qmk.md
index 9b80fb179e..c1bcfe3ce9 100644
--- a/docs/understanding_qmk.md
+++ b/docs/understanding_qmk.md
@@ -155,7 +155,6 @@ The `process_record()` function itself is deceptively simple, but hidden within
* [`bool process_printer(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_printer.c#L77)
* [`bool process_auto_shift(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_auto_shift.c#L94)
* `bool process_dynamic_tapping_term(uint16_t keycode, keyrecord_t *record)`
- * [`bool process_terminal(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_terminal.c#L264)
* [Identify and process Quantum-specific keycodes](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L291)
At any step during this chain of events a function (such as `process_record_kb()`) can `return false` to halt all further processing.
diff --git a/docs/ws2812_driver.md b/docs/ws2812_driver.md
index 8acac0b3aa..54e6e77d81 100644
--- a/docs/ws2812_driver.md
+++ b/docs/ws2812_driver.md
@@ -11,11 +11,12 @@ These LEDs are called "addressable" because instead of using a wire per color, e
## Supported Driver Types
| | AVR | ARM |
-|----------|--------------------|--------------------|
+| -------- | ------------------ | ------------------ |
| bit bang | :heavy_check_mark: | :heavy_check_mark: |
| I2C | :heavy_check_mark: | |
| SPI | | :heavy_check_mark: |
| PWM | | :heavy_check_mark: |
+| PIO | | :heavy_check_mark: |
## Driver configuration
@@ -33,11 +34,11 @@ The default setting is 280 µs, which should work for most cases, but this can b
Some variants of the WS2812 may have their color components in a different physical or logical order. For example, the WS2812B-2020 has physically swapped red and green LEDs, which causes the wrong color to be displayed, because the default order of the bytes sent over the wire is defined as GRB.
In this case, you can change the byte order by defining `WS2812_BYTE_ORDER` as one of the following values:
-|Byte order |Known devices |
-|---------------------------------|-----------------------------|
-|`WS2812_BYTE_ORDER_GRB` (default)|Most WS2812's, SK6812, SK6805|
-|`WS2812_BYTE_ORDER_RGB` |WS2812B-2020 |
-|`WS2812_BYTE_ORDER_BGR` |TM1812 |
+| Byte order | Known devices |
+| --------------------------------- | ----------------------------- |
+| `WS2812_BYTE_ORDER_GRB` (default) | Most WS2812's, SK6812, SK6805 |
+| `WS2812_BYTE_ORDER_RGB` | WS2812B-2020 |
+| `WS2812_BYTE_ORDER_BGR` | TM1812 |
### Bitbang
@@ -54,13 +55,13 @@ WS2812_DRIVER = bitbang
The WS2812 LED communication topology depends on a serialized timed window. Different versions of the addressable LEDs have differing requirements for the timing parameters, for instance, of the SK6812.
You can tune these parameters through the definition of the following macros:
-| Macro |Default | AVR | ARM |
-|---------------------|--------------------------------------------|--------------------|--------------------|
-|`WS2812_TIMING` |`1250` | :heavy_check_mark: | :heavy_check_mark: |
-|`WS2812_T0H` |`350` | :heavy_check_mark: | :heavy_check_mark: |
-|`WS2812_T0L` |`WS2812_TIMING - WS2812_T0H` | | :heavy_check_mark: |
-|`WS2812_T1H` |`900` | :heavy_check_mark: | :heavy_check_mark: |
-|`WS2812_T1L` |`WS2812_TIMING - WS2812_T1H` | | :heavy_check_mark: |
+| Macro | Default | AVR | ARM |
+| --------------- | ---------------------------- | ------------------ | ------------------ |
+| `WS2812_TIMING` | `1250` | :heavy_check_mark: | :heavy_check_mark: |
+| `WS2812_T0H` | `350` | :heavy_check_mark: | :heavy_check_mark: |
+| `WS2812_T0L` | `WS2812_TIMING - WS2812_T0H` | | :heavy_check_mark: |
+| `WS2812_T1H` | `900` | :heavy_check_mark: | :heavy_check_mark: |
+| `WS2812_T1L` | `WS2812_TIMING - WS2812_T1H` | | :heavy_check_mark: |
### I2C
Targeting boards where WS2812 support is offloaded to a 2nd MCU. Currently the driver is limited to AVR given the known consumers are ps2avrGB/BMC. To configure it, add this to your rules.mk:
@@ -107,16 +108,16 @@ To adjust the baudrate at which the SPI peripheral is configured, users will nee
Only divisors of 2, 4, 8, 16, 32, 64, 128 and 256 are supported by hardware.
-|Define |Default|Description |
-|--------------------|-------|-------------------------------------|
-|`WS2812_SPI_DIVISOR`|`16` |SPI source clock peripheral divisor |
+| Define | Default | Description |
+| -------------------- | ------- | ----------------------------------- |
+| `WS2812_SPI_DIVISOR` | `16` | SPI source clock peripheral divisor |
#### Testing Notes
While not an exhaustive list, the following table provides the scenarios that have been partially validated:
| | SPI1 | SPI2 | SPI3 |
-|------|---------------------------------------------|-----------------------------------------|-----------------------|
+| ---- | ------------------------------------------- | --------------------------------------- | --------------------- |
| f072 | ? | B15 :heavy_check_mark: (needs SCK: B13) | N/A |
| f103 | A7 :heavy_check_mark: | B15 :heavy_check_mark: | N/A |
| f303 | A7 :heavy_check_mark: B5 :heavy_check_mark: | B15 :heavy_check_mark: | B5 :heavy_check_mark: |
@@ -150,15 +151,32 @@ You must also turn on the PWM feature in your halconf.h and mcuconf.h
While not an exhaustive list, the following table provides the scenarios that have been partially validated:
-| | Status |
-|-|-|
-| f072 | ? |
-| f103 | :heavy_check_mark: |
-| f303 | :heavy_check_mark: |
+| | Status |
+| --------- | ------------------ |
+| f072 | ? |
+| f103 | :heavy_check_mark: |
+| f303 | :heavy_check_mark: |
| f401/f411 | :heavy_check_mark: |
*Other supported ChibiOS boards and/or pins may function, it will be highly chip and configuration dependent.*
+### PIO
+
+Targeting Raspberry Pi RP2040 boards only where WS2812 support is offloaded to an dedicated PIO implementation. This offloads processing of the WS2812 protocol from the MCU to a dedicated PIO program using DMA transfers.
+
+To configure it, add this to your rules.mk:
+
+```make
+WS2812_DRIVER = vendor
+```
+
+Configure the hardware via your config.h:
+```c
+#define WS2812_PIO_USE_PIO1 // Force the usage of PIO1 peripheral, by default the WS2812 implementation uses the PIO0 peripheral
+```
+
+The WS2812 PIO programm uses 1 state machine, 4 instructions and does not use any interrupt handlers.
+
### Push Pull and Open Drain Configuration
The default configuration is a push pull on the defined pin.
This can be configured for bitbang, PWM and SPI.
diff --git a/docs/zh-cn/_summary.md b/docs/zh-cn/_summary.md
index dbad1021fa..3baee6dc2e 100644
--- a/docs/zh-cn/_summary.md
+++ b/docs/zh-cn/_summary.md
@@ -91,7 +91,6 @@
* [æ¢æ‰‹](zh-cn/feature_swap_hands.md)
* [一键多用](zh-cn/feature_tap_dance.md)
* [点按é…ç½®](zh-cn/tap_hold.md)
- * [终端](zh-cn/feature_terminal.md)
* [Unicode](zh-cn/feature_unicode.md)
* [用户空间](zh-cn/feature_userspace.md)
* [WPM计算](zh-cn/feature_wpm.md)
diff --git a/docs/zh-cn/custom_quantum_functions.md b/docs/zh-cn/custom_quantum_functions.md
index 29c5089052..dba9e7e7c0 100644
--- a/docs/zh-cn/custom_quantum_functions.md
+++ b/docs/zh-cn/custom_quantum_functions.md
@@ -240,7 +240,7 @@ void suspend_wakeup_init_user(void) {
```c
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _RAISE:
rgblight_setrgb (0x00, 0x00, 0xFF);
break;
@@ -267,7 +267,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
### `layer_state_set_*` 函数文档
-* 键盘/å„å­ç‰ˆæœ¬ï¼š`uint32_t layer_state_set_kb(uint32_t state)`
+* 键盘/å„å­ç‰ˆæœ¬ï¼š`layer_state_t layer_state_set_kb(layer_state_t state)`
* 布局: `layer_state_t layer_state_set_user(layer_state_t state)`
@@ -325,7 +325,7 @@ void keyboard_post_init_user(void) {
```c
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _RAISE:
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_magenta(); rgblight_mode_noeeprom(1); }
break;
@@ -474,4 +474,3 @@ cancel_deferred_exec(my_token);
```c
#define MAX_DEFERRED_EXECUTORS 16
```
-
diff --git a/drivers/eeprom/eeprom_i2c.h b/drivers/eeprom/eeprom_i2c.h
index 77eea66d63..85317c9ea5 100644
--- a/drivers/eeprom/eeprom_i2c.h
+++ b/drivers/eeprom/eeprom_i2c.h
@@ -54,6 +54,11 @@
# define EXTERNAL_EEPROM_PAGE_SIZE 32
# define EXTERNAL_EEPROM_ADDRESS_SIZE 2
# define EXTERNAL_EEPROM_WRITE_TIME 5
+#elif defined(EEPROM_I2C_24LC32A)
+# define EXTERNAL_EEPROM_BYTE_COUNT 4096
+# define EXTERNAL_EEPROM_PAGE_SIZE 32
+# define EXTERNAL_EEPROM_ADDRESS_SIZE 2
+# define EXTERNAL_EEPROM_WRITE_TIME 5
#elif defined(EEPROM_I2C_MB85RC256V)
# define EXTERNAL_EEPROM_BYTE_COUNT 32768
# define EXTERNAL_EEPROM_PAGE_SIZE 128
diff --git a/drivers/eeprom/eeprom_wear_leveling.c b/drivers/eeprom/eeprom_wear_leveling.c
new file mode 100644
index 0000000000..bd77eef35c
--- /dev/null
+++ b/drivers/eeprom/eeprom_wear_leveling.c
@@ -0,0 +1,23 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <stdint.h>
+#include <string.h>
+
+#include "eeprom_driver.h"
+#include "wear_leveling.h"
+
+void eeprom_driver_init(void) {
+ wear_leveling_init();
+}
+
+void eeprom_driver_erase(void) {
+ wear_leveling_erase();
+}
+
+void eeprom_read_block(void *buf, const void *addr, size_t len) {
+ wear_leveling_read((uint32_t)addr, buf, len);
+}
+
+void eeprom_write_block(const void *buf, void *addr, size_t len) {
+ wear_leveling_write((uint32_t)addr, buf, len);
+}
diff --git a/drivers/led/aw20216.c b/drivers/led/aw20216.c
index 448accdcd3..55083936ef 100644
--- a/drivers/led/aw20216.c
+++ b/drivers/led/aw20216.c
@@ -53,6 +53,10 @@
# define AW_GLOBAL_CURRENT_MAX 150
#endif
+#ifndef AW_SPI_MODE
+# define AW_SPI_MODE 0
+#endif
+
#ifndef AW_SPI_DIVISOR
# define AW_SPI_DIVISOR 4
#endif
@@ -63,7 +67,7 @@ bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
bool AW20216_write(pin_t cs_pin, uint8_t page, uint8_t reg, uint8_t* data, uint8_t len) {
static uint8_t s_spi_transfer_buffer[2] = {0};
- if (!spi_start(cs_pin, false, 3, AW_SPI_DIVISOR)) {
+ if (!spi_start(cs_pin, false, AW_SPI_MODE, AW_SPI_DIVISOR)) {
spi_stop();
return false;
}
diff --git a/drivers/led/issi/is31fl3733-simple.c b/drivers/led/issi/is31fl3733-simple.c
index af006f756d..2f41a7b1a9 100644
--- a/drivers/led/issi/is31fl3733-simple.c
+++ b/drivers/led/issi/is31fl3733-simple.c
@@ -70,6 +70,10 @@
# define ISSI_CSPULLUP PUR_0R
#endif
+#ifndef ISSI_GLOBALCURRENT
+# define ISSI_GLOBALCURRENT 0xFF
+#endif
+
// Transfer buffer for TWITransmitData()
uint8_t g_twi_transfer_buffer[20];
@@ -182,7 +186,7 @@ void IS31FL3733_init(uint8_t addr, uint8_t sync) {
// Set de-ghost pull-down resistors (CSx)
IS31FL3733_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP);
// Set global current to maximum.
- IS31FL3733_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
+ IS31FL3733_write_register(addr, ISSI_REG_GLOBALCURRENT, ISSI_GLOBALCURRENT);
// Disable software shutdown.
IS31FL3733_write_register(addr, ISSI_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((ISSI_PWM_FREQUENCY & 0b111) << 3) | 0x01);
diff --git a/drivers/led/issi/is31fl3733.c b/drivers/led/issi/is31fl3733.c
index a2fdaa90fa..add998f256 100644
--- a/drivers/led/issi/is31fl3733.c
+++ b/drivers/led/issi/is31fl3733.c
@@ -69,6 +69,10 @@
# define ISSI_CSPULLUP PUR_0R
#endif
+#ifndef ISSI_GLOBALCURRENT
+# define ISSI_GLOBALCURRENT 0xFF
+#endif
+
// Transfer buffer for TWITransmitData()
uint8_t g_twi_transfer_buffer[20];
@@ -172,7 +176,7 @@ void IS31FL3733_init(uint8_t addr, uint8_t sync) {
// Set de-ghost pull-down resistors (CSx)
IS31FL3733_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP);
// Set global current to maximum.
- IS31FL3733_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
+ IS31FL3733_write_register(addr, ISSI_REG_GLOBALCURRENT, ISSI_GLOBALCURRENT);
// Disable software shutdown.
IS31FL3733_write_register(addr, ISSI_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((ISSI_PWM_FREQUENCY & 0b111) << 3) | 0x01);
diff --git a/drivers/led/issi/is31fl3736.c b/drivers/led/issi/is31fl3736.c
index 7752a3f6cb..e9943614d2 100644
--- a/drivers/led/issi/is31fl3736.c
+++ b/drivers/led/issi/is31fl3736.c
@@ -63,6 +63,10 @@
# define ISSI_CSPULLUP PUR_0R
#endif
+#ifndef ISSI_GLOBALCURRENT
+# define ISSI_GLOBALCURRENT 0xFF
+#endif
+
// Transfer buffer for TWITransmitData()
uint8_t g_twi_transfer_buffer[20];
@@ -154,7 +158,7 @@ void IS31FL3736_init(uint8_t addr) {
// Set de-ghost pull-down resistors (CSx)
IS31FL3736_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP);
// Set global current to maximum.
- IS31FL3736_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
+ IS31FL3736_write_register(addr, ISSI_REG_GLOBALCURRENT, ISSI_GLOBALCURRENT);
// Disable software shutdown.
IS31FL3736_write_register(addr, ISSI_REG_CONFIGURATION, 0x01);
diff --git a/drivers/led/issi/is31fl3737.c b/drivers/led/issi/is31fl3737.c
index bce0c34b2c..932530ac0a 100644
--- a/drivers/led/issi/is31fl3737.c
+++ b/drivers/led/issi/is31fl3737.c
@@ -69,6 +69,10 @@
# define ISSI_CSPULLUP PUR_0R
#endif
+#ifndef ISSI_GLOBALCURRENT
+# define ISSI_GLOBALCURRENT 0xFF
+#endif
+
// Transfer buffer for TWITransmitData()
uint8_t g_twi_transfer_buffer[20];
@@ -161,7 +165,7 @@ void IS31FL3737_init(uint8_t addr) {
// Set de-ghost pull-down resistors (CSx)
IS31FL3737_write_register(addr, ISSI_REG_CSPULLUP, ISSI_CSPULLUP);
// Set global current to maximum.
- IS31FL3737_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
+ IS31FL3737_write_register(addr, ISSI_REG_GLOBALCURRENT, ISSI_GLOBALCURRENT);
// Disable software shutdown.
IS31FL3737_write_register(addr, ISSI_REG_CONFIGURATION, ((ISSI_PWM_FREQUENCY & 0b111) << 3) | 0x01);
diff --git a/drivers/led/issi/is31fl3741.c b/drivers/led/issi/is31fl3741.c
index 393b0179b5..ba6b6761a3 100644
--- a/drivers/led/issi/is31fl3741.c
+++ b/drivers/led/issi/is31fl3741.c
@@ -69,6 +69,10 @@
# define ISSI_CSPULLUP PUR_32KR
#endif
+#ifndef ISSI_GLOBALCURRENT
+# define ISSI_GLOBALCURRENT 0xFF
+#endif
+
#define ISSI_MAX_LEDS 351
// Transfer buffer for TWITransmitData()
@@ -163,7 +167,7 @@ void IS31FL3741_init(uint8_t addr) {
IS31FL3741_write_register(addr, ISSI_REG_CONFIGURATION, 0x01);
// Set Golbal Current Control Register
- IS31FL3741_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
+ IS31FL3741_write_register(addr, ISSI_REG_GLOBALCURRENT, ISSI_GLOBALCURRENT);
// Set Pull up & Down for SWx CSy
IS31FL3741_write_register(addr, ISSI_REG_PULLDOWNUP, ((ISSI_CSPULLUP << 4) | ISSI_SWPULLUP));
diff --git a/drivers/painter/gc9a01/qp_gc9a01.c b/drivers/painter/gc9a01/qp_gc9a01.c
index ad76d58b07..37700a28a4 100644
--- a/drivers/painter/gc9a01/qp_gc9a01.c
+++ b/drivers/painter/gc9a01/qp_gc9a01.c
@@ -102,12 +102,11 @@ const struct tft_panel_dc_reset_painter_driver_vtable_t gc9a01_driver_vtable = {
.flush = qp_tft_panel_flush,
.pixdata = qp_tft_panel_pixdata,
.viewport = qp_tft_panel_viewport,
- .palette_convert = qp_tft_panel_palette_convert,
- .append_pixels = qp_tft_panel_append_pixels,
+ .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
+ .append_pixels = qp_tft_panel_append_pixels_rgb565,
},
- .rgb888_to_native16bit = qp_rgb888_to_rgb565_swapped,
- .num_window_bytes = 2,
- .swap_window_coords = false,
+ .num_window_bytes = 2,
+ .swap_window_coords = false,
.opcodes =
{
.display_on = GC9A01_CMD_DISPLAY_ON,
diff --git a/drivers/painter/ili9xxx/qp_ili9163.c b/drivers/painter/ili9xxx/qp_ili9163.c
index beaac0fbb5..14363c7d04 100644
--- a/drivers/painter/ili9xxx/qp_ili9163.c
+++ b/drivers/painter/ili9xxx/qp_ili9163.c
@@ -67,12 +67,11 @@ const struct tft_panel_dc_reset_painter_driver_vtable_t ili9163_driver_vtable =
.flush = qp_tft_panel_flush,
.pixdata = qp_tft_panel_pixdata,
.viewport = qp_tft_panel_viewport,
- .palette_convert = qp_tft_panel_palette_convert,
- .append_pixels = qp_tft_panel_append_pixels,
+ .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
+ .append_pixels = qp_tft_panel_append_pixels_rgb565,
},
- .rgb888_to_native16bit = qp_rgb888_to_rgb565_swapped,
- .num_window_bytes = 2,
- .swap_window_coords = false,
+ .num_window_bytes = 2,
+ .swap_window_coords = false,
.opcodes =
{
.display_on = ILI9XXX_CMD_DISPLAY_ON,
diff --git a/drivers/painter/ili9xxx/qp_ili9341.c b/drivers/painter/ili9xxx/qp_ili9341.c
index 1f41dcfc0b..9608f109bd 100644
--- a/drivers/painter/ili9xxx/qp_ili9341.c
+++ b/drivers/painter/ili9xxx/qp_ili9341.c
@@ -74,12 +74,11 @@ const struct tft_panel_dc_reset_painter_driver_vtable_t ili9341_driver_vtable =
.flush = qp_tft_panel_flush,
.pixdata = qp_tft_panel_pixdata,
.viewport = qp_tft_panel_viewport,
- .palette_convert = qp_tft_panel_palette_convert,
- .append_pixels = qp_tft_panel_append_pixels,
+ .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
+ .append_pixels = qp_tft_panel_append_pixels_rgb565,
},
- .rgb888_to_native16bit = qp_rgb888_to_rgb565_swapped,
- .num_window_bytes = 2,
- .swap_window_coords = false,
+ .num_window_bytes = 2,
+ .swap_window_coords = false,
.opcodes =
{
.display_on = ILI9XXX_CMD_DISPLAY_ON,
diff --git a/drivers/painter/ili9xxx/qp_ili9488.c b/drivers/painter/ili9xxx/qp_ili9488.c
new file mode 100644
index 0000000000..55cf9f896f
--- /dev/null
+++ b/drivers/painter/ili9xxx/qp_ili9488.c
@@ -0,0 +1,120 @@
+// Copyright 2021 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "qp_internal.h"
+#include "qp_comms.h"
+#include "qp_ili9488.h"
+#include "qp_ili9xxx_opcodes.h"
+#include "qp_tft_panel.h"
+
+#ifdef QUANTUM_PAINTER_ILI9488_SPI_ENABLE
+# include <qp_comms_spi.h>
+#endif // QUANTUM_PAINTER_ILI9488_SPI_ENABLE
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Common
+
+// Driver storage
+tft_panel_dc_reset_painter_device_t ili9488_drivers[ILI9488_NUM_DEVICES] = {0};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Initialization
+
+bool qp_ili9488_init(painter_device_t device, painter_rotation_t rotation) {
+ // clang-format off
+ const uint8_t ili9488_init_sequence[] = {
+ // Command, Delay, N, Data[N]
+ ILI9XXX_CMD_RESET, 120, 0,
+ ILI9XXX_SET_PGAMMA, 0, 15, 0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F,
+ ILI9XXX_SET_NGAMMA, 0, 15, 0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F,
+ ILI9XXX_SET_POWER_CTL_1, 0, 2, 0x17, 0x15,
+ ILI9XXX_SET_POWER_CTL_2, 0, 1, 0x41,
+ ILI9XXX_SET_VCOM_CTL_1, 0, 3, 0x00, 0x12, 0x80,
+ ILI9XXX_SET_PIX_FMT, 0, 1, 0x66,
+ ILI9XXX_SET_RGB_IF_SIG_CTL, 0, 1, 0x80,
+ ILI9XXX_SET_FRAME_CTL_NORMAL, 0, 1, 0xA0,
+ ILI9XXX_SET_INVERSION_CTL, 0, 1, 0x02,
+ ILI9XXX_SET_FUNCTION_CTL, 0, 2, 0x02, 0x02,
+ ILI9XXX_SET_IMAGE_FUNCTION, 0, 1, 0x00,
+ ILI9XXX_SET_PUMP_RATIO_CTL, 0, 4, 0xA9, 0x51, 0x2C, 0x82,
+ ILI9XXX_CMD_SLEEP_OFF, 5, 0,
+ ILI9XXX_CMD_DISPLAY_ON, 20, 0
+ };
+ // clang-format on
+ qp_comms_bulk_command_sequence(device, ili9488_init_sequence, sizeof(ili9488_init_sequence));
+
+ // Configure the rotation (i.e. the ordering and direction of memory writes in GRAM)
+ const uint8_t madctl[] = {
+ [QP_ROTATION_0] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MY,
+ [QP_ROTATION_90] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX | ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MY,
+ [QP_ROTATION_180] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MX,
+ [QP_ROTATION_270] = ILI9XXX_MADCTL_BGR | ILI9XXX_MADCTL_MV,
+ };
+ qp_comms_command_databyte(device, ILI9XXX_SET_MEM_ACS_CTL, madctl[rotation]);
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Driver vtable
+
+const struct tft_panel_dc_reset_painter_driver_vtable_t ili9488_driver_vtable = {
+ .base =
+ {
+ .init = qp_ili9488_init,
+ .power = qp_tft_panel_power,
+ .clear = qp_tft_panel_clear,
+ .flush = qp_tft_panel_flush,
+ .pixdata = qp_tft_panel_pixdata,
+ .viewport = qp_tft_panel_viewport,
+ .palette_convert = qp_tft_panel_palette_convert_rgb888,
+ .append_pixels = qp_tft_panel_append_pixels_rgb888,
+ },
+ .num_window_bytes = 2,
+ .swap_window_coords = false,
+ .opcodes =
+ {
+ .display_on = ILI9XXX_CMD_DISPLAY_ON,
+ .display_off = ILI9XXX_CMD_DISPLAY_OFF,
+ .set_column_address = ILI9XXX_SET_COL_ADDR,
+ .set_row_address = ILI9XXX_SET_PAGE_ADDR,
+ .enable_writes = ILI9XXX_SET_MEM,
+ },
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SPI
+
+#ifdef QUANTUM_PAINTER_ILI9488_SPI_ENABLE
+
+// Factory function for creating a handle to the ILI9488 device
+painter_device_t qp_ili9488_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode) {
+ for (uint32_t i = 0; i < ILI9488_NUM_DEVICES; ++i) {
+ tft_panel_dc_reset_painter_device_t *driver = &ili9488_drivers[i];
+ if (!driver->base.driver_vtable) {
+ driver->base.driver_vtable = (const struct painter_driver_vtable_t *)&ili9488_driver_vtable;
+ driver->base.comms_vtable = (const struct painter_comms_vtable_t *)&spi_comms_with_dc_vtable;
+ driver->base.native_bits_per_pixel = 24; // RGB888
+ driver->base.panel_width = panel_width;
+ driver->base.panel_height = panel_height;
+ driver->base.rotation = QP_ROTATION_0;
+ driver->base.offset_x = 0;
+ driver->base.offset_y = 0;
+
+ // SPI and other pin configuration
+ driver->base.comms_config = &driver->spi_dc_reset_config;
+ driver->spi_dc_reset_config.spi_config.chip_select_pin = chip_select_pin;
+ driver->spi_dc_reset_config.spi_config.divisor = spi_divisor;
+ driver->spi_dc_reset_config.spi_config.lsb_first = false;
+ driver->spi_dc_reset_config.spi_config.mode = spi_mode;
+ driver->spi_dc_reset_config.dc_pin = dc_pin;
+ driver->spi_dc_reset_config.reset_pin = reset_pin;
+ return (painter_device_t)driver;
+ }
+ }
+ return NULL;
+}
+
+#endif // QUANTUM_PAINTER_ILI9488_SPI_ENABLE
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/painter/ili9xxx/qp_ili9488.h b/drivers/painter/ili9xxx/qp_ili9488.h
new file mode 100644
index 0000000000..21b8f03322
--- /dev/null
+++ b/drivers/painter/ili9xxx/qp_ili9488.h
@@ -0,0 +1,37 @@
+// Copyright 2021 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "gpio.h"
+#include "qp_internal.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter ILI9488 configurables (add to your keyboard's config.h)
+
+#ifndef ILI9488_NUM_DEVICES
+/**
+ * @def This controls the maximum number of ILI9488 devices that Quantum Painter can communicate with at any one time.
+ * Increasing this number allows for multiple displays to be used.
+ */
+# define ILI9488_NUM_DEVICES 1
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantum Painter ILI9488 device factories
+
+#ifdef QUANTUM_PAINTER_ILI9488_SPI_ENABLE
+/**
+ * Factory method for an ILI9488 SPI LCD device.
+ *
+ * @param panel_width[in] the width of the display panel
+ * @param panel_height[in] the height of the display panel
+ * @param chip_select_pin[in] the GPIO pin used for SPI chip select
+ * @param dc_pin[in] the GPIO pin used for D/C control
+ * @param reset_pin[in] the GPIO pin used for RST
+ * @param spi_divisor[in] the SPI divisor to use when communicating with the display
+ * @param spi_mode[in] the SPI mode to use when communicating with the display
+ * @return the device handle used with all drawing routines in Quantum Painter
+ */
+painter_device_t qp_ili9488_make_spi_device(uint16_t panel_width, uint16_t panel_height, pin_t chip_select_pin, pin_t dc_pin, pin_t reset_pin, uint16_t spi_divisor, int spi_mode);
+#endif // QUANTUM_PAINTER_ILI9488_SPI_ENABLE
diff --git a/drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h b/drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h
index 1fa395cb89..47bb703648 100644
--- a/drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h
+++ b/drivers/painter/ili9xxx/qp_ili9xxx_opcodes.h
@@ -85,6 +85,7 @@
#define ILI9XXX_SET_NGAMMA 0xE1 // Set negative gamma
#define ILI9XXX_SET_DGAMMA_CTL_1 0xE2 // Set digital gamma ctl 1
#define ILI9XXX_SET_DGAMMA_CTL_2 0xE3 // Set digital gamma ctl 2
+#define ILI9XXX_SET_IMAGE_FUNCTION 0xE9 // Set image function
#define ILI9XXX_ENABLE_3_GAMMA 0xF2 // Enable 3 gamma
#define ILI9XXX_SET_IF_CTL 0xF6 // Set interface control
#define ILI9XXX_SET_PUMP_RATIO_CTL 0xF7 // Set pump ratio control
diff --git a/drivers/painter/ssd1351/qp_ssd1351.c b/drivers/painter/ssd1351/qp_ssd1351.c
index 970e7e67f3..7ce76bab6d 100644
--- a/drivers/painter/ssd1351/qp_ssd1351.c
+++ b/drivers/painter/ssd1351/qp_ssd1351.c
@@ -71,12 +71,11 @@ const struct tft_panel_dc_reset_painter_driver_vtable_t ssd1351_driver_vtable =
.flush = qp_tft_panel_flush,
.pixdata = qp_tft_panel_pixdata,
.viewport = qp_tft_panel_viewport,
- .palette_convert = qp_tft_panel_palette_convert,
- .append_pixels = qp_tft_panel_append_pixels,
+ .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
+ .append_pixels = qp_tft_panel_append_pixels_rgb565,
},
- .rgb888_to_native16bit = qp_rgb888_to_rgb565_swapped,
- .num_window_bytes = 1,
- .swap_window_coords = true,
+ .num_window_bytes = 1,
+ .swap_window_coords = true,
.opcodes =
{
.display_on = SSD1351_DISPLAYON,
diff --git a/drivers/painter/st77xx/qp_st7789.c b/drivers/painter/st77xx/qp_st7789.c
index d005ece050..49e8436c29 100644
--- a/drivers/painter/st77xx/qp_st7789.c
+++ b/drivers/painter/st77xx/qp_st7789.c
@@ -90,12 +90,11 @@ const struct tft_panel_dc_reset_painter_driver_vtable_t st7789_driver_vtable = {
.flush = qp_tft_panel_flush,
.pixdata = qp_tft_panel_pixdata,
.viewport = qp_tft_panel_viewport,
- .palette_convert = qp_tft_panel_palette_convert,
- .append_pixels = qp_tft_panel_append_pixels,
+ .palette_convert = qp_tft_panel_palette_convert_rgb565_swapped,
+ .append_pixels = qp_tft_panel_append_pixels_rgb565,
},
- .rgb888_to_native16bit = qp_rgb888_to_rgb565_swapped,
- .num_window_bytes = 2,
- .swap_window_coords = false,
+ .num_window_bytes = 2,
+ .swap_window_coords = false,
.opcodes =
{
.display_on = ST77XX_CMD_DISPLAY_ON,
diff --git a/drivers/painter/tft_panel/qp_tft_panel.c b/drivers/painter/tft_panel/qp_tft_panel.c
index 4d636c9509..ad83b6c792 100644
--- a/drivers/painter/tft_panel/qp_tft_panel.c
+++ b/drivers/painter/tft_panel/qp_tft_panel.c
@@ -10,29 +10,6 @@
#define BYTE_SWAP(x) (((((uint16_t)(x)) >> 8) & 0x00FF) | ((((uint16_t)(x)) << 8) & 0xFF00))
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Native pixel format conversion
-
-uint16_t qp_rgb888_to_rgb565(uint8_t r, uint8_t g, uint8_t b) {
- uint16_t rgb565 = (((uint16_t)r) >> 3) << 11 | (((uint16_t)g) >> 2) << 5 | (((uint16_t)b) >> 3);
- return rgb565;
-}
-
-uint16_t qp_rgb888_to_rgb565_swapped(uint8_t r, uint8_t g, uint8_t b) {
- uint16_t rgb565 = (((uint16_t)r) >> 3) << 11 | (((uint16_t)g) >> 2) << 5 | (((uint16_t)b) >> 3);
- return BYTE_SWAP(rgb565);
-}
-
-uint16_t qp_rgb888_to_bgr565(uint8_t r, uint8_t g, uint8_t b) {
- uint16_t bgr565 = (((uint16_t)b) >> 3) << 11 | (((uint16_t)g) >> 2) << 5 | (((uint16_t)r) >> 3);
- return bgr565;
-}
-
-uint16_t qp_rgb888_to_bgr565_swapped(uint8_t r, uint8_t g, uint8_t b) {
- uint16_t bgr565 = (((uint16_t)b) >> 3) << 11 | (((uint16_t)g) >> 2) << 5 | (((uint16_t)r) >> 3);
- return BYTE_SWAP(bgr565);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Quantum Painter API implementations
// Power control
@@ -105,26 +82,49 @@ bool qp_tft_panel_viewport(painter_device_t device, uint16_t left, uint16_t top,
// Stream pixel data to the current write position in GRAM
bool qp_tft_panel_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) {
- qp_comms_send(device, pixel_data, native_pixel_count * sizeof(uint16_t));
+ struct painter_driver_t *driver = (struct painter_driver_t *)device;
+ qp_comms_send(device, pixel_data, native_pixel_count * driver->native_bits_per_pixel / 8);
return true;
}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Convert supplied palette entries into their native equivalents
-bool qp_tft_panel_palette_convert(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) {
- struct painter_driver_t * driver = (struct painter_driver_t *)device;
- struct tft_panel_dc_reset_painter_driver_vtable_t *vtable = (struct tft_panel_dc_reset_painter_driver_vtable_t *)driver->driver_vtable;
+
+bool qp_tft_panel_palette_convert_rgb565_swapped(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) {
for (int16_t i = 0; i < palette_size; ++i) {
- RGB rgb = hsv_to_rgb_nocie((HSV){palette[i].hsv888.h, palette[i].hsv888.s, palette[i].hsv888.v});
- palette[i].rgb565 = vtable->rgb888_to_native16bit(rgb.r, rgb.g, rgb.b);
+ RGB rgb = hsv_to_rgb_nocie((HSV){palette[i].hsv888.h, palette[i].hsv888.s, palette[i].hsv888.v});
+ uint16_t rgb565 = (((uint16_t)rgb.r) >> 3) << 11 | (((uint16_t)rgb.g) >> 2) << 5 | (((uint16_t)rgb.b) >> 3);
+ palette[i].rgb565 = BYTE_SWAP(rgb565);
}
return true;
}
+bool qp_tft_panel_palette_convert_rgb888(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) {
+ for (int16_t i = 0; i < palette_size; ++i) {
+ RGB rgb = hsv_to_rgb_nocie((HSV){palette[i].hsv888.h, palette[i].hsv888.s, palette[i].hsv888.v});
+ palette[i].rgb888.r = rgb.r;
+ palette[i].rgb888.g = rgb.g;
+ palette[i].rgb888.b = rgb.b;
+ }
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Append pixels to the target location, keyed by the pixel index
-bool qp_tft_panel_append_pixels(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) {
+
+bool qp_tft_panel_append_pixels_rgb565(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) {
uint16_t *buf = (uint16_t *)target_buffer;
for (uint32_t i = 0; i < pixel_count; ++i) {
buf[pixel_offset + i] = palette[palette_indices[i]].rgb565;
}
return true;
}
+
+bool qp_tft_panel_append_pixels_rgb888(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) {
+ for (uint32_t i = 0; i < pixel_count; ++i) {
+ target_buffer[(pixel_offset + i) * 3 + 0] = palette[palette_indices[i]].rgb888.r;
+ target_buffer[(pixel_offset + i) * 3 + 1] = palette[palette_indices[i]].rgb888.g;
+ target_buffer[(pixel_offset + i) * 3 + 2] = palette[palette_indices[i]].rgb888.b;
+ }
+ return true;
+}
diff --git a/drivers/painter/tft_panel/qp_tft_panel.h b/drivers/painter/tft_panel/qp_tft_panel.h
index 6eddfc503d..3cb015891b 100644
--- a/drivers/painter/tft_panel/qp_tft_panel.h
+++ b/drivers/painter/tft_panel/qp_tft_panel.h
@@ -11,15 +11,10 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Common TFT panel implementation using D/C, and RST pins.
-typedef uint16_t (*rgb888_to_native_uint16_t)(uint8_t r, uint8_t g, uint8_t b);
-
// Driver vtable with extras
struct tft_panel_dc_reset_painter_driver_vtable_t {
struct painter_driver_vtable_t base; // must be first, so it can be cast to/from the painter_driver_vtable_t* type
- // Conversion function for palette entries
- rgb888_to_native_uint16_t rgb888_to_native16bit;
-
// Number of bytes for transmitting x/y coordinates
uint8_t num_window_bytes;
@@ -58,10 +53,9 @@ bool qp_tft_panel_clear(painter_device_t device);
bool qp_tft_panel_flush(painter_device_t device);
bool qp_tft_panel_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom);
bool qp_tft_panel_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count);
-bool qp_tft_panel_palette_convert(painter_device_t device, int16_t palette_size, qp_pixel_t *palette);
-bool qp_tft_panel_append_pixels(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices);
-uint16_t qp_rgb888_to_rgb565(uint8_t r, uint8_t g, uint8_t b);
-uint16_t qp_rgb888_to_rgb565_swapped(uint8_t r, uint8_t g, uint8_t b);
-uint16_t qp_rgb888_to_bgr565(uint8_t r, uint8_t g, uint8_t b);
-uint16_t qp_rgb888_to_bgr565_swapped(uint8_t r, uint8_t g, uint8_t b);
+bool qp_tft_panel_palette_convert_rgb565_swapped(painter_device_t device, int16_t palette_size, qp_pixel_t *palette);
+bool qp_tft_panel_palette_convert_rgb888(painter_device_t device, int16_t palette_size, qp_pixel_t *palette);
+
+bool qp_tft_panel_append_pixels_rgb565(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices);
+bool qp_tft_panel_append_pixels_rgb888(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices);
diff --git a/drivers/ps2/ps2.h b/drivers/ps2/ps2.h
index f123192852..2465e16235 100644
--- a/drivers/ps2/ps2.h
+++ b/drivers/ps2/ps2.h
@@ -89,6 +89,7 @@ uint8_t ps2_host_send(uint8_t data);
uint8_t ps2_host_recv_response(void);
uint8_t ps2_host_recv(void);
void ps2_host_set_led(uint8_t usb_led);
+bool pbuf_has_data(void);
/*--------------------------------------------------------------------
* static functions
diff --git a/drivers/ps2/ps2_interrupt.c b/drivers/ps2/ps2_interrupt.c
index c49b4f8b75..c9a9f1e1ec 100644
--- a/drivers/ps2/ps2_interrupt.c
+++ b/drivers/ps2/ps2_interrupt.c
@@ -66,8 +66,8 @@ uint8_t ps2_error = PS2_ERR_NONE;
static inline uint8_t pbuf_dequeue(void);
static inline void pbuf_enqueue(uint8_t data);
-static inline bool pbuf_has_data(void);
static inline void pbuf_clear(void);
+bool pbuf_has_data(void);
#if defined(PROTOCOL_CHIBIOS)
void ps2_interrupt_service_routine(void);
@@ -309,7 +309,7 @@ static inline uint8_t pbuf_dequeue(void) {
return val;
}
-static inline bool pbuf_has_data(void) {
+bool pbuf_has_data(void) {
#if defined(__AVR__)
uint8_t sreg = SREG;
cli();
diff --git a/drivers/ps2/ps2_mouse.c b/drivers/ps2/ps2_mouse.c
index ccb0a929ae..66b48bb3c3 100644
--- a/drivers/ps2/ps2_mouse.c
+++ b/drivers/ps2/ps2_mouse.c
@@ -53,6 +53,7 @@ void ps2_mouse_init(void) {
ps2_mouse_set_remote_mode();
#else
ps2_mouse_enable_data_reporting();
+ ps2_mouse_set_stream_mode();
#endif
#ifdef PS2_MOUSE_ENABLE_SCROLLING
@@ -75,19 +76,33 @@ void ps2_mouse_task(void) {
extern int tp_buttons;
/* receives packet from mouse */
+#ifdef PS2_MOUSE_USE_REMOTE_MODE
uint8_t rcv;
rcv = ps2_host_send(PS2_MOUSE_READ_DATA);
if (rcv == PS2_ACK) {
mouse_report.buttons = ps2_host_recv_response() | tp_buttons;
mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER;
mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER;
-#ifdef PS2_MOUSE_ENABLE_SCROLLING
+# ifdef PS2_MOUSE_ENABLE_SCROLLING
mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER;
-#endif
+# endif
+ } else {
+ if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n");
+ return;
+ }
+#else
+ if (pbuf_has_data()) {
+ mouse_report.buttons = ps2_host_recv_response() | tp_buttons;
+ mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER;
+ mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER;
+# ifdef PS2_MOUSE_ENABLE_SCROLLING
+ mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER;
+# endif
} else {
if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n");
return;
}
+#endif
/* if mouse moves or buttons state changes */
if (mouse_report.x || mouse_report.y || mouse_report.v || ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) {
diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c
index 2db7f916fe..1d1e4ccfc6 100644
--- a/drivers/sensors/cirque_pinnacle.c
+++ b/drivers/sensors/cirque_pinnacle.c
@@ -1,8 +1,13 @@
// Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license
+// based on https://github.com/cirque-corp/Cirque_Pinnacle_1CA027/tree/master/Circular_Trackpad
+// with modifications and changes for QMK
+// refer to documentation: Gen2 and Gen3 (Pinnacle ASIC) at https://www.cirque.com/documentation
+
#include "cirque_pinnacle.h"
#include "print.h"
#include "debug.h"
#include "wait.h"
+#include "timer.h"
// Registers for RAP
// clang-format off
@@ -38,11 +43,9 @@
#define ADC_ATTENUATE_3X 0x80
#define ADC_ATTENUATE_4X 0xC0
-// Register config values for this demo
-#define SYSCONFIG_1_VALUE 0x00
-#define FEEDCONFIG_1_VALUE 0x03 // 0x03 for absolute mode 0x01 for relative mode
-#define FEEDCONFIG_2_VALUE 0x1C // 0x1F for normal functionality 0x1E for intellimouse disabled
-#define Z_IDLE_COUNT_VALUE 0x05
+#ifndef CIRQUE_PINNACLE_ATTENUATION
+# define CIRQUE_PINNACLE_ATTENUATION ADC_ATTENUATE_4X
+#endif
// clang-format on
bool touchpad_init;
@@ -110,16 +113,14 @@ void cirque_pinnacle_clear_flags() {
// Enables/Disables the feed
void cirque_pinnacle_enable_feed(bool feedEnable) {
uint8_t temp;
-
RAP_ReadBytes(FEEDCONFIG_1, &temp, 1); // Store contents of FeedConfig1 register
if (feedEnable) {
temp |= 0x01; // Set Feed Enable bit
- RAP_Write(0x04, temp);
} else {
temp &= ~0x01; // Clear Feed Enable bit
- RAP_Write(0x04, temp);
}
+ RAP_Write(FEEDCONFIG_1, temp);
}
/* ERA (Extended Register Access) Functions */
@@ -191,7 +192,7 @@ void cirque_pinnacle_tune_edge_sensitivity(void) {
ERA_ReadBytes(0x0168, &temp, 1);
}
-/* Pinnacle-based TM040040 Functions */
+/* Pinnacle-based TM040040/TM035035/TM023023 Functions */
void cirque_pinnacle_init(void) {
#if defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
spi_init();
@@ -200,39 +201,87 @@ void cirque_pinnacle_init(void) {
#endif
touchpad_init = true;
+
// Host clears SW_CC flag
cirque_pinnacle_clear_flags();
- // Host configures bits of registers 0x03 and 0x05
- RAP_Write(SYSCONFIG_1, SYSCONFIG_1_VALUE);
- RAP_Write(FEEDCONFIG_2, FEEDCONFIG_2_VALUE);
-
- // Host enables preferred output mode (absolute)
- RAP_Write(FEEDCONFIG_1, FEEDCONFIG_1_VALUE);
+ // SysConfig1 (Low Power Mode)
+ // Bit 0: Reset, 1=Reset
+ // Bit 1: Shutdown, 1=Shutdown, 0=Active
+ // Bit 2: Sleep Enable, 1=low power mode, 0=normal mode
+ // send a RESET command now, in case QMK had a soft-reset without a power cycle
+ RAP_Write(SYSCONFIG_1, 0x01);
+ wait_ms(30); // Pinnacle needs 10-15ms to boot, so wait long enough before configuring
+ RAP_Write(SYSCONFIG_1, 0x00);
+ wait_us(50);
- // Host sets z-idle packet count to 5 (default is 30)
- RAP_Write(Z_IDLE_COUNT, Z_IDLE_COUNT_VALUE);
+ // FeedConfig2 (Feature flags for Relative Mode Only)
+ // Bit 0: IntelliMouse Enable, 1=enable, 0=disable
+ // Bit 1: All Taps Disable, 1=disable, 0=enable
+ // Bit 2: Secondary Tap Disable, 1=disable, 0=enable
+ // Bit 3: Scroll Disable, 1=disable, 0=enable
+ // Bit 4: GlideExtend® Disable, 1=disable, 0=enable
+ // Bit 5: reserved
+ // Bit 6: reserved
+ // Bit 7: Swap X & Y, 1=90° rotation, 0=0° rotation
+ RAP_Write(FEEDCONFIG_2, 0x00);
+
+ // FeedConfig1 (Data Output Flags)
+ // Bit 0: Feed enable, 1=feed, 0=no feed
+ // Bit 1: Data mode, 1=absolute, 0=relative
+ // Bit 2: Filter disable, 1=no filter, 0=filter
+ // Bit 3: X disable, 1=no X data, 0=X data
+ // Bit 4: Y disable, 1=no Y data, 0=Y data
+ // Bit 5: reserved
+ // Bit 6: X data Invert, 1=X max to 0, 0=0 to Y max
+ // Bit 7: Y data Invert, 1=Y max to 0, 0=0 to Y max
+ RAP_Write(FEEDCONFIG_1, CIRQUE_PINNACLE_POSITION_MODE << 1);
+
+ // Host sets z-idle packet count to 5 (default is 0x1F/30)
+ RAP_Write(Z_IDLE_COUNT, 5);
+
+ cirque_pinnacle_set_adc_attenuation(CIRQUE_PINNACLE_ATTENUATION);
- cirque_pinnacle_set_adc_attenuation(0xFF);
cirque_pinnacle_tune_edge_sensitivity();
cirque_pinnacle_enable_feed(true);
}
-// Reads XYZ data from Pinnacle registers 0x14 through 0x17
-// Stores result in pinnacle_data_t struct with xValue, yValue, and zValue members
pinnacle_data_t cirque_pinnacle_read_data(void) {
- uint8_t data[6] = {0};
- pinnacle_data_t result = {0};
+ uint8_t data_ready = 0;
+ uint8_t data[6] = {0};
+ pinnacle_data_t result = {0};
+
+ // Check if there is valid data available
+ RAP_ReadBytes(STATUS_1, &data_ready, 1); // bit2 is Software Data Ready, bit3 is Command Complete, bit0 and bit1 are reserved/unused
+ if ((data_ready & 0x04) == 0) {
+ // no data available yet
+ result.valid = false; // be explicit
+ return result;
+ }
+
+ // Read all data bytes
RAP_ReadBytes(PACKET_BYTE_0, data, 6);
+ // Get ready for the next data sample
cirque_pinnacle_clear_flags();
- result.buttonFlags = data[0] & 0x3F;
- result.xValue = data[2] | ((data[4] & 0x0F) << 8);
- result.yValue = data[3] | ((data[4] & 0xF0) << 4);
- result.zValue = data[5] & 0x3F;
-
- result.touchDown = (result.xValue != 0 || result.yValue != 0);
+#if CIRQUE_PINNACLE_POSITION_MODE
+ // Decode data for absolute mode
+ // Register 0x13 is unused in this mode (palm detection area)
+ result.buttonFlags = data[0] & 0x3F; // bit0 to bit5 are switch 0-5, only hardware button presses (from input pin on the Pinnacle chip)
+ result.xValue = data[2] | ((data[4] & 0x0F) << 8); // merge high and low bits for X
+ result.yValue = data[3] | ((data[4] & 0xF0) << 4); // merge high and low bits for Y
+ result.zValue = data[5] & 0x3F; // Z is only lower 6 bits, upper 2 bits are reserved/unused
+ result.touchDown = (result.xValue != 0 || result.yValue != 0); // (0,0) is a "magic coordinate" to indicate "finger touched down"
+#else
+ // Decode data for relative mode
+ // Registers 0x16 and 0x17 are unused in this mode
+ result.buttons = data[0] & 0x07; // bit0 = primary button, bit1 = secondary button, bit2 = auxilary button, if Taps enabled then also software-recognized taps are reported
+ result.xDelta = data[1];
+ result.yDelta = data[2];
+ result.wheelCount = data[3];
+#endif
+ result.valid = true;
return result;
}
diff --git a/drivers/sensors/cirque_pinnacle.h b/drivers/sensors/cirque_pinnacle.h
index c8cb360e03..d65bdb41b6 100644
--- a/drivers/sensors/cirque_pinnacle.h
+++ b/drivers/sensors/cirque_pinnacle.h
@@ -5,23 +5,14 @@
#include <stdint.h>
#include <stdbool.h>
-// Convenient way to store and access measurements
-typedef struct {
- uint16_t xValue;
- uint16_t yValue;
- uint16_t zValue;
- uint8_t buttonFlags;
- bool touchDown;
-} pinnacle_data_t;
-
-void cirque_pinnacle_init(void);
-pinnacle_data_t cirque_pinnacle_read_data(void);
-void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution);
-uint16_t cirque_pinnacle_get_scale(void);
-void cirque_pinnacle_set_scale(uint16_t scale);
-
#ifndef CIRQUE_PINNACLE_TIMEOUT
-# define CIRQUE_PINNACLE_TIMEOUT 20
+# define CIRQUE_PINNACLE_TIMEOUT 20 // I2C timeout in milliseconds
+#endif
+
+#define CIRQUE_PINNACLE_ABSOLUTE_MODE 1
+#define CIRQUE_PINNACLE_RELATIVE_MODE 0
+#ifndef CIRQUE_PINNACLE_POSITION_MODE
+# define CIRQUE_PINNACLE_POSITION_MODE CIRQUE_PINNACLE_ABSOLUTE_MODE
#endif
// Coordinate scaling values
@@ -43,7 +34,9 @@ void cirque_pinnacle_set_scale(uint16_t scale);
#ifndef CIRQUE_PINNACLE_Y_RANGE
# define CIRQUE_PINNACLE_Y_RANGE (CIRQUE_PINNACLE_Y_UPPER - CIRQUE_PINNACLE_Y_LOWER)
#endif
-
+#if !defined(POINTING_DEVICE_TASK_THROTTLE_MS)
+# define POINTING_DEVICE_TASK_THROTTLE_MS 10 // Cirque Pinnacle in normal operation produces data every 10ms. Advanced configuration for pen/stylus usage might require lower values.
+#endif
#if defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c)
# include "i2c_master.h"
// Cirque's 7-bit I2C Slave Address
@@ -72,3 +65,26 @@ void cirque_pinnacle_set_scale(uint16_t scale);
# endif
# endif
#endif
+
+// Convenient way to store and access measurements
+typedef struct {
+ bool valid; // true if valid data was read, false if no data was ready
+#if CIRQUE_PINNACLE_POSITION_MODE
+ uint16_t xValue;
+ uint16_t yValue;
+ uint16_t zValue;
+ uint8_t buttonFlags;
+ bool touchDown;
+#else
+ uint8_t xDelta;
+ uint8_t yDelta;
+ uint8_t wheelCount;
+ uint8_t buttons;
+#endif
+} pinnacle_data_t;
+
+void cirque_pinnacle_init(void);
+pinnacle_data_t cirque_pinnacle_read_data(void);
+void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution);
+uint16_t cirque_pinnacle_get_scale(void);
+void cirque_pinnacle_set_scale(uint16_t scale);
diff --git a/drivers/sensors/cirque_pinnacle_i2c.c b/drivers/sensors/cirque_pinnacle_i2c.c
index 8a38f1dcea..b328dd9a7a 100644
--- a/drivers/sensors/cirque_pinnacle_i2c.c
+++ b/drivers/sensors/cirque_pinnacle_i2c.c
@@ -19,7 +19,7 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, NULL, 0, CIRQUE_PINNACLE_TIMEOUT);
if (i2c_readReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, data, count, CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) {
#ifdef CONSOLE_ENABLE
- dprintf("error right touchpad\n");
+ dprintf("error cirque_pinnacle i2c_readReg\n");
#endif
touchpad_init = false;
}
@@ -34,7 +34,7 @@ void RAP_Write(uint8_t address, uint8_t data) {
if (touchpad_init) {
if (i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, &data, sizeof(data), CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) {
#ifdef CONSOLE_ENABLE
- dprintf("error right touchpad\n");
+ dprintf("error cirque_pinnacle i2c_writeReg\n");
#endif
touchpad_init = false;
}
diff --git a/drivers/sensors/cirque_pinnacle_spi.c b/drivers/sensors/cirque_pinnacle_spi.c
index 34c77df07b..bd980fc863 100644
--- a/drivers/sensors/cirque_pinnacle_spi.c
+++ b/drivers/sensors/cirque_pinnacle_spi.c
@@ -25,7 +25,7 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) {
}
} else {
#ifdef CONSOLE_ENABLE
- dprintf("error right touchpad\n");
+ dprintf("error cirque_pinnacle spi_start read\n");
#endif
touchpad_init = false;
}
@@ -43,7 +43,7 @@ void RAP_Write(uint8_t address, uint8_t data) {
spi_write(data);
} else {
#ifdef CONSOLE_ENABLE
- dprintf("error right touchpad\n");
+ dprintf("error cirque_pinnacle spi_start write\n");
#endif
touchpad_init = false;
}
diff --git a/drivers/sensors/pimoroni_trackball.c b/drivers/sensors/pimoroni_trackball.c
index 333e017a06..88a351316b 100644
--- a/drivers/sensors/pimoroni_trackball.c
+++ b/drivers/sensors/pimoroni_trackball.c
@@ -95,16 +95,3 @@ int16_t pimoroni_trackball_get_offsets(uint8_t negative_dir, uint8_t positive_di
uint16_t magnitude = (scale * offset * offset * precision) >> 7;
return isnegative ? -(int16_t)(magnitude) : (int16_t)(magnitude);
}
-
-void pimoroni_trackball_adapt_values(int8_t* mouse, int16_t* offset) {
- if (*offset > 127) {
- *mouse = 127;
- *offset -= 127;
- } else if (*offset < -127) {
- *mouse = -127;
- *offset += 127;
- } else {
- *mouse = *offset;
- *offset = 0;
- }
-}
diff --git a/drivers/sensors/pimoroni_trackball.h b/drivers/sensors/pimoroni_trackball.h
index e20ee748a7..749f381bbd 100644
--- a/drivers/sensors/pimoroni_trackball.h
+++ b/drivers/sensors/pimoroni_trackball.h
@@ -52,7 +52,6 @@ typedef struct {
void pimoroni_trackball_device_init(void);
void pimoroni_trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
int16_t pimoroni_trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale);
-void pimoroni_trackball_adapt_values(int8_t* mouse, int16_t* offset);
uint16_t pimoroni_trackball_get_cpi(void);
void pimoroni_trackball_set_cpi(uint16_t cpi);
i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data);
diff --git a/drivers/serial.h b/drivers/serial.h
index 0cfdbd9959..fb91b136e7 100644
--- a/drivers/serial.h
+++ b/drivers/serial.h
@@ -27,3 +27,13 @@ void soft_serial_initiator_init(void);
void soft_serial_target_init(void);
bool soft_serial_transaction(int sstd_index);
+
+#ifdef SERIAL_DEBUG
+# include <debug.h>
+# include <print.h>
+# define serial_dprintf(...) dprintf(__VA_ARGS__)
+#else
+# define serial_dprintf(...) \
+ do { \
+ } while (0)
+#endif
diff --git a/drivers/wear_leveling/wear_leveling_flash_spi.c b/drivers/wear_leveling/wear_leveling_flash_spi.c
new file mode 100644
index 0000000000..6191f8bf09
--- /dev/null
+++ b/drivers/wear_leveling/wear_leveling_flash_spi.c
@@ -0,0 +1,101 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <stdbool.h>
+#include <hal.h>
+#include "util.h"
+#include "timer.h"
+#include "wear_leveling.h"
+#include "wear_leveling_internal.h"
+
+#ifndef WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT
+# define WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT 32
+#endif // WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT
+
+bool backing_store_init(void) {
+ bs_dprintf("Init\n");
+ flash_init();
+ return true;
+}
+
+bool backing_store_unlock(void) {
+ bs_dprintf("Unlock\n");
+ // No-op -- handled by the flash driver as it is.
+ return true;
+}
+
+bool backing_store_erase(void) {
+#ifdef WEAR_LEVELING_DEBUG_OUTPUT
+ uint32_t start = timer_read32();
+#endif
+
+ bool ret = true;
+ for (int i = 0; i < (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT); ++i) {
+ flash_status_t status = flash_erase_block(((WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) + i) * (EXTERNAL_FLASH_BLOCK_SIZE));
+ if (status != FLASH_STATUS_SUCCESS) {
+ ret = false;
+ break;
+ }
+ }
+
+ bs_dprintf("Backing store erase took %ldms to complete\n", ((long)(timer_read32() - start)));
+ return ret;
+}
+
+bool backing_store_write(uint32_t address, backing_store_int_t value) {
+ return backing_store_write_bulk(address, &value, 1);
+}
+
+bool backing_store_lock(void) {
+ bs_dprintf("Lock \n");
+ // No-op -- handled by the flash driver as it is.
+ return true;
+}
+
+bool backing_store_read(uint32_t address, backing_store_int_t *value) {
+ return backing_store_read_bulk(address, value, 1);
+}
+
+bool backing_store_read_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
+ bs_dprintf("Read ");
+ uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address;
+ flash_status_t status = flash_read_block(offset, values, sizeof(backing_store_int_t) * item_count);
+ if (status == FLASH_STATUS_SUCCESS) {
+ for (size_t i = 0; i < item_count; ++i) {
+ values[i] = ~values[i];
+ }
+ wl_dump(offset, values, sizeof(backing_store_int_t) * item_count);
+ }
+ return status == FLASH_STATUS_SUCCESS;
+}
+
+bool backing_store_write_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
+ uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address;
+ size_t index = 0;
+ backing_store_int_t temp[WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT];
+ do {
+ // Copy out the block of data we want to transmit first
+ size_t this_loop = MIN(item_count, WEAR_LEVELING_EXTERNAL_FLASH_BULK_COUNT);
+ for (size_t i = 0; i < this_loop; ++i) {
+ temp[i] = values[index + i];
+ }
+
+ bs_dprintf("Write ");
+ wl_dump(offset, temp, sizeof(backing_store_int_t) * this_loop);
+
+ // Take the complement instead
+ for (size_t i = 0; i < this_loop; ++i) {
+ temp[i] = ~temp[i];
+ }
+
+ // Write out the block
+ if (flash_write_block(offset, temp, sizeof(backing_store_int_t) * this_loop) != FLASH_STATUS_SUCCESS) {
+ return false;
+ }
+
+ offset += this_loop * sizeof(backing_store_int_t);
+ index += this_loop;
+ item_count -= this_loop;
+ } while (item_count > 0);
+
+ return true;
+}
diff --git a/drivers/wear_leveling/wear_leveling_flash_spi_config.h b/drivers/wear_leveling/wear_leveling_flash_spi_config.h
new file mode 100644
index 0000000000..394370daa3
--- /dev/null
+++ b/drivers/wear_leveling/wear_leveling_flash_spi_config.h
@@ -0,0 +1,34 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#ifndef __ASSEMBLER__
+# include <stdlib.h>
+# include <stdint.h>
+# include "flash_spi.h"
+#endif
+
+// Use 1 block -- check the config for the SPI flash to determine how big it is
+#ifndef WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT
+# define WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT 1
+#endif // WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT
+
+// Start at the first block of the external flash
+#ifndef WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET
+# define WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET 0
+#endif // WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET
+
+// 8-byte writes by default
+#ifndef BACKING_STORE_WRITE_SIZE
+# define BACKING_STORE_WRITE_SIZE 8
+#endif
+
+// The space allocated by the block
+#ifndef WEAR_LEVELING_BACKING_SIZE
+# define WEAR_LEVELING_BACKING_SIZE ((EXTERNAL_FLASH_BLOCK_SIZE) * (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT))
+#endif // WEAR_LEVELING_BACKING_SIZE
+
+// Use half of the backing size for logical EEPROM
+#ifndef WEAR_LEVELING_LOGICAL_SIZE
+# define WEAR_LEVELING_LOGICAL_SIZE ((WEAR_LEVELING_BACKING_SIZE) / 2)
+#endif // WEAR_LEVELING_LOGICAL_SIZE
diff --git a/keyboards/1k/keymaps/tap_dance/config.h b/keyboards/1k/keymaps/tap_dance/config.h
index 5df7869537..bd0163e447 100644
--- a/keyboards/1k/keymaps/tap_dance/config.h
+++ b/keyboards/1k/keymaps/tap_dance/config.h
@@ -4,3 +4,4 @@
#pragma once
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
diff --git a/keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/config.h b/keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/config.h
index c835440076..161b46c814 100644
--- a/keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/config.h
+++ b/keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/config.h
@@ -3,6 +3,7 @@
/* tap dance stuff*/
#undef TAPPING_TERM
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
#define TAPPING_TOGGLE 2
@@ -12,4 +13,4 @@
#define EXAMPLESTRING4 "tapdance_4"
#undef RGBLED_NUM
-#define RGBLED_NUM 16 \ No newline at end of file
+#define RGBLED_NUM 16
diff --git a/keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/keymap.c b/keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/keymap.c
index 6b7b36cbb2..eeca552657 100644
--- a/keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/keymap.c
+++ b/keyboards/1upkeyboards/sweet16/keymaps/ridingintraffic/keymap.c
@@ -196,7 +196,7 @@ void matrix_scan_user(void) {
}
}
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _TAPLAND:
rgblight_setrgb(0, 16, 0); //green
break;
diff --git a/keyboards/40percentclub/gherkin/keymaps/itsaferbie/keymap.c b/keyboards/40percentclub/gherkin/keymaps/itsaferbie/keymap.c
index 950b6e86b9..32c074c88f 100644
--- a/keyboards/40percentclub/gherkin/keymaps/itsaferbie/keymap.c
+++ b/keyboards/40percentclub/gherkin/keymaps/itsaferbie/keymap.c
@@ -105,7 +105,7 @@ void matrix_scan_user(void) {
#ifdef RGBLIGHT_ENABLE
static uint8_t old_layer = 255;
- uint8_t new_layer = biton32(layer_state);
+ uint8_t new_layer = get_highest_layer(layer_state);
// Color of the Icons.
if (old_layer != new_layer) {
diff --git a/keyboards/40percentclub/half_n_half/keymaps/Boy_314/keymap.c b/keyboards/40percentclub/half_n_half/keymaps/Boy_314/keymap.c
index 2eef3dc48b..bd467482fe 100644
--- a/keyboards/40percentclub/half_n_half/keymaps/Boy_314/keymap.c
+++ b/keyboards/40percentclub/half_n_half/keymaps/Boy_314/keymap.c
@@ -128,10 +128,10 @@ void tap_dance_choose_layer_reset (qk_tap_dance_state_t *state, void *user_data)
layer_off(_RAISE);
break;
case 3:
- if (biton32(default_layer_state) == _DVORAK) {
+ if (get_highest_layer(default_layer_state) == _DVORAK) {
set_single_persistent_default_layer(_QWERTY);
}
- else if (biton32(default_layer_state) == _QWERTY) {
+ else if (get_highest_layer(default_layer_state) == _QWERTY) {
set_single_persistent_default_layer(_DVORAK);
}
break;
diff --git a/keyboards/40percentclub/mf68/keymaps/delivrance/rules.mk b/keyboards/40percentclub/mf68/keymaps/delivrance/rules.mk
index 5ac2ce5ccb..3d056cb71b 100644
--- a/keyboards/40percentclub/mf68/keymaps/delivrance/rules.mk
+++ b/keyboards/40percentclub/mf68/keymaps/delivrance/rules.mk
@@ -1,6 +1,5 @@
BACKLIGHT_DRIVER = custom
NKRO_ENABLE = yes
-TERMINAL_ENABLE = yes
DYNAMIC_MACRO_ENABLE = yes
# Use RAM (fake EEPROM, transient) instead of real EEPROM
diff --git a/keyboards/annepro2/c15/config.h b/keyboards/annepro2/c15/config.h
index ff92aeea8e..2ebb962efb 100644
--- a/keyboards/annepro2/c15/config.h
+++ b/keyboards/annepro2/c15/config.h
@@ -49,3 +49,21 @@
// Obins stock firmware has something similar to this already enabled, but disabled by default in QMK
#define PERMISSIVE_HOLD
+
+// SPI configuration
+#define SPI_DRIVER SPID1
+#define SPI_SCK_PIN A0
+#define SPI_MOSI_PIN A1
+#define SPI_MISO_PIN A2
+
+// Flash configuration
+#define EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN B6
+#define EXTERNAL_FLASH_SPI_CLOCK_DIVISOR 16
+#define EXTERNAL_FLASH_PAGE_SIZE 256
+#define EXTERNAL_FLASH_SECTOR_SIZE 4096
+#define EXTERNAL_FLASH_BLOCK_SIZE 4096
+#define EXTERNAL_FLASH_SIZE (256 * 1024) // 2M-bit flash size
+
+// Wear-leveling driver configuration
+#define WEAR_LEVELING_LOGICAL_SIZE 1024
+#define WEAR_LEVELING_BACKING_SIZE (WEAR_LEVELING_LOGICAL_SIZE * 2)
diff --git a/keyboards/annepro2/c15/rules.mk b/keyboards/annepro2/c15/rules.mk
index 2c518b6339..302aeecbe6 100644
--- a/keyboards/annepro2/c15/rules.mk
+++ b/keyboards/annepro2/c15/rules.mk
@@ -26,6 +26,10 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
AUDIO_ENABLE = no # Audio output
+# Wear-levelling driver
+EEPROM_DRIVER = wear_leveling
+WEAR_LEVELING_DRIVER = spi_flash
+
# Custom RGB matrix handling
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = custom
diff --git a/keyboards/annepro2/c18/config.h b/keyboards/annepro2/c18/config.h
index 82a406a157..5e4978048b 100644
--- a/keyboards/annepro2/c18/config.h
+++ b/keyboards/annepro2/c18/config.h
@@ -47,3 +47,21 @@
// Obins stock firmware has something similar to this already enabled, but disabled by default in QMK
#define PERMISSIVE_HOLD
+
+// SPI configuration
+#define SPI_DRIVER SPID1
+#define SPI_SCK_PIN A0
+#define SPI_MOSI_PIN A1
+#define SPI_MISO_PIN A2
+
+// Flash configuration
+#define EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN A3
+#define EXTERNAL_FLASH_SPI_CLOCK_DIVISOR 16
+#define EXTERNAL_FLASH_PAGE_SIZE 256
+#define EXTERNAL_FLASH_SECTOR_SIZE 4096
+#define EXTERNAL_FLASH_BLOCK_SIZE 4096
+#define EXTERNAL_FLASH_SIZE (256 * 1024) // 2M-bit flash size
+
+// Wear-leveling driver configuration
+#define WEAR_LEVELING_LOGICAL_SIZE 1024
+#define WEAR_LEVELING_BACKING_SIZE (WEAR_LEVELING_LOGICAL_SIZE * 2)
diff --git a/keyboards/annepro2/c18/rules.mk b/keyboards/annepro2/c18/rules.mk
index 60c2e08648..b1c7208f8b 100644
--- a/keyboards/annepro2/c18/rules.mk
+++ b/keyboards/annepro2/c18/rules.mk
@@ -26,6 +26,10 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
AUDIO_ENABLE = no # Audio output
+# Wear-levelling driver
+EEPROM_DRIVER = wear_leveling
+WEAR_LEVELING_DRIVER = spi_flash
+
# Custom RGB matrix handling
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = custom
diff --git a/keyboards/annepro2/halconf.h b/keyboards/annepro2/halconf.h
index 686b91a7fb..dcb04eab1b 100644
--- a/keyboards/annepro2/halconf.h
+++ b/keyboards/annepro2/halconf.h
@@ -25,4 +25,8 @@
#define SERIAL_USB_BUFFERS_SIZE 256
+#define HAL_USE_SPI TRUE
+#define SPI_USE_WAIT TRUE
+#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
+
#include_next <halconf.h>
diff --git a/keyboards/annepro2/mcuconf.h b/keyboards/annepro2/mcuconf.h
index 8265fe6eb9..9e39bd9681 100644
--- a/keyboards/annepro2/mcuconf.h
+++ b/keyboards/annepro2/mcuconf.h
@@ -60,3 +60,11 @@
#define HT32_USB_USE_USB0 TRUE
#define HT32_USB_USB0_IRQ_PRIORITY 5
+
+/*
+ * SPI driver setting
+ */
+
+#define HT32_SPI_USE_SPI1 TRUE
+#define HT32_SPI1_IRQ_PRIORITY 9
+
diff --git a/keyboards/bandominedoni/keymaps/led/keymap.c b/keyboards/bandominedoni/keymaps/led/keymap.c
index 305756b5b1..4a88d33872 100644
--- a/keyboards/bandominedoni/keymaps/led/keymap.c
+++ b/keyboards/bandominedoni/keymaps/led/keymap.c
@@ -180,7 +180,7 @@ void keyboard_post_init_user(void) {
#ifdef RGB_MATRIX_ENABLE
void rgb_matrix_indicators_user(void) {
if (rgb_matrix_is_enabled()) { // turn the lights on when it is enabled.
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _CLOSE:
// rgb_matrix_set_color(pgm_read_byte(&convert_led_location2number[11]), RGB_RED); // RGB_TOG <- too heavy.
diff --git a/keyboards/bandominedoni/keymaps/via/keymap.c b/keyboards/bandominedoni/keymaps/via/keymap.c
index ad6833d692..342ed1d40c 100644
--- a/keyboards/bandominedoni/keymaps/via/keymap.c
+++ b/keyboards/bandominedoni/keymaps/via/keymap.c
@@ -118,7 +118,7 @@ void keyboard_post_init_user(void) {
#ifdef RGB_MATRIX_ENABLE
void rgb_matrix_indicators_user(void) {
if (rgb_matrix_is_enabled()) { // turn the lights on when it is enabled.
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _CLOSE:
// rgb_matrix_set_color(pgm_read_byte(&convert_led_location2number[11]), RGB_RED); // RGB_TOG <- too heavy.
diff --git a/keyboards/basekeys/slice/rev1/keymaps/2moons/keymap.c b/keyboards/basekeys/slice/rev1/keymaps/2moons/keymap.c
index 26ca151089..1292f2d2ed 100644
--- a/keyboards/basekeys/slice/rev1/keymaps/2moons/keymap.c
+++ b/keyboards/basekeys/slice/rev1/keymaps/2moons/keymap.c
@@ -46,8 +46,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESFL] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _FLOCK),
- [TD_ESQW] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESFL] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _FLOCK),
+ [TD_ESQW] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/basekeys/slice/rev1_rgb/keymaps/2moons_rgb/keymap.c b/keyboards/basekeys/slice/rev1_rgb/keymaps/2moons_rgb/keymap.c
index 05de0e42d0..7e82c7b7d2 100644
--- a/keyboards/basekeys/slice/rev1_rgb/keymaps/2moons_rgb/keymap.c
+++ b/keyboards/basekeys/slice/rev1_rgb/keymaps/2moons_rgb/keymap.c
@@ -39,8 +39,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESFL] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _FLOCK),
- [TD_ESQW] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESFL] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _FLOCK),
+ [TD_ESQW] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/biacco42/ergo42/keymaps/hdbx/keymap.c b/keyboards/biacco42/ergo42/keymaps/hdbx/keymap.c
index bb3b6fac48..58f01bb322 100644
--- a/keyboards/biacco42/ergo42/keymaps/hdbx/keymap.c
+++ b/keyboards/biacco42/ergo42/keymaps/hdbx/keymap.c
@@ -134,7 +134,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
// RGB Underglow使用時ã®ãƒ¬ã‚¤ãƒ¤ãƒ¼æ¯Žã®ã‚«ãƒ©ãƒ¼åˆ‡ã‚Šæ›¿ãˆ
-uint32_t layer_state_set_keymap (uint32_t state) {
+layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
@@ -148,7 +148,7 @@ void matrix_init_user(void) {
layer_state_t layer_state_set_user(layer_state_t state) {
state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST);
#ifdef RGBLIGHT_ENABLE
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _RAISE:
rgblight_setrgb_chartreuse(); // RAISE:シャルトリューズ
break;
diff --git a/keyboards/bpiphany/frosty_flake/keymaps/nikchi/config.h b/keyboards/bpiphany/frosty_flake/keymaps/nikchi/config.h
index 4bc6d2c3c0..e45034f9a8 100644
--- a/keyboards/bpiphany/frosty_flake/keymaps/nikchi/config.h
+++ b/keyboards/bpiphany/frosty_flake/keymaps/nikchi/config.h
@@ -2,6 +2,7 @@
// place overrides here
#define TAPPING_TERM 200
+#define TAPPING_TERM_PER_KEY
#define LEADER_TIMEOUT 800
#define DISABLE_SPACE_CADET_ROLLOVER
diff --git a/keyboards/bpiphany/frosty_flake/keymaps/nikchi/keymap.c b/keyboards/bpiphany/frosty_flake/keymaps/nikchi/keymap.c
index dd2098d945..6db177c183 100644
--- a/keyboards/bpiphany/frosty_flake/keymaps/nikchi/keymap.c
+++ b/keyboards/bpiphany/frosty_flake/keymaps/nikchi/keymap.c
@@ -52,17 +52,33 @@ qk_tap_dance_action_t tap_dance_actions[] = {
// Tap once for CTRL, twice for Caps Lock
[TD_CTCPS] = ACTION_TAP_DANCE_DOUBLE(KC_LCTL, KC_CAPS),
[COPA] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_C), LCTL(KC_V)),
- [EMOJIS] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(cycleEmojis, NULL, NULL, 800),
- [ANIMAL] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(cycleAnimals, NULL, NULL, 800),
- //[SYMBOLS] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(cycleSymbols, NULL, NULL, 800),
- [FOODS] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(cycleFoods, NULL, NULL, 800),
- [ETC] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(cycleEtc, NULL, NULL, 800),
- //[VEHICLES] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(cycleVehicles, NULL, NULL, 800),
- //[SUPPLEMENT] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(cycleSupplement, NULL, NULL, 800),
- [ALLS] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(cycleAll, NULL, NULL, 800)
+ [EMOJIS] = ACTION_TAP_DANCE_FN_ADVANCED(cycleEmojis, NULL, NULL),
+ [ANIMAL] = ACTION_TAP_DANCE_FN_ADVANCED(cycleAnimals, NULL, NULL),
+ //[SYMBOLS] = ACTION_TAP_DANCE_FN_ADVANCED(cycleSymbols, NULL, NULL),
+ [FOODS] = ACTION_TAP_DANCE_FN_ADVANCED(cycleFoods, NULL, NULL),
+ [ETC] = ACTION_TAP_DANCE_FN_ADVANCED(cycleEtc, NULL, NULL),
+ //[VEHICLES] = ACTION_TAP_DANCE_FN_ADVANCED(cycleVehicles, NULL, NULL),
+ //[SUPPLEMENT] = ACTION_TAP_DANCE_FN_ADVANCED(cycleSupplement, NULL, NULL),
+ [ALLS] = ACTION_TAP_DANCE_FN_ADVANCED(cycleAll, NULL, NULL)
// Other declarations would go here, separated by commas, if you have them
};
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case TD(EMOJIS):
+ case TD(ANIMAL):
+ //case TD(SYMBOLS):
+ case TD(FOODS):
+ case TD(ETC):
+ //case TD(VEHICLES):
+ //case TD(SUPPLEMENT):
+ case TD(ALLS):
+ return 800;
+ default:
+ return TAPPING_TERM;
+ }
+}
+
// macros
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
switch(id) {
diff --git a/keyboards/bpiphany/frosty_flake/keymaps/nikchi/variableTapDance.md b/keyboards/bpiphany/frosty_flake/keymaps/nikchi/variableTapDance.md
index b2e5041393..c3fce50f2a 100644
--- a/keyboards/bpiphany/frosty_flake/keymaps/nikchi/variableTapDance.md
+++ b/keyboards/bpiphany/frosty_flake/keymaps/nikchi/variableTapDance.md
@@ -3,7 +3,4 @@ Tap Dance is constrained normally by `TAPPING_TERM` defined in your keyboard's c
-- `ACTION_TAP_DANCE_FN_ADVANCED_TIME(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, tap_specific_tapping_term)` : This works the same as `ACTION_TAP_DANCE_FN_ADVANCED` just with the extra `tap_specific_tapping_term` arguement at the end. This way you can set a specific tap dance to have a longer or shorter tap in between your taps, giving you more, or less, time in between each tap.
-
-
-`tap_specific_tapping_term` should be the same type and range of values that one would put into the `TAPPING_TERM` definition in the config.h file.
+- Implementing `uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record)`, you can set a specific tap dance to have a longer or shorter tap in between your taps, giving you more, or less, time in between each tap. The return value should be the same type and range of values that one would put into the `TAPPING_TERM` definition in the config.h file.
diff --git a/keyboards/bpiphany/kitten_paw/keymaps/ickerwx/keymap.c b/keyboards/bpiphany/kitten_paw/keymaps/ickerwx/keymap.c
index cc4d0bca63..4553d4e0e3 100644
--- a/keyboards/bpiphany/kitten_paw/keymaps/ickerwx/keymap.c
+++ b/keyboards/bpiphany/kitten_paw/keymaps/ickerwx/keymap.c
@@ -89,7 +89,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
void matrix_scan_user(void) {
uint8_t layer;
- layer = biton32(layer_state);
+ layer = get_highest_layer(layer_state);
if (current_layer_global != layer) {
current_layer_global = layer;
@@ -132,7 +132,7 @@ void tap_helper(keyrecord_t *record, uint16_t orig_mod, uint16_t macro_mod, uint
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
uint8_t layer;
- layer = biton32(layer_state);
+ layer = get_highest_layer(layer_state);
if (layer == PROG2) {
if (keycode >= KC_A && keycode <= KC_EXSEL && \
!( // do not send LSFT + these keycodes, they are needed for emulating the US layout
diff --git a/keyboards/bpiphany/pegasushoof/keymaps/blowrak/keymap.c b/keyboards/bpiphany/pegasushoof/keymaps/blowrak/keymap.c
index 7884462021..dc55cdf9fd 100644
--- a/keyboards/bpiphany/pegasushoof/keymaps/blowrak/keymap.c
+++ b/keyboards/bpiphany/pegasushoof/keymaps/blowrak/keymap.c
@@ -77,7 +77,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
void matrix_scan_user(void)
{
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case KM_BLOWRAK:
ph_caps_led_on();
diff --git a/keyboards/cannonkeys/ortho75/ortho75.c b/keyboards/cannonkeys/ortho75/ortho75.c
index 7c722d7156..58b7396a1b 100644
--- a/keyboards/cannonkeys/ortho75/ortho75.c
+++ b/keyboards/cannonkeys/ortho75/ortho75.c
@@ -5,47 +5,48 @@
uint8_t layer = 0;
-uint32_t layer_state_set_kb(uint32_t state) {
- state = layer_state_set_user(state);
- layer = biton32(state);
- return state;
+layer_state_t layer_state_set_kb(layer_state_t state) {
+ state = layer_state_set_user(state);
+ layer = get_highest_layer(state);
+ return state;
}
bool encoder_update_kb(uint8_t index, bool clockwise) {
if (!encoder_update_user(index, clockwise)) return false;
- uint16_t mapped_code = 0;
- if (index == 0) {
- if (clockwise) {
- switch(layer){
- case 0:
- default:
- mapped_code = KC_VOLU;
- break;
- case 1:
- mapped_code = KC_MEDIA_NEXT_TRACK;
- break;
- case 2:
- mapped_code = KC_PGDN;
- break;
+ uint16_t mapped_code = 0;
+ if (index == 0) {
+ if (clockwise) {
+ switch (layer) {
+ case 0:
+ default:
+ mapped_code = KC_VOLU;
+ break;
+ case 1:
+ mapped_code = KC_MEDIA_NEXT_TRACK;
+ break;
+ case 2:
+ mapped_code = KC_PGDN;
+ break;
+ }
+ } else {
+ switch (layer) {
+ case 0:
+ default:
+ mapped_code = KC_VOLD;
+ break;
+ case 1:
+ mapped_code = KC_MEDIA_PREV_TRACK;
+ break;
+ case 2:
+ mapped_code = KC_PGUP;
+ break;
+ }
}
- } else {
- switch(layer){
- case 0:
- default:
- mapped_code = KC_VOLD;
- break;
- case 1:
- mapped_code = KC_MEDIA_PREV_TRACK;
- break;
- case 2:
- mapped_code = KC_PGUP;
- break;
+ uint16_t held_keycode_timer = timer_read();
+ register_code(mapped_code);
+ while (timer_elapsed(held_keycode_timer) < MEDIA_KEY_DELAY) { /* no-op */
}
+ unregister_code(mapped_code);
}
- uint16_t held_keycode_timer = timer_read();
- register_code(mapped_code);
- while (timer_elapsed(held_keycode_timer) < MEDIA_KEY_DELAY){ /* no-op */ }
- unregister_code(mapped_code);
- }
- return true;
+ return true;
}
diff --git a/keyboards/cannonkeys/satisfaction75/satisfaction75.c b/keyboards/cannonkeys/satisfaction75/satisfaction75.c
index bd7eaf1885..9435377839 100644
--- a/keyboards/cannonkeys/satisfaction75/satisfaction75.c
+++ b/keyboards/cannonkeys/satisfaction75/satisfaction75.c
@@ -240,7 +240,7 @@ void read_host_led_state(void) {
layer_state_t layer_state_set_kb(layer_state_t state) {
state = layer_state_set_user(state);
- layer = biton32(state);
+ layer = get_highest_layer(state);
oled_request_wakeup();
return state;
}
diff --git a/keyboards/ckeys/handwire_101/keymaps/default/keymap.c b/keyboards/ckeys/handwire_101/keymaps/default/keymap.c
index 3bb1a2c009..3f5ebc8655 100755
--- a/keyboards/ckeys/handwire_101/keymaps/default/keymap.c
+++ b/keyboards/ckeys/handwire_101/keymaps/default/keymap.c
@@ -134,10 +134,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `--------=======------------------------'
*/
[_TERMINAL] = LAYOUT_ortho_4x4(
- _______, TERM_ABOUT, _______, _______,
- TERM_OFF, TERM_PRINT, _______, _______,
- _______, TERM_FLUSH, _______, _______,
- TERM_ON, TERM_HELP , _______, _______
+ _______, TERM_ABOUT, _______, _______,
+ _______, TERM_PRINT, _______, _______,
+ _______, TERM_FLUSH, _______, _______,
+ _______, TERM_HELP , _______, _______
),
/* ADMIN
* ,-----------------------------------------.
diff --git a/keyboards/ckeys/handwire_101/rules.mk b/keyboards/ckeys/handwire_101/rules.mk
index 8fa32bcee5..3131bb405a 100755
--- a/keyboards/ckeys/handwire_101/rules.mk
+++ b/keyboards/ckeys/handwire_101/rules.mk
@@ -12,7 +12,6 @@ MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
-TERMINAL_ENABLE = yes
NKRO_ENABLE = yes # Enable N-Key Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
AUDIO_ENABLE = no # Audio output
diff --git a/keyboards/ckeys/washington/keymaps/default/keymap.c b/keyboards/ckeys/washington/keymaps/default/keymap.c
index 95e0f3ab59..9ce0181fe4 100644
--- a/keyboards/ckeys/washington/keymaps/default/keymap.c
+++ b/keyboards/ckeys/washington/keymaps/default/keymap.c
@@ -40,7 +40,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
bool encoder_update_user(uint8_t index, bool clockwise) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _BASE:
if (clockwise) {
tap_code(KC_VOLU);
@@ -62,7 +62,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
bool oled_task_user(void) {
// Host Keyboard Layer Status
oled_write_P(PSTR("Layer: "), false);
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _BASE:
oled_write_P(PSTR("Default\n"), false);
break;
diff --git a/keyboards/clueboard/66/keymaps/magicmonty/keymap.c b/keyboards/clueboard/66/keymaps/magicmonty/keymap.c
index 56d4c47071..7b7d2bdce0 100644
--- a/keyboards/clueboard/66/keymaps/magicmonty/keymap.c
+++ b/keyboards/clueboard/66/keymaps/magicmonty/keymap.c
@@ -199,7 +199,7 @@ void matrix_scan_user(void) {
if (!rgblight_config.enable || rgblight_config.mode != 1) { return; }
- uint32_t layer = layer_state;
+ layer_state_t layer = layer_state;
uint8_t val = rgblight_config.val;
if (layer & (1<<_FL)) {
diff --git a/keyboards/contra/keymaps/default/keymap.c b/keyboards/contra/keymaps/default/keymap.c
index 6c05ebebff..1a365c9a6d 100644
--- a/keyboards/contra/keymaps/default/keymap.c
+++ b/keyboards/contra/keymaps/default/keymap.c
@@ -163,7 +163,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_ADJUST] = LAYOUT_planck_mit(
_______, QK_BOOT, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL ,
_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______,
- _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______,
+ _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
diff --git a/keyboards/crkbd/keymaps/dsanchezseco/keymap.c b/keyboards/crkbd/keymaps/dsanchezseco/keymap.c
index 6ef428a11f..ab84e5c580 100644
--- a/keyboards/crkbd/keymaps/dsanchezseco/keymap.c
+++ b/keyboards/crkbd/keymaps/dsanchezseco/keymap.c
@@ -84,7 +84,7 @@ oled_rotation_t oled_init_user(oled_rotation_t rotation) {
const char *read_logo(void);
bool oled_task_user(void){
- switch (biton32(layer_state)){
+ switch (get_highest_layer(layer_state)){
case _DVORAK:
oled_write_ln_P(PSTR("DVRK"), false);
break;
diff --git a/keyboards/crkbd/keymaps/edvorakjp/keymap.c b/keyboards/crkbd/keymaps/edvorakjp/keymap.c
index 5e56da61a9..f3b801da68 100644
--- a/keyboards/crkbd/keymaps/edvorakjp/keymap.c
+++ b/keyboards/crkbd/keymaps/edvorakjp/keymap.c
@@ -54,9 +54,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format on
#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
-uint32_t layer_state_set_keymap(uint32_t state) {
+layer_state_t layer_state_set_keymap(layer_state_t state) {
rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case L_EDVORAKJP_LOWER:
rgblight_sethsv_noeeprom_red();
break;
diff --git a/keyboards/crkbd/keymaps/edvorakjp/oled.c b/keyboards/crkbd/keymaps/edvorakjp/oled.c
index e5ff029565..cd75f8e277 100644
--- a/keyboards/crkbd/keymaps/edvorakjp/oled.c
+++ b/keyboards/crkbd/keymaps/edvorakjp/oled.c
@@ -9,7 +9,7 @@ void render_layer_state(void) {
char layer_name[17];
oled_write_P(PSTR("Layer: "), false);
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case L_EDVORAKJP_BASE:
oled_write_ln_P(PSTR("Default"), false);
break;
diff --git a/keyboards/crkbd/keymaps/jarred/keymap.c b/keyboards/crkbd/keymaps/jarred/keymap.c
index b938636c2a..3784eff2b8 100644
--- a/keyboards/crkbd/keymaps/jarred/keymap.c
+++ b/keyboards/crkbd/keymaps/jarred/keymap.c
@@ -84,7 +84,7 @@ const char *read_keylogs(void);
char matrix_line_str[24];
const char *read_layer_state(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
strcpy(matrix_line_str, "Layer: ");
diff --git a/keyboards/delikeeb/vaneela/keymaps/default/keymap.c b/keyboards/delikeeb/vaneela/keymaps/default/keymap.c
index b1d7401b9d..57df91cd4d 100644
--- a/keyboards/delikeeb/vaneela/keymaps/default/keymap.c
+++ b/keyboards/delikeeb/vaneela/keymaps/default/keymap.c
@@ -106,7 +106,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[_FN] = LAYOUT_ortho_5x12(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
- _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______,TERM_ON, TERM_OFF, KC_DEL,
+ _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______,_______, _______, KC_DEL,
_______, _______, _______, _______, _______, AG_NORM, AG_SWAP, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/keyboards/delikeeb/vaneela/keymaps/via/keymap.c b/keyboards/delikeeb/vaneela/keymaps/via/keymap.c
index 65194b84d3..4bfee3daf5 100644
--- a/keyboards/delikeeb/vaneela/keymaps/via/keymap.c
+++ b/keyboards/delikeeb/vaneela/keymaps/via/keymap.c
@@ -105,7 +105,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[_FN] = LAYOUT_ortho_5x12(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
- _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______,TERM_ON, TERM_OFF, KC_DEL,
+ _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL,
_______, _______, _______, _______, _______, AG_NORM, AG_SWAP, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/keyboards/dichotomy/keymaps/default/keymap.c b/keyboards/dichotomy/keymaps/default/keymap.c
index b8c7ef4274..80fc4d89bc 100755
--- a/keyboards/dichotomy/keymaps/default/keymap.c
+++ b/keyboards/dichotomy/keymaps/default/keymap.c
@@ -109,7 +109,7 @@ report_mouse_t currentReport = {};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
//uint8_t layer;
- //layer = biton32(layer_state); // get the current layer //Or don't, I didn't use it.
+ //layer = get_highest_layer(layer_state); // get the current layer //Or don't, I didn't use it.
bool returnVal = true; //this is to determine if more key processing is needed.
//custom layer handling for tri_layer,
@@ -437,7 +437,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
};
void matrix_scan_user(void) {
- //uint8_t layer = biton32(layer_state);
+ //uint8_t layer = get_highest_layer(layer_state);
for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
if ((timer_elapsed(special_timers[i]) >= CUSTOM_LONGPRESS) && (!special_key_states[i]) && special_key_pressed[i]){
switch (i + SAFE_RANGE){
diff --git a/keyboards/dm9records/plaid/keymaps/default/keymap.c b/keyboards/dm9records/plaid/keymaps/default/keymap.c
index f11b744066..d96c250609 100644
--- a/keyboards/dm9records/plaid/keymaps/default/keymap.c
+++ b/keyboards/dm9records/plaid/keymaps/default/keymap.c
@@ -195,7 +195,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_ADJUST] = LAYOUT_plaid_grid(
QK_BOOT,LED_1, LED_2, LED_3, LED_4, LED_5,LED_6, LED_7, LED_8, LED_9, LED_0,KC_DEL ,
_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______,
- _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______,
+ _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
diff --git a/keyboards/dm9records/plaid/keymaps/thehalfdeafchef/keymap.c b/keyboards/dm9records/plaid/keymaps/thehalfdeafchef/keymap.c
index 6dcabb160e..e617d0dd5f 100644
--- a/keyboards/dm9records/plaid/keymaps/thehalfdeafchef/keymap.c
+++ b/keyboards/dm9records/plaid/keymaps/thehalfdeafchef/keymap.c
@@ -129,7 +129,7 @@ layer_state_t layer_state_set_user(layer_state_t state) { return update_tri_laye
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _LOWER:
diff --git a/keyboards/doppelganger/doppelganger.c b/keyboards/doppelganger/doppelganger.c
index 04d19480da..304d764028 100644
--- a/keyboards/doppelganger/doppelganger.c
+++ b/keyboards/doppelganger/doppelganger.c
@@ -15,25 +15,31 @@
*/
#include "doppelganger.h"
-void keyboard_pre_init_kb (void) {
- setPinOutput(C6);
- setPinOutput(B0);
+void keyboard_pre_init_kb(void) {
+ setPinOutput(C6);
+ setPinOutput(B0);
}
bool led_update_kb(led_t led_state) {
- bool res = led_update_user(led_state);
- if(res) {
- // writePin sets the pin high for 1 and low for 0.
- // In this example the pins are inverted, setting
- // it low/0 turns it on, and high/1 turns the LED off.
- // This behavior depends on whether the LED is between the pin
- // and VCC or the pin and GND.
- writePin(C6, !led_state.caps_lock);
- }
- return res;
+ bool res = led_update_user(led_state);
+ if (res) {
+ // writePin sets the pin high for 1 and low for 0.
+ // In this example the pins are inverted, setting
+ // it low/0 turns it on, and high/1 turns the LED off.
+ // This behavior depends on whether the LED is between the pin
+ // and VCC or the pin and GND.
+ writePin(C6, !led_state.caps_lock);
+ }
+ return res;
}
__attribute__((weak)) layer_state_t layer_state_set_user(layer_state_t state) {
- writePin(B0, !(state & (1UL << 1)));
- return state;
+ writePin(B0, !(state & (1UL << 1)));
+ return state;
+}
+
+// Override core logic as we reuse SPLIT_HAND_PIN within matrix pins
+bool is_keyboard_left(void) {
+ setPinInput(SPLIT_HAND_PIN);
+ return readPin(SPLIT_HAND_PIN);
}
diff --git a/keyboards/duck/lightsaver/keymaps/rasmus/keymap.c b/keyboards/duck/lightsaver/keymaps/rasmus/keymap.c
index 70dc17bb13..65f128a26b 100644
--- a/keyboards/duck/lightsaver/keymaps/rasmus/keymap.c
+++ b/keyboards/duck/lightsaver/keymaps/rasmus/keymap.c
@@ -34,8 +34,8 @@ enum {
//Tap Dance Definitions
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_F1_GAME] = ACTION_TAP_DANCE_DUAL_ROLE(KC_F1, GAME),
- [TD_CAPS_FN] = ACTION_TAP_DANCE_DUAL_ROLE(KC_CAPS, 5)
+ [TD_F1_GAME] = ACTION_TAP_DANCE_LAYER_MOVE(KC_F1, GAME),
+ [TD_CAPS_FN] = ACTION_TAP_DANCE_LAYER_MOVE(KC_CAPS, 5)
};
enum macro_id {
diff --git a/keyboards/dz60/keymaps/iso_split-spacebar/keymap.c b/keyboards/dz60/keymaps/iso_split-spacebar/keymap.c
index a9e811f9a4..d3956ce3f0 100644
--- a/keyboards/dz60/keymaps/iso_split-spacebar/keymap.c
+++ b/keyboards/dz60/keymaps/iso_split-spacebar/keymap.c
@@ -4,12 +4,12 @@
// thanks to atlacat, hailbreno, itsaferbie and weeheavy...
// and special thanks to AGausmann and drashna for the layer-activated RGB underglow
-// https://www.reddit.com/r/olkb/comments/6t1vdu/update_layeractivated_rgb_underglow/
+// https://www.reddit.com/r/olkb/comments/6t1vdu/update_layeractivated_rgb_underglow/
// https://github.com/AGausmann/qmk_firmware/blob/agausmann-v3.x/keyboards/nyquist/keymaps/agausmann/keymap.c
#include QMK_KEYBOARD_H
-/*
+/*
* Each layer gets a name for readability.
* The underscores don't mean anything - you can
* have a layer called STUFF or any other name.
@@ -23,8 +23,8 @@
#define NL 2 // Numpad Layer
#define RL 3 // RGB Layer
-/*
-* Let's give an easier name to the RGB modes
+/*
+* Let's give an easier name to the RGB modes
* and assign the ones we want to the different layer
* these will then be used by the function below
*
@@ -49,10 +49,10 @@
//
#define RGB_RL_MODE rgblight_mode_noeeprom(22) //rgb mode for RL layer
#define RGB_RL_LIGHT rgblight_sethsv_noeeprom_red() //rgb light for RL layer
-
+
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
-
+
/* Keymap BL: Base Layer (Default Layer)
*
* ,-----------------------------------------------------------.
@@ -140,7 +140,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, RGB_STA, RGB_BRE, RGB_RAI, RGB_SWI, _______, _______, RGB_SNA, RGB_KNI, RGB_GRA, RGB_XMS, _______, _______, _______,
_______, BL_DEC, BL_TOGG, BL_INC, BL_STEP, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, MO(FL), _______, _______, _______, TO(BL), _______),
-
+
};
@@ -175,25 +175,25 @@ void matrix_scan_user(void) {
#ifdef RGBLIGHT_ENABLE
static uint8_t old_layer = 1;
- uint8_t new_layer = biton32(layer_state);
+ uint8_t new_layer = get_highest_layer(layer_state);
if (old_layer != new_layer) {
switch (new_layer) {
case BL:
RGB_BL_MODE;
- RGB_BL_LIGHT;
+ RGB_BL_LIGHT;
break;
case FL:
RGB_FL_MODE;
- RGB_FL_LIGHT;
+ RGB_FL_LIGHT;
break;
case NL:
- RGB_NL_MODE;
- RGB_NL_LIGHT;
+ RGB_NL_MODE;
+ RGB_NL_LIGHT;
break;
case RL:
- RGB_RL_MODE;
- RGB_RL_LIGHT;
+ RGB_RL_MODE;
+ RGB_RL_LIGHT;
break;
}
diff --git a/keyboards/dz60/keymaps/marianas/customLogic.c b/keyboards/dz60/keymaps/marianas/customLogic.c
index f22bd882e9..03ba92fe92 100644
--- a/keyboards/dz60/keymaps/marianas/customLogic.c
+++ b/keyboards/dz60/keymaps/marianas/customLogic.c
@@ -11,7 +11,7 @@ static int16_t fnTimer = 0;
layer_state_t layer_state_set_user(layer_state_t state)
{
- switch (biton32(state))
+ switch (get_highest_layer(state))
{
case QWERTY:
rgblight_mode(9);
diff --git a/keyboards/dz60/keymaps/xtonhasvim/keymap.c b/keyboards/dz60/keymaps/xtonhasvim/keymap.c
index 9a482686d8..49bc20b576 100644
--- a/keyboards/dz60/keymaps/xtonhasvim/keymap.c
+++ b/keyboards/dz60/keymaps/xtonhasvim/keymap.c
@@ -73,7 +73,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
static uint32_t last_state = 0;
if(last_state != state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _CMD:
user_led_on();
break;
@@ -85,5 +85,3 @@ layer_state_t layer_state_set_user(layer_state_t state) {
}
return state;
}
-
-
diff --git a/keyboards/dztech/dz60rgb/keymaps/matthewrobo/keymap.c b/keyboards/dztech/dz60rgb/keymaps/matthewrobo/keymap.c
index a12358c8d9..287496e17f 100644
--- a/keyboards/dztech/dz60rgb/keymaps/matthewrobo/keymap.c
+++ b/keyboards/dztech/dz60rgb/keymaps/matthewrobo/keymap.c
@@ -96,7 +96,7 @@ void rgb_matrix_indicators_user(void)
uint8_t this_led = host_keyboard_leds();
if (!g_suspend_state && rgb_matrix_config.enable) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _NAV:
if (this_led & (1 << USB_LED_NUM_LOCK)) {
rgb_matrix_set_color(13, 0xFF, 0x00, 0x00);
diff --git a/keyboards/dztech/dz60rgb/keymaps/mekanist/keymap.c b/keyboards/dztech/dz60rgb/keymaps/mekanist/keymap.c
index a7c6360568..6af35cf779 100644
--- a/keyboards/dztech/dz60rgb/keymaps/mekanist/keymap.c
+++ b/keyboards/dztech/dz60rgb/keymaps/mekanist/keymap.c
@@ -62,7 +62,7 @@ void rgb_matrix_indicators_user(void)
uint8_t this_led = host_keyboard_leds();
if (!g_suspend_state && rgb_matrix_config.enable) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _LAYER1:
rgb_matrix_layer_helper(0xFF, 0x00, 0x00); break;
@@ -78,7 +78,7 @@ void rgb_matrix_indicators_user(void)
rgb_matrix_set_color(40, 0xFF, 0xFF, 0xFF);
}
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _LAYER3:
if (this_led & (1 << USB_LED_NUM_LOCK)) {
rgb_matrix_set_color(13, 0xFF, 0x00, 0x00);
diff --git a/keyboards/dztech/dz60rgb/keymaps/perseid/keymap.c b/keyboards/dztech/dz60rgb/keymaps/perseid/keymap.c
index c13fcc1d35..daef7b271d 100644
--- a/keyboards/dztech/dz60rgb/keymaps/perseid/keymap.c
+++ b/keyboards/dztech/dz60rgb/keymaps/perseid/keymap.c
@@ -37,7 +37,7 @@ void rgb_matrix_layer_helper (uint8_t red, uint8_t green, uint8_t blue) {
void rgb_matrix_indicators_user(void)
{
if (!g_suspend_state) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _QWERTY:
rgb_matrix_layer_helper(0x00, 0x0F, 0xFF); break;
@@ -46,7 +46,7 @@ void rgb_matrix_indicators_user(void)
}
}
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _FNM:
rgb_matrix_set_color(0, 0x00, 0xFF, 0x00);
rgb_matrix_set_color(1, 0x00, 0x00, 0x00);
diff --git a/keyboards/dztech/dz65rgb/keymaps/catrielmuller/keymap.c b/keyboards/dztech/dz65rgb/keymaps/catrielmuller/keymap.c
index 8bd6069107..817c0fd2ff 100644
--- a/keyboards/dztech/dz65rgb/keymaps/catrielmuller/keymap.c
+++ b/keyboards/dztech/dz65rgb/keymaps/catrielmuller/keymap.c
@@ -238,5 +238,5 @@ void rgb_matrix_indicators_user(void) {
}
// Show Selected Layer
- rgb_matrix_set_color(layers_leds_map[biton32(layer_state)], MAIN_COLOR[0], MAIN_COLOR[1], MAIN_COLOR[2]);
-} \ No newline at end of file
+ rgb_matrix_set_color(layers_leds_map[get_highest_layer(layer_state)], MAIN_COLOR[0], MAIN_COLOR[1], MAIN_COLOR[2]);
+}
diff --git a/keyboards/dztech/dz65rgb/keymaps/drootz/keymap.c b/keyboards/dztech/dz65rgb/keymaps/drootz/keymap.c
index c313f467e3..2ebbddcef7 100644
--- a/keyboards/dztech/dz65rgb/keymaps/drootz/keymap.c
+++ b/keyboards/dztech/dz65rgb/keymaps/drootz/keymap.c
@@ -1,20 +1,20 @@
#include QMK_KEYBOARD_H
/**************** SOME GLOBALS *********************/
-
+
bool onMac = false;
bool isLeader = false;
bool isBlinking = false;
bool isRecording = false;
bool isPlaying = false;
-const float led_dim_ratio = 0.50;
-static uint16_t blink_cycle_timer,
- blink_fade_in_timer,
- blink_fade_out_timer,
+const float led_dim_ratio = 0.50;
+static uint16_t blink_cycle_timer,
+ blink_fade_in_timer,
+ blink_fade_out_timer,
macro_one_play_timer,
macro_two_play_timer,
macro_play_blink_timer = 2000;
-static uint8_t fade_in_step_counter,
+static uint8_t fade_in_step_counter,
fade_out_step_counter,
blink_hsv_value;
@@ -26,13 +26,13 @@ Function to set color with hsv arguments
- "val_ratio" is used to adjust brightness ratio
*/
void rgb_matrix_set_color_hsv(uint8_t led, uint16_t hue, uint16_t sat, uint16_t val, float val_ratio) {
- const uint8_t h = hue <= 255 ? hue : rgb_matrix_config.hsv.h;
+ const uint8_t h = hue <= 255 ? hue : rgb_matrix_config.hsv.h;
const uint8_t s = sat <= 255 ? sat : rgb_matrix_config.hsv.s;
const uint8_t v = val <= 255 ? val * val_ratio : rgb_matrix_config.hsv.v * val_ratio;
HSV hsv_in = {h, s, v};
RGB rgb_out = hsv_to_rgb(hsv_in);
rgb_matrix_set_color(led, rgb_out.r, rgb_out.g, rgb_out.b);
-}
+}
void reset_blink_cycle(void) {
blink_cycle_timer = timer_read();
@@ -110,31 +110,31 @@ const layers_leds_map[] = {
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_MAIN] = LAYOUT_65_ansi(
- KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS,
- KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
- KC_LEAD, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
- KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_DEL,
+ KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
+ KC_LEAD, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_DEL,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(_FN), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
[_MAC] = LAYOUT_65_ansi(
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_LALT, KC_LGUI, KC_TRNS, KC_TRNS, MO(_FN), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
[_FN] = LAYOUT_65_ansi(
- DYN_REC_STOP, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO,
- KC_TRNS, KC_MUTE, KC_VOLU, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RGB_SAD, RGB_SAI, DYN_MACRO_PLAY2, DYN_REC_START2,
- KC_TRNS, KC_BRID, KC_VOLD, KC_BRIU, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RGB_HUD, RGB_HUI, DYN_MACRO_PLAY1, DYN_REC_START1,
- KC_TRNS, TO(_MAIN), TO(_MAC), KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RGB_SPD, RGB_SPI, KC_TRNS, RGB_VAI, KC_NO,
+ DYN_REC_STOP, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO,
+ KC_TRNS, KC_MUTE, KC_VOLU, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RGB_SAD, RGB_SAI, DYN_MACRO_PLAY2, DYN_REC_START2,
+ KC_TRNS, KC_BRID, KC_VOLD, KC_BRIU, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RGB_HUD, RGB_HUI, DYN_MACRO_PLAY1, DYN_REC_START1,
+ KC_TRNS, TO(_MAIN), TO(_MAC), KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RGB_SPD, RGB_SPI, KC_TRNS, RGB_VAI, KC_NO,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_RMOD, RGB_VAD, RGB_MOD
),
-};
+};
//**************** MATRIX SCANS *********************//
-void rgb_matrix_indicators_user(void) {
+void rgb_matrix_indicators_user(void) {
#ifdef RGB_MATRIX_ENABLE
@@ -144,7 +144,7 @@ void rgb_matrix_indicators_user(void) {
/* CapsLock LED indicator */
if (IS_HOST_LED_ON(USB_LED_CAPS_LOCK)) {
rgb_matrix_set_color_hsv(30, 999, 0, led_constant_val, 0.75); // WHITE
- }
+ }
/* Current layer LED indicator */
rgb_matrix_set_color_hsv(layers_leds_map[get_highest_layer(layer_state)], 999, 0, led_constant_val, led_dim_ratio); // WHITE
@@ -155,7 +155,7 @@ void rgb_matrix_indicators_user(void) {
rgb_matrix_set_color_hsv(30, 999, 999, 999, 1); // CONFIG
} else {
rgb_matrix_set_color_hsv(14, 999, 999, 999, led_dim_ratio); // CONFIG
- }
+ }
/* Blinking LED indicator when recording Dynamic Macro */
if (isRecording && isBlinking) {
@@ -174,7 +174,7 @@ void rgb_matrix_indicators_user(void) {
}
}
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _FN:
/* Dynamic Macro LED indicator */
if (isRecording) {
@@ -188,12 +188,12 @@ void rgb_matrix_indicators_user(void) {
/* Layer LED indicators */
rgb_matrix_set_color_hsv(45, 999, 0, led_constant_val, led_dim_ratio); /* WHITE Layer _MAIN */
rgb_matrix_set_color_hsv(46, 999, 0, led_constant_val, led_dim_ratio); /* WHITE Layer _MAC */
- break;
+ break;
}
#endif /* RGB_MATRIX */
}
-
+
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
bool pressed = record->event.pressed;
if (pressed) {
@@ -202,12 +202,12 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
onMac = true;
break;
case TO(_MAIN):
- onMac = false;
+ onMac = false;
break;
}
}
return true;
-}
+}
//**************** LEADER *********************//
@@ -244,7 +244,7 @@ const uint8_t french_accent_index[3] = {
[_ACUTE] = 2
};
-/*
+/*
This represent unicode decimal values
Each index will be mapped to numpad keycode to out put the correct sequence
All codes in this array should be of size 3
@@ -272,8 +272,8 @@ const uint8_t french_decimal_unicodes[5][3][2] = { /*[Letter][Accent][Case]*/
}
},{
{
- 140, // î
- 206 // ÃŽ
+ 140, // î
+ 206 // ÃŽ
}
},{
{
@@ -306,7 +306,7 @@ This is designed and work on an English language keyboard setting on both Window
=> accept french_letter and french_accent enum's as argument
*/
void send_french_accent(uint8_t letter, uint8_t accent) {
-
+
bool isCaps;
uint8_t decimal_unicode_in;
uint8_t decimal_unicode_size = 3;
@@ -330,7 +330,7 @@ void send_french_accent(uint8_t letter, uint8_t accent) {
};
/*
- Function to tap the correct keycodes in sequence for the
+ Function to tap the correct keycodes in sequence for the
"Windows Alt Code" requested, aka Decimal Unicodes
*/
void tap_win_alt_code(void) {
@@ -341,7 +341,7 @@ void send_french_accent(uint8_t letter, uint8_t accent) {
tap_code(numpad_key_map[decimal_unicode_out[i]]);
}
}
-
+
isCaps = IS_HOST_LED_ON(USB_LED_CAPS_LOCK) ? true : false;
if (onMac) {
@@ -372,7 +372,7 @@ void send_french_accent(uint8_t letter, uint8_t accent) {
/*Couple functions used to output the same macro on two different sequences*/
-/* (|) */
+/* (|) */
void ldrkey_send_paranthesis_wrap_ini(void) {
SEND_STRING("()" SS_TAP(X_LEFT));
}
@@ -382,7 +382,7 @@ void ldrkey_send_paranthesis_wrap_word(void) {
onMac ? SEND_STRING(SS_LALT(SS_TAP(X_LEFT)) "(" SS_LALT(SS_TAP(X_RIGHT)) ")") : SEND_STRING(SS_LCTL(SS_TAP(X_LEFT)) "(" SS_LCTL(SS_TAP(X_RIGHT)) ")");
}
-/* (selection) */
+/* (selection) */
void ldrkey_send_paranthesis_wrap_selection(void) {
onMac ? SEND_STRING(SS_LGUI(SS_TAP(X_X)) "()" SS_TAP(X_LEFT) SS_LGUI(SS_TAP(X_V)) SS_TAP(X_RIGHT)) : SEND_STRING(SS_LCTL(SS_TAP(X_X)) "()" SS_TAP(X_LEFT) SS_LCTL(SS_TAP(X_V)) SS_TAP(X_RIGHT));
}
@@ -419,9 +419,9 @@ void ldrkey_send_curlybrace_wrap_selection(void) {
LEADER_EXTERNS();
-void matrix_scan_user(void)
+void matrix_scan_user(void)
{
- LEADER_DICTIONARY()
+ LEADER_DICTIONARY()
{
leading = false;
leader_end();
@@ -476,49 +476,49 @@ void matrix_scan_user(void)
tap_code(KC_CAPS);
}
/* ± => LdrKey > = > - */
- SEQ_TWO_KEYS(KC_EQL, KC_MINS) {
- onMac ? SEND_STRING(SS_LALT(SS_LSFT(SS_TAP(X_EQL)))) : SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_P2) SS_TAP(X_P4) SS_TAP(X_P1) SS_UP(X_LALT));
+ SEQ_TWO_KEYS(KC_EQL, KC_MINS) {
+ onMac ? SEND_STRING(SS_LALT(SS_LSFT(SS_TAP(X_EQL)))) : SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_P2) SS_TAP(X_P4) SS_TAP(X_P1) SS_UP(X_LALT));
}
/* ≤ => LdrKey > - > = */
- SEQ_TWO_KEYS(KC_MINS, KC_EQL) {
- onMac ? SEND_STRING(SS_LALT(SS_TAP(X_COMM))) : SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_P2) SS_TAP(X_P4) SS_TAP(X_P3) SS_UP(X_LALT));
+ SEQ_TWO_KEYS(KC_MINS, KC_EQL) {
+ onMac ? SEND_STRING(SS_LALT(SS_TAP(X_COMM))) : SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_P2) SS_TAP(X_P4) SS_TAP(X_P3) SS_UP(X_LALT));
}
/* ≥ => LdrKey > = > = */
- SEQ_TWO_KEYS(KC_EQL, KC_EQL) {
- onMac ? SEND_STRING(SS_LALT(SS_TAP(X_DOT))) : SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_P2) SS_TAP(X_P4) SS_TAP(X_P2) SS_UP(X_LALT));
+ SEQ_TWO_KEYS(KC_EQL, KC_EQL) {
+ onMac ? SEND_STRING(SS_LALT(SS_TAP(X_DOT))) : SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_P2) SS_TAP(X_P4) SS_TAP(X_P2) SS_UP(X_LALT));
}
/* <= => LdrKey > , > , */
- SEQ_TWO_KEYS(KC_COMM, KC_COMM) {
- SEND_STRING(SS_LSFT(SS_TAP(X_COMM)) SS_TAP(X_SPC) SS_TAP(X_EQL) SS_TAP(X_LEFT) SS_TAP(X_BSPC) SS_TAP(X_RIGHT));
+ SEQ_TWO_KEYS(KC_COMM, KC_COMM) {
+ SEND_STRING(SS_LSFT(SS_TAP(X_COMM)) SS_TAP(X_SPC) SS_TAP(X_EQL) SS_TAP(X_LEFT) SS_TAP(X_BSPC) SS_TAP(X_RIGHT));
}
/* => => LdrKey > . > . */
- SEQ_TWO_KEYS(KC_DOT, KC_DOT) {
- SEND_STRING("=>");
+ SEQ_TWO_KEYS(KC_DOT, KC_DOT) {
+ SEND_STRING("=>");
}
/* ", " => LdrKey > " " */
- SEQ_ONE_KEY(KC_SPC) {
- SEND_STRING(", ");
+ SEQ_ONE_KEY(KC_SPC) {
+ SEND_STRING(", ");
}
/* ". " => LdrKey > " " > " " */
- SEQ_TWO_KEYS(KC_SPC, KC_SPC) {
- SEND_STRING(". ");
+ SEQ_TWO_KEYS(KC_SPC, KC_SPC) {
+ SEND_STRING(". ");
}
/* Backward delete current word (on cursor) */
- SEQ_TWO_KEYS(KC_BSPC, KC_BSPC) {
- onMac ? SEND_STRING(SS_LALT(SS_TAP(X_RIGHT)) SS_LALT(SS_LSFT(SS_TAP(X_LEFT))) SS_TAP(X_BSPC)) : SEND_STRING(SS_LCTL(SS_TAP(X_RIGHT)) SS_LCTL(SS_LSFT(SS_TAP(X_LEFT))) SS_TAP(X_BSPC));
+ SEQ_TWO_KEYS(KC_BSPC, KC_BSPC) {
+ onMac ? SEND_STRING(SS_LALT(SS_TAP(X_RIGHT)) SS_LALT(SS_LSFT(SS_TAP(X_LEFT))) SS_TAP(X_BSPC)) : SEND_STRING(SS_LCTL(SS_TAP(X_RIGHT)) SS_LCTL(SS_LSFT(SS_TAP(X_LEFT))) SS_TAP(X_BSPC));
}
/* Previous word delete */
- SEQ_ONE_KEY(KC_BSPC) {
- onMac ? SEND_STRING(SS_LALT(SS_LSFT(SS_TAP(X_LEFT))) SS_TAP(X_BSPC)) : SEND_STRING(SS_LCTL(SS_LSFT(SS_TAP(X_LEFT))) SS_TAP(X_BSPC));
+ SEQ_ONE_KEY(KC_BSPC) {
+ onMac ? SEND_STRING(SS_LALT(SS_LSFT(SS_TAP(X_LEFT))) SS_TAP(X_BSPC)) : SEND_STRING(SS_LCTL(SS_LSFT(SS_TAP(X_LEFT))) SS_TAP(X_BSPC));
}
/* Forward delete current word (on cursor) */
- SEQ_TWO_KEYS(KC_DEL, KC_DEL) {
+ SEQ_TWO_KEYS(KC_DEL, KC_DEL) {
- onMac ? SEND_STRING(SS_LALT(SS_TAP(X_LEFT)) SS_LALT(SS_LSFT(SS_TAP(X_RIGHT))) SS_TAP(X_DEL)) : SEND_STRING(SS_LCTL(SS_TAP(X_LEFT)) SS_LCTL(SS_LSFT(SS_TAP(X_RIGHT))) SS_TAP(X_DEL));
+ onMac ? SEND_STRING(SS_LALT(SS_TAP(X_LEFT)) SS_LALT(SS_LSFT(SS_TAP(X_RIGHT))) SS_TAP(X_DEL)) : SEND_STRING(SS_LCTL(SS_TAP(X_LEFT)) SS_LCTL(SS_LSFT(SS_TAP(X_RIGHT))) SS_TAP(X_DEL));
}
/* Next word delete */
- SEQ_ONE_KEY(KC_DEL) {
- onMac ? SEND_STRING(SS_LALT(SS_LSFT(SS_TAP(X_RIGHT))) SS_TAP(X_DEL)): SEND_STRING(SS_LCTL(SS_LSFT(SS_TAP(X_RIGHT))) SS_TAP(X_DEL));
+ SEQ_ONE_KEY(KC_DEL) {
+ onMac ? SEND_STRING(SS_LALT(SS_LSFT(SS_TAP(X_RIGHT))) SS_TAP(X_DEL)): SEND_STRING(SS_LCTL(SS_LSFT(SS_TAP(X_RIGHT))) SS_TAP(X_DEL));
}
/* ` => LdrKey > Escape */
SEQ_ONE_KEY(KC_GESC) {
@@ -548,7 +548,7 @@ void matrix_scan_user(void)
SEQ_ONE_KEY(KC_Q) {
onMac ? SEND_STRING(SS_LGUI(SS_TAP(X_Q))) : SEND_STRING(SS_LALT(SS_TAP(X_F4)));
}
- /* " => LdrKey > ' */
+ /* " => LdrKey > ' */
SEQ_ONE_KEY(KC_QUOT) {
SEND_STRING("\"");
}
@@ -657,48 +657,48 @@ void matrix_scan_user(void)
ldrkey_send_curlybrace_wrap_selection();
}
/* Select everything on this line before cursor => LdrKey > Left */
- SEQ_ONE_KEY(KC_LEFT) {
+ SEQ_ONE_KEY(KC_LEFT) {
onMac ? SEND_STRING(SS_LSFT(SS_LGUI(SS_TAP(X_LEFT)))) : SEND_STRING(SS_LSFT(SS_TAP(X_HOME)));
}
/* Select everything on this line after cursor => LdrKey > Right */
- SEQ_ONE_KEY(KC_RIGHT) {
+ SEQ_ONE_KEY(KC_RIGHT) {
onMac ? SEND_STRING(SS_LSFT(SS_LGUI(SS_TAP(X_RIGHT)))) : SEND_STRING(SS_LSFT(SS_TAP(X_END)));
}
/* Select everything on this line before cursor and bring on previous line => LdrKey > Left > Left */
- SEQ_TWO_KEYS(KC_LEFT, KC_LEFT) {
- onMac ? SEND_STRING(SS_LSFT(SS_TAP(X_UP) SS_LGUI(SS_TAP(X_RIGHT)))) : SEND_STRING(SS_LSFT(SS_TAP(X_UP) SS_TAP(X_END)));
+ SEQ_TWO_KEYS(KC_LEFT, KC_LEFT) {
+ onMac ? SEND_STRING(SS_LSFT(SS_TAP(X_UP) SS_LGUI(SS_TAP(X_RIGHT)))) : SEND_STRING(SS_LSFT(SS_TAP(X_UP) SS_TAP(X_END)));
}
/* Select everything on this line => LdrKey > Right > Left */
- SEQ_TWO_KEYS(KC_RIGHT, KC_LEFT) {
- onMac ? SEND_STRING(SS_LGUI(SS_TAP(X_RIGHT) SS_LSFT(SS_LGUI(SS_TAP(X_LEFT))))) : SEND_STRING(SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)));
+ SEQ_TWO_KEYS(KC_RIGHT, KC_LEFT) {
+ onMac ? SEND_STRING(SS_LGUI(SS_TAP(X_RIGHT) SS_LSFT(SS_LGUI(SS_TAP(X_LEFT))))) : SEND_STRING(SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)));
}
/* Select 1x Page Up on the page before the cursor => LdrKey > Up */
- SEQ_ONE_KEY(KC_UP) {
+ SEQ_ONE_KEY(KC_UP) {
SEND_STRING(SS_LSFT(SS_TAP(X_PGUP)));
}
/* Select 1x Page Down on the page after the cursor => LdrKey > Down */
- SEQ_ONE_KEY(KC_DOWN) {
- SEND_STRING(SS_LSFT(SS_TAP(X_PGDN)));
+ SEQ_ONE_KEY(KC_DOWN) {
+ SEND_STRING(SS_LSFT(SS_TAP(X_PGDN)));
}
/* Select everything on the page before the cursor => LdrKey > Up > Up */
- SEQ_TWO_KEYS(KC_UP, KC_UP) {
+ SEQ_TWO_KEYS(KC_UP, KC_UP) {
onMac ? SEND_STRING(SS_LSFT(SS_LGUI(SS_TAP(X_UP)))) : SEND_STRING(SS_LSFT(SS_LCTL(SS_TAP(X_HOME))));
}
/* Select everything on the page after the cursor => LdrKey > Down > Down */
- SEQ_TWO_KEYS(KC_DOWN, KC_DOWN) {
+ SEQ_TWO_KEYS(KC_DOWN, KC_DOWN) {
onMac ? SEND_STRING(SS_LSFT(SS_LGUI(SS_TAP(X_DOWN)))) : SEND_STRING(SS_LSFT(SS_LCTL(SS_TAP(X_END))));
}
/* HELPER => spit out the url of the layout description page on github */
- SEQ_FIVE_KEYS(KC_GESC, KC_GESC, KC_GESC, KC_GESC, KC_GESC) {
+ SEQ_FIVE_KEYS(KC_GESC, KC_GESC, KC_GESC, KC_GESC, KC_GESC) {
SEND_STRING("https://github.com/qmk/qmk_firmware/tree/master/keyboards/dztech/dz65rgb/keymaps/drootz");
}
/* google.ca => LdrKey > G > G */
- SEQ_TWO_KEYS(KC_G, KC_G) {
- SEND_STRING("https://google.ca" SS_TAP(X_ENT));
+ SEQ_TWO_KEYS(KC_G, KC_G) {
+ SEND_STRING("https://google.ca" SS_TAP(X_ENT));
}
/* @gmail => LdrKey > M > L > T */
- SEQ_THREE_KEYS(KC_M, KC_L, KC_T) {
- SEND_STRING("mailto." SS_TAP(X_D) SS_TAP(X_A) SS_TAP(X_N) SS_TAP(X_I) SS_TAP(X_E) SS_TAP(X_L) SS_TAP(X_R) SS_TAP(X_A) SS_TAP(X_C) SS_TAP(X_I) SS_TAP(X_N) SS_TAP(X_E) "@gmail.com");
+ SEQ_THREE_KEYS(KC_M, KC_L, KC_T) {
+ SEND_STRING("mailto." SS_TAP(X_D) SS_TAP(X_A) SS_TAP(X_N) SS_TAP(X_I) SS_TAP(X_E) SS_TAP(X_L) SS_TAP(X_R) SS_TAP(X_A) SS_TAP(X_C) SS_TAP(X_I) SS_TAP(X_N) SS_TAP(X_E) "@gmail.com");
}
/* Show Desktop => LdrKey > D */
SEQ_ONE_KEY(KC_D) {
diff --git a/keyboards/dztech/dz65rgb/keymaps/matthewrobo/keymap.c b/keyboards/dztech/dz65rgb/keymaps/matthewrobo/keymap.c
index 00915a9b4f..0c7bfbbb48 100644
--- a/keyboards/dztech/dz65rgb/keymaps/matthewrobo/keymap.c
+++ b/keyboards/dztech/dz65rgb/keymaps/matthewrobo/keymap.c
@@ -91,7 +91,7 @@ void rgb_matrix_indicators_user(void)
uint8_t this_led = host_keyboard_leds();
if (!g_suspend_state && rgb_matrix_config.enable) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _NAV:
if (IS_LED_ON(this_led, USB_LED_NUM_LOCK)) {
rgb_matrix_set_color(17, 0xFF, 0x00, 0x00);
diff --git a/keyboards/ergodox_ez/keymaps/bepo_tm_style/keymap.c b/keyboards/ergodox_ez/keymaps/bepo_tm_style/keymap.c
index a5b107baae..91798ab188 100755
--- a/keyboards/ergodox_ez/keymaps/bepo_tm_style/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/bepo_tm_style/keymap.c
@@ -190,7 +190,7 @@ static bool is_macro1_recording = false;
// The current set of active layers (as a bitmask).
// There is a global 'layer_state' variable but it is set after the call
// to layer_state_set_user().
-static uint32_t current_layer_state = 0;
+static layer_state_t current_layer_state = 0;
layer_state_t layer_state_set_user(layer_state_t state);
// Method called at the end of the tap dance on the TAP_MACRO key. That key is
diff --git a/keyboards/ergodox_ez/keymaps/blakedietz/keymap.c b/keyboards/ergodox_ez/keymaps/blakedietz/keymap.c
index 5c08d30727..67c50eb129 100644
--- a/keyboards/ergodox_ez/keymaps/blakedietz/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/blakedietz/keymap.c
@@ -200,7 +200,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
@@ -262,4 +262,3 @@ void matrix_scan_user(void) {
// }
// return true;
//}
-
diff --git a/keyboards/ergodox_ez/keymaps/bpruitt-goddard/keymap.c b/keyboards/ergodox_ez/keymaps/bpruitt-goddard/keymap.c
index 229ece0d74..eff7f111b4 100644
--- a/keyboards/ergodox_ez/keymaps/bpruitt-goddard/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/bpruitt-goddard/keymap.c
@@ -98,7 +98,7 @@ static bool is_macro1_recording = false;
// The current set of active layers (as a bitmask).
// There is a global 'layer_state' variable but it is set after the call
// to layer_state_set_user().
-static uint32_t current_layer_state = 0;
+static layer_state_t current_layer_state = 0;
layer_state_t layer_state_set_user(layer_state_t state);
// Method called at the end of the tap dance on the TAP_MACRO key. That key is
diff --git a/keyboards/ergodox_ez/keymaps/default_osx/keymap.c b/keyboards/ergodox_ez/keymaps/default_osx/keymap.c
index 73b1077b83..3ab66078fe 100644
--- a/keyboards/ergodox_ez/keymaps/default_osx/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/default_osx/keymap.c
@@ -141,7 +141,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/keymaps/dvorak_42_key/keymap.c b/keyboards/ergodox_ez/keymaps/dvorak_42_key/keymap.c
index fab2977356..ff9ae77bdd 100644
--- a/keyboards/ergodox_ez/keymaps/dvorak_42_key/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/dvorak_42_key/keymap.c
@@ -725,7 +725,7 @@ void led_set_user(uint8_t usb_led) {
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_2_off();
diff --git a/keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h b/keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h
index da20820787..c35963d842 100644
--- a/keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h
+++ b/keyboards/ergodox_ez/keymaps/hacker_dvorak/config.h
@@ -7,6 +7,7 @@
#undef TAPPING_TERM
#define TAPPING_TERM 175
+#define TAPPING_TERM_PER_KEY
#undef DEBOUNCE
#define DEBOUNCE 15
diff --git a/keyboards/ergodox_ez/keymaps/hacker_dvorak/tap_dance/tap_dance_actions.c b/keyboards/ergodox_ez/keymaps/hacker_dvorak/tap_dance/tap_dance_actions.c
index 59e3e2b0dc..1d5e1cee00 100644
--- a/keyboards/ergodox_ez/keymaps/hacker_dvorak/tap_dance/tap_dance_actions.c
+++ b/keyboards/ergodox_ez/keymaps/hacker_dvorak/tap_dance/tap_dance_actions.c
@@ -13,14 +13,32 @@ qk_tap_dance_action_t tap_dance_actions[] = {
[RPRN_RBRC] = ACTION_TAP_DANCE_DOUBLE(KC_RPRN, KC_RBRC),
[LCBR_LABK] = ACTION_TAP_DANCE_DOUBLE(KC_LCBR, KC_LABK),
[RCBR_RABK] = ACTION_TAP_DANCE_DOUBLE(KC_RCBR, KC_RABK),
- [SCLN_COLN] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, scln_coln_finished, scln_coln_reset, DANCING_TERM),
- [QUOT_DQUO] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, quot_dquot_finished, quot_dquot_reset, DANCING_TERM),
- [DOT_COMM] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, dot_comm_finished, dot_comm_reset, DANCING_TERM),
- [NONE_LEAD] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, none_lead_finished, none_lead_reset, DANCING_TERM),
- [U_ARR_GUI] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, u_arrows_gui_finished, u_arrows_gui_reset, DANCING_TERM),
- [H_MOU_GUI] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, h_mouse_gui_finished, h_mouse_gui_reset, DANCING_TERM),
- [J_MED_MEH] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, j_media_meh_finished, j_media_meh_reset, DANCING_TERM),
- [W_MED_MEH] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, w_media_meh_finished, w_media_meh_reset, DANCING_TERM),
- [K_NUM_HYP] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, k_numpad_hyper_finished, k_numpad_hyper_reset, DANCING_TERM),
- [M_CHO_HYP] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, m_chords_hyper_finished, m_chords_hyper_reset, DANCING_TERM),
+ [SCLN_COLN] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, scln_coln_finished, scln_coln_reset),
+ [QUOT_DQUO] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, quot_dquot_finished, quot_dquot_reset),
+ [DOT_COMM] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dot_comm_finished, dot_comm_reset),
+ [NONE_LEAD] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, none_lead_finished, none_lead_reset),
+ [U_ARR_GUI] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, u_arrows_gui_finished, u_arrows_gui_reset),
+ [H_MOU_GUI] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, h_mouse_gui_finished, h_mouse_gui_reset),
+ [J_MED_MEH] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, j_media_meh_finished, j_media_meh_reset),
+ [W_MED_MEH] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, w_media_meh_finished, w_media_meh_reset),
+ [K_NUM_HYP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, k_numpad_hyper_finished, k_numpad_hyper_reset),
+ [M_CHO_HYP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, m_chords_hyper_finished, m_chords_hyper_reset),
};
+
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case TD(SCLN_COLN):
+ case TD(QUOT_DQUO):
+ case TD(DOT_COMM):
+ case TD(NONE_LEAD):
+ case TD(U_ARR_GUI):
+ case TD(H_MOU_GUI):
+ case TD(J_MED_MEH):
+ case TD(W_MED_MEH):
+ case TD(K_NUM_HYP):
+ case TD(M_CHO_HYP):
+ return DANCING_TERM;
+ default:
+ return TAPPING_TERM;
+ }
+}
diff --git a/keyboards/ergodox_ez/keymaps/hacker_dvorak/user/layer_set_state_user.c b/keyboards/ergodox_ez/keymaps/hacker_dvorak/user/layer_set_state_user.c
index fd022681b0..ed407def79 100644
--- a/keyboards/ergodox_ez/keymaps/hacker_dvorak/user/layer_set_state_user.c
+++ b/keyboards/ergodox_ez/keymaps/hacker_dvorak/user/layer_set_state_user.c
@@ -1,6 +1,6 @@
layer_state_t layer_state_set_user(layer_state_t state) {
- uint8_t layer = biton32(state);
+ uint8_t layer = get_highest_layer(state);
switch (layer) {
case DVORAK:
diff --git a/keyboards/ergodox_ez/keymaps/heartrobotninja/keymap.c b/keyboards/ergodox_ez/keymaps/heartrobotninja/keymap.c
index b6edc17532..91884c8e76 100644
--- a/keyboards/ergodox_ez/keymaps/heartrobotninja/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/heartrobotninja/keymap.c
@@ -370,7 +370,7 @@ LEADER_EXTERNS();
void matrix_scan_user(void)
{
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if (keyboard_report->mods & MOD_BIT(KC_LSFT) ||
((get_oneshot_mods() & MOD_BIT(KC_LSFT)) &&
@@ -677,4 +677,4 @@ void matrix_init_user(void)
wait_ms(1000);
rgblight_effect_knight(50);
-} \ No newline at end of file
+}
diff --git a/keyboards/ergodox_ez/keymaps/kou/keymap.c b/keyboards/ergodox_ez/keymaps/kou/keymap.c
index c8d0a6b5dd..01427c2d2d 100644
--- a/keyboards/ergodox_ez/keymaps/kou/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/kou/keymap.c
@@ -284,7 +284,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/keymaps/lukaus/keymap.c b/keyboards/ergodox_ez/keymaps/lukaus/keymap.c
index 5d797beb18..542e123db3 100644
--- a/keyboards/ergodox_ez/keymaps/lukaus/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/lukaus/keymap.c
@@ -813,7 +813,7 @@ case RU_7:
layer_state_t layer_state_set_user(layer_state_t state) {
- uint8_t layer = biton32(state);
+ uint8_t layer = get_highest_layer(state);
// ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/keymaps/matrixman/keymap.c b/keyboards/ergodox_ez/keymaps/matrixman/keymap.c
index 10b6567cdb..bb6ba5ae34 100644
--- a/keyboards/ergodox_ez/keymaps/matrixman/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/matrixman/keymap.c
@@ -165,7 +165,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/keymaps/nathanvercaemert/keymap.c b/keyboards/ergodox_ez/keymaps/nathanvercaemert/keymap.c
index e31391a674..a3c2176951 100644
--- a/keyboards/ergodox_ez/keymaps/nathanvercaemert/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/nathanvercaemert/keymap.c
@@ -218,7 +218,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
layer_state_t layer_state_set_user(layer_state_t state) {
- uint8_t layer = biton32(state);
+ uint8_t layer = get_highest_layer(state);
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
@@ -431,4 +431,3 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
return true;
}
-
diff --git a/keyboards/ergodox_ez/keymaps/nfriend/keymap.c b/keyboards/ergodox_ez/keymaps/nfriend/keymap.c
index 1d12093bab..ba578dd1c5 100644
--- a/keyboards/ergodox_ez/keymaps/nfriend/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/nfriend/keymap.c
@@ -1057,7 +1057,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
- uint8_t layer = biton32(state);
+ uint8_t layer = get_highest_layer(state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/keymaps/profet_80/keymap.c b/keyboards/ergodox_ez/keymaps/profet_80/keymap.c
index 85455fa9d9..6f602e828e 100644
--- a/keyboards/ergodox_ez/keymaps/profet_80/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/profet_80/keymap.c
@@ -157,7 +157,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/keymaps/pvinis/keymap.c b/keyboards/ergodox_ez/keymaps/pvinis/keymap.c
index 024cefd270..c69621ab98 100644
--- a/keyboards/ergodox_ez/keymaps/pvinis/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/pvinis/keymap.c
@@ -245,11 +245,11 @@ void keyboard_post_init_user_keymap(void) {
}
// light up leds based on the layer
-uint32_t layer_state_set_user_keymap(uint32_t state) {
+layer_state_t layer_state_set_user_keymap(layer_state_t state) {
ergodox_right_led_1_off();
ergodox_right_led_2_off();
ergodox_right_led_3_off();
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case LR_SYSCTL:
ergodox_right_led_3_on(); // blue
break;
@@ -306,7 +306,7 @@ uint32_t layer_state_set_user_keymap(uint32_t state) {
// SYSCTL on first tap, MOUSE ON second tap
// void layers_dance_finished(qk_tap_dance_state_t *state, void *user_data) {
-// uint8_t layer = biton32(layer_state);
+// uint8_t layer = get_highest_layer(layer_state);
// switch(state->count) {
// case 1:
diff --git a/keyboards/ergodox_ez/keymaps/rgb_layer/keymap.c b/keyboards/ergodox_ez/keymaps/rgb_layer/keymap.c
index 3e607edb39..595f3b4ee1 100644
--- a/keyboards/ergodox_ez/keymaps/rgb_layer/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/rgb_layer/keymap.c
@@ -228,7 +228,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
ergodox_right_led_1_off();
ergodox_right_led_2_off();
ergodox_right_led_3_off();
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case SYMB:
ergodox_right_led_1_on();
if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_red(); rgblight_mode_noeeprom(1); }
@@ -268,4 +268,3 @@ layer_state_t layer_state_set_user(layer_state_t state) {
}
return state;
}
-
diff --git a/keyboards/ergodox_ez/keymaps/rishka/keymap.c b/keyboards/ergodox_ez/keymaps/rishka/keymap.c
index 102803e512..0d6ac9fe95 100644
--- a/keyboards/ergodox_ez/keymaps/rishka/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/rishka/keymap.c
@@ -138,7 +138,7 @@ void keyboard_post_init_user(void) {
};
// Runs whenever there is a layer state change.
-uint32_t layer_state_set_user(layer_state_t state) {
+layer_state_t layer_state_set_user(layer_state_t state) {
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
diff --git a/keyboards/ergodox_ez/keymaps/skug/keymap.c b/keyboards/ergodox_ez/keymaps/skug/keymap.c
index 1446ea7466..04aa6a99fd 100644
--- a/keyboards/ergodox_ez/keymaps/skug/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/skug/keymap.c
@@ -228,7 +228,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/keymaps/smurmann/keymap.c b/keyboards/ergodox_ez/keymaps/smurmann/keymap.c
index 42ac13775f..c8ddc23a8b 100644
--- a/keyboards/ergodox_ez/keymaps/smurmann/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/smurmann/keymap.c
@@ -139,7 +139,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if(layer == 1)
{
@@ -157,7 +157,7 @@ void matrix_scan_user(void) {
}
if(keyboard_report->mods & MOD_BIT(KC_LSFT))
- {
+ {
ergodox_right_led_1_set (LED_BRIGHTNESS_HI);
ergodox_right_led_1_on ();
} else {
@@ -182,7 +182,7 @@ void matrix_scan_user(void) {
}
if(keyboard_report->mods & MOD_BIT(KC_LCTRL))
- {
+ {
ergodox_right_led_3_set (LED_BRIGHTNESS_HI);
ergodox_right_led_3_on ();
} else {
@@ -195,7 +195,7 @@ void matrix_scan_user(void) {
};
void led_set_user(uint8_t usb_led){
- if (usb_led & (1 << USB_LED_CAPS_LOCK))
+ if (usb_led & (1 << USB_LED_CAPS_LOCK))
{
capsOn = true;
}else {
diff --git a/keyboards/ergodox_ez/keymaps/steno/keymap.c b/keyboards/ergodox_ez/keymaps/steno/keymap.c
index 080d3f6cef..96218bbe99 100644
--- a/keyboards/ergodox_ez/keymaps/steno/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/steno/keymap.c
@@ -228,7 +228,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/keymaps/testing/keymap.c b/keyboards/ergodox_ez/keymaps/testing/keymap.c
index 5c1fc4af28..3aee63ddf1 100644
--- a/keyboards/ergodox_ez/keymaps/testing/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/testing/keymap.c
@@ -62,7 +62,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
layer_state_t layer_state_set_user(layer_state_t state) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/keymaps/vim/keymap.c b/keyboards/ergodox_ez/keymaps/vim/keymap.c
index 948f2b4794..c1c037ef23 100644
--- a/keyboards/ergodox_ez/keymaps/vim/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/vim/keymap.c
@@ -330,7 +330,7 @@ void matrix_init_user(void) {
};
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ergodox_ez/util/compile_keymap.py b/keyboards/ergodox_ez/util/compile_keymap.py
index b447ecaf5c..310512c920 100755
--- a/keyboards/ergodox_ez/util/compile_keymap.py
+++ b/keyboards/ergodox_ez/util/compile_keymap.py
@@ -27,29 +27,34 @@ PY2 = sys.version_info.major == 2
if PY2:
chr = unichr
-
KEYBOARD_LAYOUTS = {
# These map positions in the parsed layout to
# positions in the KEYMAP MATRIX
'ergodox_ez': [
- [ 0, 1, 2, 3, 4, 5, 6], [38, 39, 40, 41, 42, 43, 44],
- [ 7, 8, 9, 10, 11, 12, 13], [45, 46, 47, 48, 49, 50, 51],
- [14, 15, 16, 17, 18, 19 ], [ 52, 53, 54, 55, 56, 57],
- [20, 21, 22, 23, 24, 25, 26], [58, 59, 60, 61, 62, 63, 64],
- [27, 28, 29, 30, 31 ], [ 65, 66, 67, 68, 69],
- [ 32, 33], [70, 71 ],
- [ 34], [72 ],
- [ 35, 36, 37], [73, 74, 75 ],
+ [0, 1, 2, 3, 4, 5, 6],
+ [38, 39, 40, 41, 42, 43, 44],
+ [7, 8, 9, 10, 11, 12, 13],
+ [45, 46, 47, 48, 49, 50, 51],
+ [14, 15, 16, 17, 18, 19],
+ [52, 53, 54, 55, 56, 57],
+ [20, 21, 22, 23, 24, 25, 26],
+ [58, 59, 60, 61, 62, 63, 64],
+ [27, 28, 29, 30, 31],
+ [65, 66, 67, 68, 69],
+ [32, 33],
+ [70, 71],
+ [34],
+ [72],
+ [35, 36, 37],
+ [73, 74, 75],
]
}
-ROW_INDENTS = {
- 'ergodox_ez': [0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 5, 0, 6, 0, 4, 0]
-}
+ROW_INDENTS = {'ergodox_ez': [0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 5, 0, 6, 0, 4, 0]}
BLANK_LAYOUTS = [
-# Compact Layout
-"""
+ # Compact Layout
+ """
.------------------------------------.------------------------------------.
| | | | | | | | | | | | | | |
!-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
@@ -70,8 +75,8 @@ BLANK_LAYOUTS = [
'-----------------' '-----------------'
""",
-# Wide Layout
-"""
+ # Wide Layout
+ """
.---------------------------------------------. .---------------------------------------------.
| | | | | | | | ! | | | | | | |
!-------+-----+-----+-----+-----+-------------! !-------+-----+-----+-----+-----+-----+-------!
@@ -93,26 +98,22 @@ BLANK_LAYOUTS = [
""",
]
-
DEFAULT_CONFIG = {
- "keymaps_includes": [
- "keymap_common.h",
- ],
+ "keymaps_includes": ["keymap_common.h",],
'filler': "-+.'!:x",
'separator': "|",
'default_key_prefix': ["KC_"],
}
-
SECTIONS = [
'layout_config',
'layers',
]
-
# Markdown Parsing
-ONELINE_COMMENT_RE = re.compile(r"""
+ONELINE_COMMENT_RE = re.compile(
+ r"""
^ # comment must be at the start of the line
\s* # arbitrary whitespace
// # start of the comment
@@ -121,22 +122,26 @@ ONELINE_COMMENT_RE = re.compile(r"""
""", re.MULTILINE | re.VERBOSE
)
-INLINE_COMMENT_RE = re.compile(r"""
+INLINE_COMMENT_RE = re.compile(
+ r"""
([\,\"\[\]\{\}\d]) # anythig that might end a expression
\s+ # comment must be preceded by whitespace
// # start of the comment
\s # and succeded by whitespace
(?:[^\"\]\}\{\[]*) # the comment (except things which might be json)
$ # until the end of line
-""", re.MULTILINE | re.VERBOSE)
+""", re.MULTILINE | re.VERBOSE
+)
-TRAILING_COMMA_RE = re.compile(r"""
+TRAILING_COMMA_RE = re.compile(
+ r"""
, # the comma
(?:\s*) # arbitrary whitespace
$ # only works if the trailing comma is followed by newline
(\s*) # arbitrary whitespace
([\]\}]) # end of an array or object
-""", re.MULTILINE | re.VERBOSE)
+""", re.MULTILINE | re.VERBOSE
+)
def loads(raw_data):
@@ -178,9 +183,7 @@ def parse_config(path):
def end_section():
if section['start_line'] >= 0:
if section['name'] == 'layout_config':
- config.update(loads("\n".join(
- section['code_lines']
- )))
+ config.update(loads("\n".join(section['code_lines'])))
elif section['sub_name'].startswith('layer'):
layer_name = section['sub_name']
config['layer_lines'][layer_name] = section['code_lines']
@@ -215,6 +218,7 @@ def parse_config(path):
assert 'layout' in config
return config
+
# header file parsing
IF0_RE = re.compile(r"""
@@ -224,7 +228,6 @@ IF0_RE = re.compile(r"""
#endif
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
-
COMMENT_RE = re.compile(r"""
/\*
.*?
@@ -244,6 +247,7 @@ def regex_partial(re_str_fmt, flags):
def partial(*args, **kwargs):
re_str = re_str_fmt.format(*args, **kwargs)
return re.compile(re_str, flags)
+
return partial
@@ -256,7 +260,6 @@ KEYDEF_REP = regex_partial(r"""
) # capture group end
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
-
ENUM_RE = re.compile(r"""
(
enum
@@ -268,7 +271,6 @@ ENUM_RE = re.compile(r"""
) # capture group end
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
-
ENUM_KEY_REP = regex_partial(r"""
(
{} # the prefixes
@@ -309,14 +311,13 @@ def parse_valid_keys(config, out_path):
include_path = os.path.join(dirpath, include)
if os.path.exists(include_path):
header_data = read_header_file(include_path)
- valid_keycodes.update(
- parse_keydefs(config, header_data)
- )
+ valid_keycodes.update(parse_keydefs(config, header_data))
return valid_keycodes
# Keymap Parsing
+
def iter_raw_codes(layer_lines, filler, separator):
filler_re = re.compile("[" + filler + " ]")
for line in layer_lines:
@@ -346,28 +347,21 @@ LAYER_CHANGE_RE = re.compile(r"""
(DF|TG|MO)\(\d+\)
""", re.VERBOSE)
-
MACRO_RE = re.compile(r"""
M\(\w+\)
""", re.VERBOSE)
-
UNICODE_RE = re.compile(r"""
U[0-9A-F]{4}
""", re.VERBOSE)
-
NON_CODE = re.compile(r"""
^[^A-Z0-9_]$
""", re.VERBOSE)
def parse_uni_code(raw_code):
- macro_id = "UC_" + (
- unicodedata.name(raw_code)
- .replace(" ", "_")
- .replace("-", "_")
- )
+ macro_id = "UC_" + (unicodedata.name(raw_code).replace(" ", "_").replace("-", "_"))
code = "M({})".format(macro_id)
uc_hex = "{:04X}".format(ord(raw_code))
return code, macro_id, uc_hex
@@ -407,19 +401,13 @@ def parse_code(raw_code, key_prefixes, valid_keycodes):
def parse_keymap(config, key_indexes, layer_lines, valid_keycodes):
keymap = {}
- raw_codes = list(iter_raw_codes(
- layer_lines, config['filler'], config['separator']
- ))
+ raw_codes = list(iter_raw_codes(layer_lines, config['filler'], config['separator']))
indexed_codes = iter_indexed_codes(raw_codes, key_indexes)
key_prefixes = config['key_prefixes']
for raw_code, key_index, row_index in indexed_codes:
- code, macro_id, uc_hex = parse_code(
- raw_code, key_prefixes, valid_keycodes
- )
+ code, macro_id, uc_hex = parse_code(raw_code, key_prefixes, valid_keycodes)
# TODO: line numbers for invalid codes
- err_msg = "Could not parse key '{}' on row {}".format(
- raw_code, row_index
- )
+ err_msg = "Could not parse key '{}' on row {}".format(raw_code, row_index)
assert code is not None, err_msg
# print(repr(raw_code), repr(code), macro_id, uc_hex)
if macro_id:
@@ -432,17 +420,14 @@ def parse_keymap(config, key_indexes, layer_lines, valid_keycodes):
def parse_keymaps(config, valid_keycodes):
keymaps = collections.OrderedDict()
- key_indexes = config.get(
- 'key_indexes', KEYBOARD_LAYOUTS[config['layout']]
- )
+ key_indexes = config.get('key_indexes', KEYBOARD_LAYOUTS[config['layout']])
# TODO: maybe validate key_indexes
for layer_name, layer_lines, in config['layer_lines'].items():
- keymaps[layer_name] = parse_keymap(
- config, key_indexes, layer_lines, valid_keycodes
- )
+ keymaps[layer_name] = parse_keymap(config, key_indexes, layer_lines, valid_keycodes)
return keymaps
+
# keymap.c output
USERCODE = """
@@ -453,7 +438,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
@@ -572,7 +557,6 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {{
}};
"""
-
UNICODE_MACRO_TEMPLATE = """
case {macro_id}:
unicode_action_function(0x{hi:02x}, 0x{lo:02x});
@@ -584,9 +568,7 @@ def unicode_macro_cases(config):
for macro_id, uc_hex in config['unicode_macros'].items():
hi = int(uc_hex, 16) >> 8
lo = int(uc_hex, 16) & 0xFF
- yield UNICODE_MACRO_TEMPLATE.format(
- macro_id=macro_id, hi=hi, lo=lo
- )
+ yield UNICODE_MACRO_TEMPLATE.format(macro_id=macro_id, hi=hi, lo=lo)
def iter_keymap_lines(keymap, row_indents=None):
diff --git a/keyboards/ergoslab/keymaps/default/keymap.c b/keyboards/ergoslab/keymaps/default/keymap.c
index 59415618a8..093d586eba 100644
--- a/keyboards/ergoslab/keymaps/default/keymap.c
+++ b/keyboards/ergoslab/keymaps/default/keymap.c
@@ -51,7 +51,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
#ifdef RGBLIGHT_ENABLE
layer_state_t layer_state_set_user(layer_state_t state) {
- uint8_t layer = biton32(state);
+ uint8_t layer = get_highest_layer(state);
switch (layer) {
case BASE:
rgblight_sethsv(HSV_ERGOSLAB_ORANGE);
diff --git a/keyboards/exclusive/e65/keymaps/masterzen/keymap.c b/keyboards/exclusive/e65/keymaps/masterzen/keymap.c
index 156832de4e..898a294f7e 100644
--- a/keyboards/exclusive/e65/keymaps/masterzen/keymap.c
+++ b/keyboards/exclusive/e65/keymaps/masterzen/keymap.c
@@ -102,7 +102,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
edit = false;
}
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _ADJUST:
temp_config.mode = rgblight_get_mode();
rgblight_mode_noeeprom(1);
diff --git a/keyboards/exclusive/e7v1/keymaps/masterzen/keymap.c b/keyboards/exclusive/e7v1/keymaps/masterzen/keymap.c
index 6987e84021..2793cffe93 100644
--- a/keyboards/exclusive/e7v1/keymaps/masterzen/keymap.c
+++ b/keyboards/exclusive/e7v1/keymaps/masterzen/keymap.c
@@ -121,7 +121,7 @@ layer_state_t layer_state_set_user(layer_state_t state)
edit = false;
}
- switch (biton32(state))
+ switch (get_highest_layer(state))
{
case _ADJUST:
mode = rgblight_get_mode();
diff --git a/keyboards/flehrad/bigswitch/keymaps/333fred/config.h b/keyboards/flehrad/bigswitch/keymaps/333fred/config.h
index 3273cc8db4..6e9219115c 100644
--- a/keyboards/flehrad/bigswitch/keymaps/333fred/config.h
+++ b/keyboards/flehrad/bigswitch/keymaps/333fred/config.h
@@ -24,3 +24,4 @@
// Long tapping term on the big switch, because it takes so long to press
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
diff --git a/keyboards/fractal/keymaps/default/keymap.c b/keyboards/fractal/keymaps/default/keymap.c
index 6b0a8cc18c..ded4890d8c 100644
--- a/keyboards/fractal/keymaps/default/keymap.c
+++ b/keyboards/fractal/keymaps/default/keymap.c
@@ -158,7 +158,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[_ADJUST] = LAYOUT_ortho_5x12(
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
- _______, QK_BOOT, DEBUG, _______, _______, _______, _______, TERM_ON, TERM_OFF,_______, _______, KC_DEL,
+ _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______,_______, _______, KC_DEL,
_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______,
_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/keyboards/gboards/gergo/keymaps/colemak/keymap.c b/keyboards/gboards/gergo/keymaps/colemak/keymap.c
index b2e79114f2..35b1e0b653 100644
--- a/keyboards/gboards/gergo/keymaps/colemak/keymap.c
+++ b/keyboards/gboards/gergo/keymaps/colemak/keymap.c
@@ -146,8 +146,8 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- //uint8_t layer = biton32(layer_state);
- biton32(layer_state);
+ //uint8_t layer = get_highest_layer(layer_state);
+ get_highest_layer(layer_state);
};
@@ -171,4 +171,3 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
return true;
};
-
diff --git a/keyboards/gboards/gergoplex/keymaps/georgepetri/config.h b/keyboards/gboards/gergoplex/keymaps/georgepetri/config.h
index f66c334b85..e2c27583fa 100644
--- a/keyboards/gboards/gergoplex/keymaps/georgepetri/config.h
+++ b/keyboards/gboards/gergoplex/keymaps/georgepetri/config.h
@@ -27,3 +27,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define COMBO_ALLOW_ACTION_KEYS
#define COMBO_VARIABLE_LEN
+
+#define TAPPING_TERM_PER_KEY
diff --git a/keyboards/gboards/gergoplex/keymaps/georgepetri/keymap.c b/keyboards/gboards/gergoplex/keymaps/georgepetri/keymap.c
index e3b8944814..8b832cbac8 100644
--- a/keyboards/gboards/gergoplex/keymaps/georgepetri/keymap.c
+++ b/keyboards/gboards/gergoplex/keymaps/georgepetri/keymap.c
@@ -199,5 +199,14 @@ void ql_reset(qk_tap_dance_state_t *state, void *user_data) {
}
qk_tap_dance_action_t tap_dance_actions[] = {
- [GAME] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, ql_finished, ql_reset, 275)
+ [GAME] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ql_finished, ql_reset)
};
+
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
+ return 275;
+ default:
+ return TAPPING_TERM;
+ }
+}
diff --git a/keyboards/gh60/revc/keymaps/dbroqua/keymap.c b/keyboards/gh60/revc/keymaps/dbroqua/keymap.c
index 964f40f1c0..ffb87ef009 100644
--- a/keyboards/gh60/revc/keymaps/dbroqua/keymap.c
+++ b/keyboards/gh60/revc/keymaps/dbroqua/keymap.c
@@ -101,7 +101,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
void matrix_scan_user(void) {
- uint32_t layer = layer_state;
+ layer_state_t layer = layer_state;
if (layer & (1<<1)) {
gh60_fn_led_on();
@@ -120,4 +120,4 @@ void matrix_scan_user(void) {
} else {
gh60_esc_led_off();
}
-}; \ No newline at end of file
+};
diff --git a/keyboards/gh60/revc/keymaps/default/keymap.c b/keyboards/gh60/revc/keymaps/default/keymap.c
index a8fd4f3c22..4ebc71ff4b 100644
--- a/keyboards/gh60/revc/keymaps/default/keymap.c
+++ b/keyboards/gh60/revc/keymaps/default/keymap.c
@@ -31,7 +31,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
void matrix_scan_user(void) {
//Layer LED indicators
- uint32_t layer = layer_state;
+ layer_state_t layer = layer_state;
if (layer & (1<<1)) {
gh60_wasd_leds_on();
diff --git a/keyboards/gh60/revc/keymaps/robotmaxtron/keymap.c b/keyboards/gh60/revc/keymaps/robotmaxtron/keymap.c
index b84e7564fc..77bf54de63 100644
--- a/keyboards/gh60/revc/keymaps/robotmaxtron/keymap.c
+++ b/keyboards/gh60/revc/keymaps/robotmaxtron/keymap.c
@@ -97,7 +97,7 @@ void matrix_scan_user(void) {
// Layer LED indicators
// ESC led on when in function layer, WASD cluster leds enabled when on arrow cluster
- uint32_t layer = layer_state;
+ layer_state_t layer = layer_state;
if (layer & (1<<1)) {
gh60_wasd_leds_on();
} else {
diff --git a/keyboards/gh60/satan/keymaps/addcninblue/keymap.c b/keyboards/gh60/satan/keymaps/addcninblue/keymap.c
index 5012fee56b..2b1a417fb5 100644
--- a/keyboards/gh60/satan/keymaps/addcninblue/keymap.c
+++ b/keyboards/gh60/satan/keymaps/addcninblue/keymap.c
@@ -177,7 +177,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if (old_layer != layer) {
switch (layer) {
diff --git a/keyboards/glenpickle/chimera_ergo/keymaps/default/keymap.c b/keyboards/glenpickle/chimera_ergo/keymaps/default/keymap.c
index 51ab0e92cd..dd7e32f7dc 100644
--- a/keyboards/glenpickle/chimera_ergo/keymaps/default/keymap.c
+++ b/keyboards/glenpickle/chimera_ergo/keymaps/default/keymap.c
@@ -131,7 +131,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
};
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _QWERTY:
diff --git a/keyboards/glenpickle/chimera_ls/keymaps/default/keymap.c b/keyboards/glenpickle/chimera_ls/keymaps/default/keymap.c
index 0affeef389..1ae70e6245 100644
--- a/keyboards/glenpickle/chimera_ls/keymaps/default/keymap.c
+++ b/keyboards/glenpickle/chimera_ls/keymaps/default/keymap.c
@@ -158,7 +158,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _QWERTY:
diff --git a/keyboards/glenpickle/chimera_ortho/keymaps/default/keymap.c b/keyboards/glenpickle/chimera_ortho/keymaps/default/keymap.c
index 6a676493dd..bc783f540c 100644
--- a/keyboards/glenpickle/chimera_ortho/keymaps/default/keymap.c
+++ b/keyboards/glenpickle/chimera_ortho/keymaps/default/keymap.c
@@ -151,7 +151,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _QWERTY:
diff --git a/keyboards/gon/nerdtkl/keymaps/gam3cat/keymap.c b/keyboards/gon/nerdtkl/keymaps/gam3cat/keymap.c
index c4294c812e..bda83bb5da 100644
--- a/keyboards/gon/nerdtkl/keymaps/gam3cat/keymap.c
+++ b/keyboards/gon/nerdtkl/keymaps/gam3cat/keymap.c
@@ -241,7 +241,7 @@ void matrix_scan_user(void) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _BL:
custom_backlight_level(0);
break;
diff --git a/keyboards/handwired/ergocheap/config.h b/keyboards/handwired/ergocheap/config.h
index 26905e8cb3..00b9616e3e 100644
--- a/keyboards/handwired/ergocheap/config.h
+++ b/keyboards/handwired/ergocheap/config.h
@@ -47,6 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
/*
* Feature disable options
diff --git a/keyboards/handwired/frenchdev/keymaps/default/keymap.c b/keyboards/handwired/frenchdev/keymaps/default/keymap.c
index 2d917b412e..11463a0162 100644
--- a/keyboards/handwired/frenchdev/keymaps/default/keymap.c
+++ b/keyboards/handwired/frenchdev/keymaps/default/keymap.c
@@ -209,7 +209,7 @@ void press_underscore(void) {
uint8_t old_layer=_BASE;
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
frenchdev_led_1_off();
frenchdev_led_2_off();
diff --git a/keyboards/handwired/kbod/keymaps/default/keymap.c b/keyboards/handwired/kbod/keymaps/default/keymap.c
index 333f8a769f..0ffc3e9d97 100644
--- a/keyboards/handwired/kbod/keymaps/default/keymap.c
+++ b/keyboards/handwired/kbod/keymaps/default/keymap.c
@@ -89,7 +89,7 @@ void matrix_init_user(void) {
}
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if (layer) {
PORTC |= _BV(PC7);
} else {
diff --git a/keyboards/handwired/onekey/config.h b/keyboards/handwired/onekey/config.h
index f491d4d393..88c15806ce 100644
--- a/keyboards/handwired/onekey/config.h
+++ b/keyboards/handwired/onekey/config.h
@@ -42,6 +42,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define LOCKING_RESYNC_ENABLE
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
/*
* Feature disable options
diff --git a/keyboards/handwired/onekey/onekey.c b/keyboards/handwired/onekey/onekey.c
index cbd67012ce..a29f9ea6d0 100644
--- a/keyboards/handwired/onekey/onekey.c
+++ b/keyboards/handwired/onekey/onekey.c
@@ -1 +1,12 @@
+// Copyright 2022 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include "onekey.h"
+
+void keyboard_post_init_kb(void) {
+ debug_enable = true;
+ debug_matrix = true;
+ debug_keyboard = true;
+ debug_mouse = true;
+ keyboard_post_init_user();
+}
diff --git a/keyboards/handwired/onekey/rp2040/config.h b/keyboards/handwired/onekey/rp2040/config.h
new file mode 100644
index 0000000000..f5a122e91b
--- /dev/null
+++ b/keyboards/handwired/onekey/rp2040/config.h
@@ -0,0 +1,17 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "config_common.h"
+
+#define PRODUCT Onekey Raspberry Pi RP2040
+#define MATRIX_COL_PINS { GP4 }
+#define MATRIX_ROW_PINS { GP5 }
+#define DEBUG_MATRIX_SCAN_RATE
+
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED GP25
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 500U
+
+#define RGB_DI_PIN A1
diff --git a/keyboards/handwired/onekey/rp2040/readme.md b/keyboards/handwired/onekey/rp2040/readme.md
new file mode 100644
index 0000000000..9014479f8d
--- /dev/null
+++ b/keyboards/handwired/onekey/rp2040/readme.md
@@ -0,0 +1,12 @@
+# Raspberry Pi 2040 onekey
+
+To trigger keypress, short together pins *GP4* and *GP5*.
+
+Double-tap reset to enter bootloader mode. Copy the built uf2 file to the device by dragging the file to the new USB disk.
+
+## Supported Hardware
+
+* Raspberry Pi Pico
+* SparkFun Pro Micro - RP2040
+* Adafruit KB2040 - RP2040 Kee Boar
+* ...and many more RP2040 based development boards
diff --git a/keyboards/handwired/onekey/rp2040/rules.mk b/keyboards/handwired/onekey/rp2040/rules.mk
new file mode 100644
index 0000000000..646402d0bb
--- /dev/null
+++ b/keyboards/handwired/onekey/rp2040/rules.mk
@@ -0,0 +1,3 @@
+# MCU name
+MCU = RP2040
+BOOTLOADER = rp2040
diff --git a/keyboards/handwired/ortho5x14/keymaps/2u/keymap.c b/keyboards/handwired/ortho5x14/keymaps/2u/keymap.c
index 70a96fac9d..d785825332 100644
--- a/keyboards/handwired/ortho5x14/keymaps/2u/keymap.c
+++ b/keyboards/handwired/ortho5x14/keymaps/2u/keymap.c
@@ -343,9 +343,9 @@ qk_tap_dance_action_t tap_dance_actions[] = {
[TD_PGUP_HOME] = ACTION_TAP_DANCE_DOUBLE(KC_PGUP, KC_HOME),
[TD_PGDN_END] = ACTION_TAP_DANCE_DOUBLE(KC_PGDN, KC_END),
- [TD_Q_LrALT] = ACTION_TAP_DANCE_DUAL_ROLE(KC_Q, _ALT),
- [TD_R_LrKey] = ACTION_TAP_DANCE_DUAL_ROLE(KC_R, _RAISE),
- [TD_T_LrMS] = ACTION_TAP_DANCE_DUAL_ROLE(KC_T, _MOUSE),
+ [TD_Q_LrALT] = ACTION_TAP_DANCE_LAYER_MOVE(KC_Q, _ALT),
+ [TD_R_LrKey] = ACTION_TAP_DANCE_LAYER_MOVE(KC_R, _RAISE),
+ [TD_T_LrMS] = ACTION_TAP_DANCE_LAYER_MOVE(KC_T, _MOUSE),
[TD_SHIFT_CAPS] = ACTION_TAP_DANCE_FN_ADVANCED(NULL,lshift_finished, lshift_reset),
[TD_SPC_ENT] = ACTION_TAP_DANCE_DOUBLE(KC_SPACE, KC_ENT),
diff --git a/keyboards/handwired/ortho5x14/keymaps/split1/keymap.c b/keyboards/handwired/ortho5x14/keymaps/split1/keymap.c
index b152503aaf..3734510f8c 100644
--- a/keyboards/handwired/ortho5x14/keymaps/split1/keymap.c
+++ b/keyboards/handwired/ortho5x14/keymaps/split1/keymap.c
@@ -279,9 +279,9 @@ qk_tap_dance_action_t tap_dance_actions[] = {
[TD_PGUP_HOME] = ACTION_TAP_DANCE_DOUBLE(KC_PGUP, KC_HOME),
[TD_PGDN_END] = ACTION_TAP_DANCE_DOUBLE(KC_PGUP, KC_END),
- [TD_Q_LrALT] = ACTION_TAP_DANCE_DUAL_ROLE(KC_Q, _ALT),
- [TD_R_LrKey] = ACTION_TAP_DANCE_DUAL_ROLE(KC_R, _RAISE),
- [TD_T_LrMS] = ACTION_TAP_DANCE_DUAL_ROLE(KC_T, _MOUSE),
+ [TD_Q_LrALT] = ACTION_TAP_DANCE_LAYER_MOVE(KC_Q, _ALT),
+ [TD_R_LrKey] = ACTION_TAP_DANCE_LAYER_MOVE(KC_R, _RAISE),
+ [TD_T_LrMS] = ACTION_TAP_DANCE_LAYER_MOVE(KC_T, _MOUSE),
[TD_SHIFT_CAPS] = ACTION_TAP_DANCE_FN_ADVANCED(NULL,lshift_finished, lshift_reset),
[TD_SPC_ENT] = ACTION_TAP_DANCE_DOUBLE(KC_SPACE, KC_ENT),
diff --git a/keyboards/handwired/ortho_brass/keymaps/default/keymap.c b/keyboards/handwired/ortho_brass/keymaps/default/keymap.c
index 948a7bd1bc..f32529b6a7 100644
--- a/keyboards/handwired/ortho_brass/keymaps/default/keymap.c
+++ b/keyboards/handwired/ortho_brass/keymaps/default/keymap.c
@@ -162,7 +162,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_ADJUST] = LAYOUT_ortho_4x12_1x2uC(
_______, QK_BOOT, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL ,
_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______,
- _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______,
+ _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
diff --git a/keyboards/handwired/prime_exl/keymaps/via/keymap.c b/keyboards/handwired/prime_exl/keymaps/via/keymap.c
index 0e6802996d..b5b616d55b 100644
--- a/keyboards/handwired/prime_exl/keymaps/via/keymap.c
+++ b/keyboards/handwired/prime_exl/keymaps/via/keymap.c
@@ -87,7 +87,7 @@ void led_set_user(uint8_t usb_led) {
//function for layer indicator LED
layer_state_t layer_state_set_user(layer_state_t state)
{
- if (biton32(state) == 1) {
+ if (get_highest_layer(state) == 1) {
writePinHigh(C6);
} else {
writePinLow(C6);
diff --git a/keyboards/handwired/promethium/keymaps/default/keymap.c b/keyboards/handwired/promethium/keymaps/default/keymap.c
index 1903b2f9ba..77f83361e6 100644
--- a/keyboards/handwired/promethium/keymaps/default/keymap.c
+++ b/keyboards/handwired/promethium/keymaps/default/keymap.c
@@ -529,7 +529,7 @@ void led_reset(void) {
}
void led_set_default_layer_indicator(void) {
- uint8_t default_layer = biton32(default_layer_state);
+ uint8_t default_layer = get_highest_layer(default_layer_state);
if (default_layer == _QWERTY) {
rgbsps_set(LED_IND_QWERTY, THEME_COLOR_QWERTY);
rgbsps_set(LED_IND_ALT, COLOR_BLANK);
@@ -553,7 +553,7 @@ void led_set_layer_indicator(void) {
rgbsps_set(LED_IND_GREEK, COLOR_BLANK);
rgbsps_set(LED_IND_EMOJI, COLOR_BLANK);
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if (oldlayer == layer) {
return;
}
@@ -1014,7 +1014,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
lshift = keyboard_report->mods & MOD_BIT(KC_LSFT);
rshift = keyboard_report->mods & MOD_BIT(KC_RSFT);
- layer = biton32(layer_state);
+ layer = get_highest_layer(layer_state);
#ifdef DOUBLESPACE_LAYER_ENABLE
// double-space: send space immediately if any other key depressed before space is released
diff --git a/keyboards/handwired/promethium/keymaps/priyadi/keymap.c b/keyboards/handwired/promethium/keymaps/priyadi/keymap.c
index 94b505aa2c..faa096ce08 100644
--- a/keyboards/handwired/promethium/keymaps/priyadi/keymap.c
+++ b/keyboards/handwired/promethium/keymaps/priyadi/keymap.c
@@ -532,7 +532,7 @@ void led_reset(void) {
}
void led_set_default_layer_indicator(void) {
- uint8_t default_layer = biton32(default_layer_state);
+ uint8_t default_layer = get_highest_layer(default_layer_state);
if (default_layer == _QWERTY) {
rgbsps_set(LED_IND_QWERTY, THEME_COLOR_QWERTY);
rgbsps_set(LED_IND_ALT, COLOR_BLANK);
@@ -556,7 +556,7 @@ void led_set_layer_indicator(void) {
rgbsps_set(LED_IND_GREEK, COLOR_BLANK);
rgbsps_set(LED_IND_EMOJI, COLOR_BLANK);
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if (oldlayer == layer) {
return;
}
@@ -989,7 +989,7 @@ void process_doublespace(bool pressed, bool *isactive, bool *otheractive, bool *
}
#endif
-uint32_t layer_state_set_kb(uint32_t state)
+layer_state_t layer_state_set_kb(layer_state_t state)
{
// turn on punc layer if both fun & num are on
if ((state & ((1UL<<_NUM) | (1UL<<_FUN))) == ((1UL<<_NUM) | (1UL<<_FUN))) {
@@ -1017,7 +1017,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
lshift = keyboard_report->mods & MOD_BIT(KC_LSFT);
rshift = keyboard_report->mods & MOD_BIT(KC_RSFT);
- layer = biton32(layer_state);
+ layer = get_highest_layer(layer_state);
#ifdef DOUBLESPACE_LAYER_ENABLE
// double-space: send space immediately if any other key depressed before space is released
diff --git a/keyboards/handwired/riblee_f401/keymaps/default/keymap.c b/keyboards/handwired/riblee_f401/keymaps/default/keymap.c
index 6892c0fb49..bee4de5ede 100644
--- a/keyboards/handwired/riblee_f401/keymaps/default/keymap.c
+++ b/keyboards/handwired/riblee_f401/keymaps/default/keymap.c
@@ -158,7 +158,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[_ADJUST] = LAYOUT_ortho_5x12(
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
- _______, QK_BOOT, DEBUG, _______, _______, _______, _______, TERM_ON, TERM_OFF,_______, _______, KC_DEL,
+ _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______,_______, _______, KC_DEL,
_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______,
_______, _______, _______, _______, _______, _______, NK_TOGG, LCG_SWP, LCG_NRM, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/keyboards/handwired/riblee_f411/keymaps/default/keymap.c b/keyboards/handwired/riblee_f411/keymaps/default/keymap.c
index 2e9485d6b9..ff7e1117b8 100644
--- a/keyboards/handwired/riblee_f411/keymaps/default/keymap.c
+++ b/keyboards/handwired/riblee_f411/keymaps/default/keymap.c
@@ -158,7 +158,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[_ADJUST] = LAYOUT_ortho_5x12(
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
- _______, QK_BOOT, DEBUG, _______, _______, _______, _______, TERM_ON, TERM_OFF,_______, _______, KC_DEL,
+ _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______,_______, _______, KC_DEL,
_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______,
_______, _______, _______, _______, _______, _______, NK_TOGG, LCG_SWP, LCG_NRM, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/keyboards/handwired/rs60/keymaps/default/keymap.c b/keyboards/handwired/rs60/keymaps/default/keymap.c
index 6b311a7ebb..6d5dc4a32a 100644
--- a/keyboards/handwired/rs60/keymaps/default/keymap.c
+++ b/keyboards/handwired/rs60/keymaps/default/keymap.c
@@ -155,7 +155,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[_ADJUST] = LAYOUT_ortho_5x12(
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
- _______, QK_BOOT, DEBUG, _______, _______, _______, _______, TERM_ON, TERM_OFF,_______, _______, KC_DEL,
+ _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______,_______, _______, KC_DEL,
_______, _______, _______, _______, _______, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/keyboards/handwired/terminus_mini/keymaps/default/keymap.c b/keyboards/handwired/terminus_mini/keymaps/default/keymap.c
index 8062aa711f..8d0631072f 100644
--- a/keyboards/handwired/terminus_mini/keymaps/default/keymap.c
+++ b/keyboards/handwired/terminus_mini/keymaps/default/keymap.c
@@ -193,7 +193,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[_ADJUST] = LAYOUT(
- _______, _______, _______, _______, _______, QK_BOOT, _______, TERM_ON, TERM_OFF, _______, _______, KC_DEL,
+ _______, _______, _______, _______, _______, QK_BOOT, _______, _______, _______, _______, _______, KC_DEL,
_______, _______, _______, _______, _______, _______, _______, QWERTY, COLEMAK, DVORAK, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/keyboards/handwired/traveller/keymaps/default/keymap.c b/keyboards/handwired/traveller/keymaps/default/keymap.c
index 288acbe108..2cd57db35f 100644
--- a/keyboards/handwired/traveller/keymaps/default/keymap.c
+++ b/keyboards/handwired/traveller/keymaps/default/keymap.c
@@ -219,7 +219,7 @@ void LayerLEDSet(uint8_t layr) {
uint8_t old_layer = _QW;
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if (old_layer != layer) {
LayerLEDSet(layer);
diff --git a/keyboards/handwired/tritium_numpad/keymaps/blu/keymap.c b/keyboards/handwired/tritium_numpad/keymaps/blu/keymap.c
index b618675295..50bbf232b5 100644
--- a/keyboards/handwired/tritium_numpad/keymaps/blu/keymap.c
+++ b/keyboards/handwired/tritium_numpad/keymaps/blu/keymap.c
@@ -9,7 +9,7 @@ void keyboard_pre_init_user(void)
layer_state_t layer_state_set_user(layer_state_t state)
{
// Switch layer LED accordingly
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case 0:
writePinHigh(B0);
break;
diff --git a/keyboards/handwired/uthol/rev3/config.h b/keyboards/handwired/uthol/rev3/config.h
index 90880998b7..84ca3f0cc6 100644
--- a/keyboards/handwired/uthol/rev3/config.h
+++ b/keyboards/handwired/uthol/rev3/config.h
@@ -57,6 +57,7 @@
#define LOCKING_RESYNC_ENABLE
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
// RGB Stuff
#define RGB_DI_PIN B0
diff --git a/keyboards/helix/pico/keymaps/mtei/config.h b/keyboards/helix/pico/keymaps/mtei/config.h
index 1a4dc2c842..a633105ff9 100644
--- a/keyboards/helix/pico/keymaps/mtei/config.h
+++ b/keyboards/helix/pico/keymaps/mtei/config.h
@@ -13,8 +13,6 @@
#undef TAPPING_TERM
#define TAPPING_TERM 300
#define PERMISSIVE_HOLD
-/* when TAPPING_TERM >= 500 same effect PERMISSIVE_HOLD.
- see tmk_core/common/action_tapping.c */
// If you need more program area, try select and reduce rgblight modes to use.
diff --git a/keyboards/helix/pico/keymaps/mtei/keymap.c b/keyboards/helix/pico/keymaps/mtei/keymap.c
index b703ca376d..f641829292 100644
--- a/keyboards/helix/pico/keymaps/mtei/keymap.c
+++ b/keyboards/helix/pico/keymaps/mtei/keymap.c
@@ -242,7 +242,7 @@ float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
static int current_default_layer;
-uint32_t default_layer_state_set_kb(uint32_t state) {
+layer_state_t default_layer_state_set_kb(layer_state_t state) {
// 1<<_QWERTY - 1 == 1 - 1 == _QWERTY (=0)
// 1<<_COLEMAK - 1 == 2 - 1 == _COLEMAK (=1)
current_default_layer = state - 1;
diff --git a/keyboards/helix/rev2/keymaps/default/oled_display.c b/keyboards/helix/rev2/keymaps/default/oled_display.c
index ad5558869f..384356bd14 100644
--- a/keyboards/helix/rev2/keymaps/default/oled_display.c
+++ b/keyboards/helix/rev2/keymaps/default/oled_display.c
@@ -86,7 +86,7 @@ static void render_layer_status(void) {
break;
default:
oled_write_P(PSTR("Undef-"), false);
- snprintf(buf,sizeof(buf), "%ld", layer_state);
+ snprintf(buf,sizeof(buf), "%u", layer_state);
oled_write(buf, false);
}
oled_write_P(PSTR("\n"), false);
diff --git a/keyboards/helix/rev2/keymaps/edvorakjp/keymap.c b/keyboards/helix/rev2/keymaps/edvorakjp/keymap.c
index 5de00cb14c..80d0392ffb 100644
--- a/keyboards/helix/rev2/keymaps/edvorakjp/keymap.c
+++ b/keyboards/helix/rev2/keymaps/edvorakjp/keymap.c
@@ -5,9 +5,9 @@
// keymaps definitions are moved to keymap_Xrows.c.
#ifdef RGBLIGHT_ENABLE
-uint32_t layer_state_set_keymap(uint32_t state) {
+layer_state_t layer_state_set_keymap(layer_state_t state) {
rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case L_EDVORAKJP_LOWER:
rgblight_sethsv_noeeprom_red();
break;
diff --git a/keyboards/helix/rev2/keymaps/edvorakjp/oled.c b/keyboards/helix/rev2/keymaps/edvorakjp/oled.c
index 207aebc423..14e3e5533b 100644
--- a/keyboards/helix/rev2/keymaps/edvorakjp/oled.c
+++ b/keyboards/helix/rev2/keymaps/edvorakjp/oled.c
@@ -19,7 +19,7 @@ void render_layer_state(void) {
char layer_name[17];
oled_write_P(PSTR("Layer: "), false);
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case L_EDVORAKJP_BASE:
oled_write_ln_P(PSTR("Default"), false);
break;
diff --git a/keyboards/helix/rev2/keymaps/five_rows/config.h b/keyboards/helix/rev2/keymaps/five_rows/config.h
index 4aae9b5cac..43f14aaf2c 100644
--- a/keyboards/helix/rev2/keymaps/five_rows/config.h
+++ b/keyboards/helix/rev2/keymaps/five_rows/config.h
@@ -6,8 +6,6 @@
#undef TAPPING_TERM
#define TAPPING_TERM 300
#define PERMISSIVE_HOLD
-/* when TAPPING_TERM >= 500 same effect PERMISSIVE_HOLD.
- see tmk_core/common/action_tapping.c */
#undef OLED_UPDATE_INTERVAL
#ifdef DEBUG_MATRIX_SCAN_RATE
diff --git a/keyboards/helix/rev2/keymaps/five_rows/keymap.c b/keyboards/helix/rev2/keymaps/five_rows/keymap.c
index d992425de7..4d9dc16a9e 100644
--- a/keyboards/helix/rev2/keymaps/five_rows/keymap.c
+++ b/keyboards/helix/rev2/keymaps/five_rows/keymap.c
@@ -379,8 +379,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
int current_default_layer;
-uint32_t default_layer_state_set_user(uint32_t state) {
- current_default_layer = biton32(state);
+layer_state_t default_layer_state_set_user(layer_state_t state) {
+ current_default_layer = get_highest_layer(state);
return state;
}
diff --git a/keyboards/helix/rev3_5rows/keymaps/five_rows/config.h b/keyboards/helix/rev3_5rows/keymaps/five_rows/config.h
index ab679d14b9..a6fd32c613 100644
--- a/keyboards/helix/rev3_5rows/keymaps/five_rows/config.h
+++ b/keyboards/helix/rev3_5rows/keymaps/five_rows/config.h
@@ -6,8 +6,6 @@
#undef TAPPING_TERM
#define TAPPING_TERM 300
#define PERMISSIVE_HOLD
-/* when TAPPING_TERM >= 500 same effect PERMISSIVE_HOLD.
- see tmk_core/common/action_tapping.c */
#undef OLED_UPDATE_INTERVAL
#ifdef DEBUG_MATRIX_SCAN_RATE
diff --git a/keyboards/helix/rev3_5rows/keymaps/five_rows/keymap.c b/keyboards/helix/rev3_5rows/keymaps/five_rows/keymap.c
index d992425de7..4d9dc16a9e 100644
--- a/keyboards/helix/rev3_5rows/keymaps/five_rows/keymap.c
+++ b/keyboards/helix/rev3_5rows/keymaps/five_rows/keymap.c
@@ -379,8 +379,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
int current_default_layer;
-uint32_t default_layer_state_set_user(uint32_t state) {
- current_default_layer = biton32(state);
+layer_state_t default_layer_state_set_user(layer_state_t state) {
+ current_default_layer = get_highest_layer(state);
return state;
}
diff --git a/keyboards/hineybush/h87a/keymaps/gam3cat/keymap.c b/keyboards/hineybush/h87a/keymaps/gam3cat/keymap.c
index d59438f6b3..d505d5171d 100644
--- a/keyboards/hineybush/h87a/keymaps/gam3cat/keymap.c
+++ b/keyboards/hineybush/h87a/keymaps/gam3cat/keymap.c
@@ -245,7 +245,7 @@ void matrix_scan_user(void) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _BL:
custom_backlight_level(0);
rgblight_sethsv_noeeprom(180,100,255);
diff --git a/keyboards/hotdox/keymaps/default/keymap.c b/keyboards/hotdox/keymaps/default/keymap.c
index fe07e6f91d..eb4692a4c2 100644
--- a/keyboards/hotdox/keymaps/default/keymap.c
+++ b/keyboards/hotdox/keymaps/default/keymap.c
@@ -163,7 +163,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_right_led_1_off();
ergodox_right_led_2_off();
diff --git a/keyboards/hotdox/keymaps/eozaki/keymap.c b/keyboards/hotdox/keymaps/eozaki/keymap.c
index 3516f20303..d4b8f491fd 100644
--- a/keyboards/hotdox/keymaps/eozaki/keymap.c
+++ b/keyboards/hotdox/keymaps/eozaki/keymap.c
@@ -170,7 +170,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/hotdox/keymaps/kloki/keymap.c b/keyboards/hotdox/keymaps/kloki/keymap.c
index f858effd54..2550b68978 100644
--- a/keyboards/hotdox/keymaps/kloki/keymap.c
+++ b/keyboards/hotdox/keymaps/kloki/keymap.c
@@ -189,7 +189,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/idobao/id67/keymaps/thewerther/config.h b/keyboards/idobao/id67/keymaps/thewerther/config.h
index a63a92b171..85498d91b8 100644
--- a/keyboards/idobao/id67/keymaps/thewerther/config.h
+++ b/keyboards/idobao/id67/keymaps/thewerther/config.h
@@ -18,6 +18,7 @@
#define DRIVER_LED_UNDERGLOW 10
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
#if defined(RGB_MATRIX_ENABLE)
#undef RGB_MATRIX_MAXIMUM_BRIGHTNESS
diff --git a/keyboards/input_club/ergodox_infinity/keymaps/default/keymap.c b/keyboards/input_club/ergodox_infinity/keymaps/default/keymap.c
index cd65001803..6f9967b46e 100644
--- a/keyboards/input_club/ergodox_infinity/keymaps/default/keymap.c
+++ b/keyboards/input_club/ergodox_infinity/keymaps/default/keymap.c
@@ -167,7 +167,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/input_club/ergodox_infinity/keymaps/gordon/keymap.c b/keyboards/input_club/ergodox_infinity/keymaps/gordon/keymap.c
index c321d546fb..50e3238a7d 100644
--- a/keyboards/input_club/ergodox_infinity/keymaps/gordon/keymap.c
+++ b/keyboards/input_club/ergodox_infinity/keymaps/gordon/keymap.c
@@ -335,7 +335,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_on();
ergodox_led_all_on();
diff --git a/keyboards/input_club/ergodox_infinity/keymaps/halfkeyboard/keymap.c b/keyboards/input_club/ergodox_infinity/keymaps/halfkeyboard/keymap.c
index 3870dd8ffd..c8498fe9e9 100644
--- a/keyboards/input_club/ergodox_infinity/keymaps/halfkeyboard/keymap.c
+++ b/keyboards/input_club/ergodox_infinity/keymaps/halfkeyboard/keymap.c
@@ -492,7 +492,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/input_club/ergodox_infinity/keymaps/input_club/keymap.c b/keyboards/input_club/ergodox_infinity/keymaps/input_club/keymap.c
index 545429fca0..e941cee154 100644
--- a/keyboards/input_club/ergodox_infinity/keymaps/input_club/keymap.c
+++ b/keyboards/input_club/ergodox_infinity/keymaps/input_club/keymap.c
@@ -223,7 +223,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/input_club/ergodox_infinity/keymaps/narze/keymap.c b/keyboards/input_club/ergodox_infinity/keymaps/narze/keymap.c
index dd721e9a78..184eb638c9 100644
--- a/keyboards/input_club/ergodox_infinity/keymaps/narze/keymap.c
+++ b/keyboards/input_club/ergodox_infinity/keymaps/narze/keymap.c
@@ -659,7 +659,7 @@ void matrix_setup(void) {
}
void matrix_scan_user(void) {
- // uint8_t layer = biton32(layer_state);
+ // uint8_t layer = get_highest_layer(layer_state);
// ergodox_board_led_off();
// ergodox_right_led_1_off();
diff --git a/keyboards/input_club/ergodox_infinity/keymaps/nordic_ergo/keymap.c b/keyboards/input_club/ergodox_infinity/keymaps/nordic_ergo/keymap.c
index d08b96cc6e..70f49bb5c9 100644
--- a/keyboards/input_club/ergodox_infinity/keymaps/nordic_ergo/keymap.c
+++ b/keyboards/input_club/ergodox_infinity/keymaps/nordic_ergo/keymap.c
@@ -221,7 +221,7 @@ void matrix_init_user(void){
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/input_club/ergodox_infinity/keymaps/rask/keymap.c b/keyboards/input_club/ergodox_infinity/keymaps/rask/keymap.c
index e31c1c5d6b..b202823c77 100644
--- a/keyboards/input_club/ergodox_infinity/keymaps/rask/keymap.c
+++ b/keyboards/input_club/ergodox_infinity/keymaps/rask/keymap.c
@@ -179,7 +179,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/input_club/ergodox_infinity/keymaps/rjhilgefort/keymap.c b/keyboards/input_club/ergodox_infinity/keymaps/rjhilgefort/keymap.c
index 31d218ebfb..c322222baf 100644
--- a/keyboards/input_club/ergodox_infinity/keymaps/rjhilgefort/keymap.c
+++ b/keyboards/input_club/ergodox_infinity/keymaps/rjhilgefort/keymap.c
@@ -309,7 +309,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/input_club/ergodox_infinity/keymaps/trulyergonomic/keymap.c b/keyboards/input_club/ergodox_infinity/keymaps/trulyergonomic/keymap.c
index 02f409ad9e..bbc24ea27f 100644
--- a/keyboards/input_club/ergodox_infinity/keymaps/trulyergonomic/keymap.c
+++ b/keyboards/input_club/ergodox_infinity/keymaps/trulyergonomic/keymap.c
@@ -137,7 +137,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/input_club/infinity60/keymaps/jpetermans/keymap.c b/keyboards/input_club/infinity60/keymaps/jpetermans/keymap.c
index 3c2e0d4da8..a19be6664c 100644
--- a/keyboards/input_club/infinity60/keymaps/jpetermans/keymap.c
+++ b/keyboards/input_club/infinity60/keymaps/jpetermans/keymap.c
@@ -239,7 +239,7 @@ void matrix_scan_user(void) {
//Turn on layer indicator or page depending on mode
switch(led_mode_global) {
case MODE_FLASH: //flash preset page leds then single indicator
- page = biton32(layer_state) > max_pages ? 7 : biton32(layer_state);
+ page = get_highest_layer(layer_state) > max_pages ? 7 : get_highest_layer(layer_state);
msg=(page << 8) | DISPLAY_PAGE;
chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
chThdSleepMilliseconds(500);
@@ -254,7 +254,7 @@ void matrix_scan_user(void) {
break;
case MODE_PAGE: //display pre-defined led page
- page = biton32(layer_state) > max_pages ? 7 : biton32(layer_state);
+ page = get_highest_layer(layer_state) > max_pages ? 7 : get_highest_layer(layer_state);
msg=(page << 8) | DISPLAY_PAGE;
chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
break;
diff --git a/keyboards/jc65/v32u4/keymaps/gam3cat/keymap.c b/keyboards/jc65/v32u4/keymaps/gam3cat/keymap.c
index 7572b9e073..453cd2360d 100644
--- a/keyboards/jc65/v32u4/keymaps/gam3cat/keymap.c
+++ b/keyboards/jc65/v32u4/keymaps/gam3cat/keymap.c
@@ -224,7 +224,7 @@ void matrix_scan_user(void) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _BL:
custom_backlight_level(0);
rgblight_sethsv_noeeprom(180,100,255);
diff --git a/keyboards/jones/v03/keymaps/default_jp/config.h b/keyboards/jones/v03/keymaps/default_jp/config.h
index aa06121c1c..7545003ac7 100644
--- a/keyboards/jones/v03/keymaps/default_jp/config.h
+++ b/keyboards/jones/v03/keymaps/default_jp/config.h
@@ -21,3 +21,4 @@
// time for long press
#define TAPPING_TERM 200
+#define TAPPING_TERM_PER_KEY
diff --git a/keyboards/jones/v03/keymaps/default_jp/keymap.c b/keyboards/jones/v03/keymaps/default_jp/keymap.c
index 3f5b10208c..bdcb9e88b1 100644
--- a/keyboards/jones/v03/keymaps/default_jp/keymap.c
+++ b/keyboards/jones/v03/keymaps/default_jp/keymap.c
@@ -51,9 +51,18 @@ void ql_reset(qk_tap_dance_state_t *state, void *user_data);
// Tap Dance definitions
qk_tap_dance_action_t tap_dance_actions[] = {
[TD_LSFT_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_LSFT, KC_CAPS),
- [TD_ESC_NUM] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, ql_finished, ql_reset, 275),
+ [TD_ESC_NUM] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ql_finished, ql_reset),
};
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case TD(TD_ESC_NUM):
+ return 275;
+ default:
+ return TAPPING_TERM;
+ }
+}
+
// Defines the keycodes used by our macros in process_record_user
enum custom_keycodes {
MAC = SAFE_RANGE,
@@ -303,7 +312,7 @@ static tap ql_tap_state = {
// Functions that control what our tap dance key does
void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
ql_tap_state.state = cur_dance(state);
- switch(state->keycode) {
+ switch(TAP_DANCE_KEYCODE(state)) {
case TD(TD_ESC_NUM): // ESC key action
switch (ql_tap_state.state) {
case SINGLE_TAP:
@@ -332,7 +341,7 @@ void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
}
void ql_reset(qk_tap_dance_state_t *state, void *user_data) {
- switch(state->keycode) {
+ switch(TAP_DANCE_KEYCODE(state)) {
case TD(TD_ESC_NUM):
// If the key was held down and now is released then switch off the layer
if (ql_tap_state.state == TAP_HOLD) {
diff --git a/keyboards/jones/v03_1/keymaps/default_ansi/config.h b/keyboards/jones/v03_1/keymaps/default_ansi/config.h
index 0b51190bbe..ee7b09a90c 100644
--- a/keyboards/jones/v03_1/keymaps/default_ansi/config.h
+++ b/keyboards/jones/v03_1/keymaps/default_ansi/config.h
@@ -21,6 +21,7 @@
// time for long press
#define TAPPING_TERM 200
+#define TAPPING_TERM_PER_KEY
// music map for music-mode
#define MUSIC_MAP
diff --git a/keyboards/jones/v03_1/keymaps/default_ansi/keymap.c b/keyboards/jones/v03_1/keymaps/default_ansi/keymap.c
index 5b1486bb86..a592418c4d 100644
--- a/keyboards/jones/v03_1/keymaps/default_ansi/keymap.c
+++ b/keyboards/jones/v03_1/keymaps/default_ansi/keymap.c
@@ -50,9 +50,18 @@ void ql_reset(qk_tap_dance_state_t *state, void *user_data);
// Tap Dance definitions
qk_tap_dance_action_t tap_dance_actions[] = {
[TD_LSFT_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_LSFT, KC_CAPS),
- [TD_ESC_NUM] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, ql_finished, ql_reset, 275),
+ [TD_ESC_NUM] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ql_finished, ql_reset),
};
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case TD(TD_ESC_NUM):
+ return 275;
+ default:
+ return TAPPING_TERM;
+ }
+}
+
// Defines the keycodes used by our macros in process_record_user
enum custom_keycodes {
MAC = SAFE_RANGE,
@@ -244,7 +253,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
}
}
if (index == 1) { /* Second encoder, Left side */
- switch(biton32(layer_state)) {
+ switch(get_highest_layer(layer_state)) {
case _LOWER:
if (clockwise) {
rgblight_decrease_hue();
@@ -322,7 +331,7 @@ static tap ql_tap_state = {
// Functions that control what our tap dance key does
void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
ql_tap_state.state = cur_dance(state);
- switch(state->keycode) {
+ switch(TAP_DANCE_KEYCODE(state)) {
case TD(TD_ESC_NUM): // ESC key action
switch (ql_tap_state.state) {
case SINGLE_TAP:
@@ -351,7 +360,7 @@ void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
}
void ql_reset(qk_tap_dance_state_t *state, void *user_data) {
- switch(state->keycode) {
+ switch(TAP_DANCE_KEYCODE(state)) {
case TD(TD_ESC_NUM):
// If the key was held down and now is released then switch off the layer
if (ql_tap_state.state == TAP_HOLD) {
diff --git a/keyboards/jones/v03_1/keymaps/default_jp/config.h b/keyboards/jones/v03_1/keymaps/default_jp/config.h
index 0b51190bbe..ee7b09a90c 100644
--- a/keyboards/jones/v03_1/keymaps/default_jp/config.h
+++ b/keyboards/jones/v03_1/keymaps/default_jp/config.h
@@ -21,6 +21,7 @@
// time for long press
#define TAPPING_TERM 200
+#define TAPPING_TERM_PER_KEY
// music map for music-mode
#define MUSIC_MAP
diff --git a/keyboards/jones/v03_1/keymaps/default_jp/keymap.c b/keyboards/jones/v03_1/keymaps/default_jp/keymap.c
index 436586a721..56f51d56ce 100644
--- a/keyboards/jones/v03_1/keymaps/default_jp/keymap.c
+++ b/keyboards/jones/v03_1/keymaps/default_jp/keymap.c
@@ -51,9 +51,18 @@ void ql_reset(qk_tap_dance_state_t *state, void *user_data);
// Tap Dance definitions
qk_tap_dance_action_t tap_dance_actions[] = {
[TD_LSFT_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_LSFT, KC_CAPS),
- [TD_ESC_NUM] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, ql_finished, ql_reset, 275),
+ [TD_ESC_NUM] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ql_finished, ql_reset),
};
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case TD(TD_ESC_NUM):
+ return 275;
+ default:
+ return TAPPING_TERM;
+ }
+}
+
// Defines the keycodes used by our macros in process_record_user
enum custom_keycodes {
MAC = SAFE_RANGE,
@@ -246,7 +255,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
}
}
if (index == 1) { /* Second encoder, Left side */
- switch(biton32(layer_state)) {
+ switch(get_highest_layer(layer_state)) {
case _LOWER:
if (clockwise) {
rgblight_decrease_hue();
@@ -324,7 +333,7 @@ static tap ql_tap_state = {
// Functions that control what our tap dance key does
void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
ql_tap_state.state = cur_dance(state);
- switch(state->keycode) {
+ switch(TAP_DANCE_KEYCODE(state)) {
case TD(TD_ESC_NUM): // ESC key action
switch (ql_tap_state.state) {
case SINGLE_TAP:
@@ -353,7 +362,7 @@ void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
}
void ql_reset(qk_tap_dance_state_t *state, void *user_data) {
- switch(state->keycode) {
+ switch(TAP_DANCE_KEYCODE(state)) {
case TD(TD_ESC_NUM):
// If the key was held down and now is released then switch off the layer
if (ql_tap_state.state == TAP_HOLD) {
diff --git a/keyboards/kakunpc/angel64/alpha/keymaps/default/keymap.c b/keyboards/kakunpc/angel64/alpha/keymaps/default/keymap.c
index 0f2a8dada1..92dfa7da6e 100644
--- a/keyboards/kakunpc/angel64/alpha/keymaps/default/keymap.c
+++ b/keyboards/kakunpc/angel64/alpha/keymaps/default/keymap.c
@@ -40,7 +40,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
#ifdef OLED_ENABLE
bool oled_task_user(void) {
oled_write_P(PSTR("Layer: "), false);
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case BASE:
oled_write_P(PSTR("Default\n"), false);
break;
diff --git a/keyboards/kakunpc/angel64/rev1/keymaps/kakunpc/keymap.c b/keyboards/kakunpc/angel64/rev1/keymaps/kakunpc/keymap.c
index 6c5184c1b3..601bf5f02f 100644
--- a/keyboards/kakunpc/angel64/rev1/keymaps/kakunpc/keymap.c
+++ b/keyboards/kakunpc/angel64/rev1/keymaps/kakunpc/keymap.c
@@ -175,7 +175,7 @@ void matrix_scan_user(void) {
#ifdef OLED_ENABLE
bool oled_task_user(void) {
oled_write_P(PSTR("Layer: "), false);
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case BASE:
oled_write_P(PSTR("Default\n"), false);
break;
diff --git a/keyboards/kakunpc/suihankey/alpha/keymaps/default/keymap.c b/keyboards/kakunpc/suihankey/alpha/keymaps/default/keymap.c
index b682f0f15d..d937b68813 100644
--- a/keyboards/kakunpc/suihankey/alpha/keymaps/default/keymap.c
+++ b/keyboards/kakunpc/suihankey/alpha/keymaps/default/keymap.c
@@ -58,7 +58,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
#ifdef OLED_ENABLE
bool oled_task_user(void) {
oled_write_P(PSTR("Layer: "), false);
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case BASE:
oled_write_P(PSTR("Default\n"), false);
break;
diff --git a/keyboards/kakunpc/suihankey/rev1/keymaps/default/keymap.c b/keyboards/kakunpc/suihankey/rev1/keymaps/default/keymap.c
index b682f0f15d..d937b68813 100644
--- a/keyboards/kakunpc/suihankey/rev1/keymaps/default/keymap.c
+++ b/keyboards/kakunpc/suihankey/rev1/keymaps/default/keymap.c
@@ -58,7 +58,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
#ifdef OLED_ENABLE
bool oled_task_user(void) {
oled_write_P(PSTR("Layer: "), false);
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case BASE:
oled_write_P(PSTR("Default\n"), false);
break;
diff --git a/keyboards/kbdfans/kbd6x/keymaps/othi/keymap.c b/keyboards/kbdfans/kbd6x/keymaps/othi/keymap.c
index 6bbbdd87c1..ce341509a6 100644
--- a/keyboards/kbdfans/kbd6x/keymaps/othi/keymap.c
+++ b/keyboards/kbdfans/kbd6x/keymaps/othi/keymap.c
@@ -38,7 +38,7 @@ void eeconfig_init_user(void) {
#define DE_UDIA_CAP UC(0x00DC)
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case NM_MODE:
rgblight_setrgb (0x00, 0x66, 0x00);
break;
@@ -187,4 +187,3 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______, _______, _______, _______, _______
),
};
-
diff --git a/keyboards/kbdfans/kbd75/keymaps/edulpn/keymap.c b/keyboards/kbdfans/kbd75/keymaps/edulpn/keymap.c
index 998f1a25d2..5a6d760355 100644
--- a/keyboards/kbdfans/kbd75/keymaps/edulpn/keymap.c
+++ b/keyboards/kbdfans/kbd75/keymaps/edulpn/keymap.c
@@ -45,7 +45,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case WINDOWS_LAYER:
rgblight_setrgb_blue();
break;
diff --git a/keyboards/kbdfans/niu_mini/keymaps/tobias/keymap.c b/keyboards/kbdfans/niu_mini/keymaps/tobias/keymap.c
index 935dd5c506..8c03ae2df2 100644
--- a/keyboards/kbdfans/niu_mini/keymaps/tobias/keymap.c
+++ b/keyboards/kbdfans/niu_mini/keymaps/tobias/keymap.c
@@ -8,7 +8,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -103,8 +103,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_EQL, S(KC_EQL), RALT(KC_2), RALT(KC_3), RALT(KC_4), RALT(KC_E), KC_RBRC, RALT(KC_7), RALT(KC_8), RALT(KC_9), RALT(KC_0), RALT(KC_MINS),
KC_LSFT, KC_NUBS, RALT(KC_NUBS), S(KC_NUBS), DGRMCRO, XXXXXXX, XXXXXXX, RALT(KC_M), KC_RBRC, S(KC_RBRC), RALT(KC_RBRC), _______,
_______, _______, KC_RALT, _______,TO(_ADJUST), _______, _______, _______, _______, _______, _______, TO(_QWERTY)
-),
-
+),
+
/* Lower
* ,-----------------------------------------------------------------------------------.
@@ -257,10 +257,10 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
else {
workmode = false;
- return false;
- }
+ return false;
+ }
}
-
+
}
return true;
}
@@ -293,7 +293,7 @@ void rgbflag(uint8_t r, uint8_t g, uint8_t b) {
layer_state_t layer_state_set_user(layer_state_t state) {
// if(rgblight_get_mode() == 1) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _QWERTY:
if(!workmode){
rgblight_mode(9);
@@ -312,7 +312,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
tap_code(KC_NLCK);
}
rgbflag(0xFF, 0x00, 0x00);
-
+
break;
case _ADJUST:
rgblight_mode(1);
@@ -350,7 +350,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
rgblight_mode(1);
if(bnumlock) {
tap_code(KC_NLCK);
- }
+ }
rgbflag(0xFF, 0xFF, 0xFF);
break;
}
@@ -363,8 +363,8 @@ layer_state_t layer_state_set_user(layer_state_t state) {
//Layer LED indicators
uint32_t layer = layer_state;
-
-
+
+
if (layer & (1<<2)) {
if(!bnumlock) {
numlock_changed = true;
@@ -373,10 +373,10 @@ layer_state_t layer_state_set_user(layer_state_t state) {
bnumlock = true;
}
}
-}
+}
*/
-
-
+
+
void led_set_user(uint8_t usb_led) {
if (usb_led & (1 << USB_LED_NUM_LOCK)) {
@@ -410,4 +410,4 @@ void led_set_user(uint8_t usb_led) {
}
-} \ No newline at end of file
+}
diff --git a/keyboards/kbdfans/niu_mini/keymaps/xtonhasvim/keymap.c b/keyboards/kbdfans/niu_mini/keymaps/xtonhasvim/keymap.c
index bfda812738..d3c6102b16 100644
--- a/keyboards/kbdfans/niu_mini/keymaps/xtonhasvim/keymap.c
+++ b/keyboards/kbdfans/niu_mini/keymaps/xtonhasvim/keymap.c
@@ -187,7 +187,7 @@ void rgbflag(uint8_t r, uint8_t g, uint8_t b, uint8_t rr, uint8_t gg, uint8_t bb
void set_state_leds(void) {
if (rgblight_get_mode() == 1) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _RAISE:
rgbflag(C_BLU, C_GRN);
break;
diff --git a/keyboards/keebio/bdn9/keymaps/vosechu-ksp/keymap.c b/keyboards/keebio/bdn9/keymaps/vosechu-ksp/keymap.c
index a449c3ec3d..3b92657d4d 100644
--- a/keyboards/keebio/bdn9/keymaps/vosechu-ksp/keymap.c
+++ b/keyboards/keebio/bdn9/keymaps/vosechu-ksp/keymap.c
@@ -64,7 +64,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
flight_mode = false;
rcs_mode = false;
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _PANIC:
panic_mode = true; // For use in encoder evaluation
rgblight_sethsv_noeeprom(HSV_RED);
diff --git a/keyboards/keebio/bfo9000/keymaps/abstractkb/keymap.c b/keyboards/keebio/bfo9000/keymaps/abstractkb/keymap.c
index 29531b9973..ad56226ac6 100644
--- a/keyboards/keebio/bfo9000/keymaps/abstractkb/keymap.c
+++ b/keyboards/keebio/bfo9000/keymaps/abstractkb/keymap.c
@@ -42,7 +42,7 @@ void matrix_post_init_user(void) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _LIST:
rgblight_sethsv_noeeprom(0,255,255);
rgblight_mode_noeeprom(RGBLIGHT_MODE_RAINBOW_SWIRL);
@@ -87,6 +87,3 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return true;
}
}
-
-
-
diff --git a/keyboards/keebio/iris/keymaps/edvorakjp/keymap.c b/keyboards/keebio/iris/keymaps/edvorakjp/keymap.c
index 0c0fc5a746..013d6c00a5 100644
--- a/keyboards/keebio/iris/keymaps/edvorakjp/keymap.c
+++ b/keyboards/keebio/iris/keymaps/edvorakjp/keymap.c
@@ -59,9 +59,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
void matrix_init_keymap() {}
#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
-uint32_t layer_state_set_keymap(uint32_t state) {
+layer_state_t layer_state_set_keymap(layer_state_t state) {
rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case L_EDVORAKJP_LOWER:
rgblight_sethsv_noeeprom_red();
break;
diff --git a/keyboards/keebio/iris/keymaps/jerryhcooke/keymap.c b/keyboards/keebio/iris/keymaps/jerryhcooke/keymap.c
index e0c09638b2..bc04f9fbfd 100644
--- a/keyboards/keebio/iris/keymaps/jerryhcooke/keymap.c
+++ b/keyboards/keebio/iris/keymaps/jerryhcooke/keymap.c
@@ -11,7 +11,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {[0] = LAYOUT(KC_GE
#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _LOWER:
clockwise ? tap_code(KC_MS_WH_UP) : tap_code(KC_MS_WH_DOWN);
break;
@@ -23,7 +23,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
break;
}
} else if (index == 1) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _LOWER:
clockwise ? tap_code(KC_UP) : tap_code(KC_DOWN);
break;
diff --git a/keyboards/keebio/iris/keymaps/sq5rix/keymap.c b/keyboards/keebio/iris/keymaps/sq5rix/keymap.c
index 19a939a55b..d3e0d680a1 100644
--- a/keyboards/keebio/iris/keymaps/sq5rix/keymap.c
+++ b/keyboards/keebio/iris/keymaps/sq5rix/keymap.c
@@ -134,7 +134,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
}
// tmux screen
else if (index == 1) {
- switch(biton32(layer_state)){
+ switch(get_highest_layer(layer_state)){
case 0:
if (clockwise) {
send_string(SS_LCTL("B")"p");
@@ -182,4 +182,3 @@ layer_state_t layer_state_set_user(layer_state_t state) {
rgblight_set_layer_state(2, layer_state_cmp(state, 4));
return state;
}
-
diff --git a/keyboards/keebio/levinson/keymaps/issmirnov/keymap.c b/keyboards/keebio/levinson/keymaps/issmirnov/keymap.c
index d9edfebaa0..6de2279be4 100644
--- a/keyboards/keebio/levinson/keymaps/issmirnov/keymap.c
+++ b/keyboards/keebio/levinson/keymaps/issmirnov/keymap.c
@@ -91,7 +91,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
#ifdef RGBLIGHT_ENABLE
layer_state_set_rgb(state);
#endif
- uint8_t layer = biton32(state);
+ uint8_t layer = get_highest_layer(state);
combo_enable(); // by default, enable combos.
switch (layer) {
case 0:
diff --git a/keyboards/keebio/levinson/keymaps/issmirnov/rgb.c b/keyboards/keebio/levinson/keymaps/issmirnov/rgb.c
index de3a5342c0..3695731353 100644
--- a/keyboards/keebio/levinson/keymaps/issmirnov/rgb.c
+++ b/keyboards/keebio/levinson/keymaps/issmirnov/rgb.c
@@ -45,7 +45,7 @@ void matrix_scan_rgb(void) {
}
void set_rgb_indicators(uint8_t this_mod, uint8_t this_osm) {
- if (biton32(layer_state) == _QWERTY) {
+ if (get_highest_layer(layer_state) == _QWERTY) {
if ((this_mod | this_osm) & MOD_MASK_SHIFT) {
rgblight_setrgb_gold_at(SHFT_LED1);
} else {
diff --git a/keyboards/keebio/levinson/keymaps/issmirnov/rgb.h b/keyboards/keebio/levinson/keymaps/issmirnov/rgb.h
index 254d3cbac0..8b14d8571d 100644
--- a/keyboards/keebio/levinson/keymaps/issmirnov/rgb.h
+++ b/keyboards/keebio/levinson/keymaps/issmirnov/rgb.h
@@ -6,7 +6,7 @@
void keyboard_post_init_rgb(void);
// If rgb enabled, set underglow for layer
-uint32_t layer_state_set_rgb(uint32_t state);
+layer_state_t layer_state_set_rgb(layer_state_t state);
// Enhance matrix scan code. Note: keep this light, since it runs every 100ms
void matrix_scan_rgb(void);
diff --git a/keyboards/keebio/levinson/keymaps/xtonhasvim/keymap.c b/keyboards/keebio/levinson/keymaps/xtonhasvim/keymap.c
index 16aa965d7d..014e6c9c23 100644
--- a/keyboards/keebio/levinson/keymaps/xtonhasvim/keymap.c
+++ b/keyboards/keebio/levinson/keymaps/xtonhasvim/keymap.c
@@ -182,7 +182,7 @@ void rgbflag(uint8_t r, uint8_t g, uint8_t b, uint8_t rr, uint8_t gg, uint8_t bb
void set_state_leds(void) {
if (rgblight_get_mode() == 1) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _RAISE:
rgbflag(C_BLU, C_GRN);
break;
diff --git a/keyboards/keebio/nyquist/keymaps/pitty/keymap.c b/keyboards/keebio/nyquist/keymaps/pitty/keymap.c
index 31912bb63e..2016cd1c46 100644
--- a/keyboards/keebio/nyquist/keymaps/pitty/keymap.c
+++ b/keyboards/keebio/nyquist/keymaps/pitty/keymap.c
@@ -143,7 +143,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
#ifdef RGBLIGHT_ENABLE
uint8_t default_layer = eeconfig_read_default_layer();
if (rgb_layer_change) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _LOWER:
rgblight_set_purple;
rgblight_mode(5);
diff --git a/keyboards/keebio/quefrency/keymaps/georgepetri/keymap.c b/keyboards/keebio/quefrency/keymaps/georgepetri/keymap.c
index a367e877fe..7d6f9da30e 100644
--- a/keyboards/keebio/quefrency/keymaps/georgepetri/keymap.c
+++ b/keyboards/keebio/quefrency/keymaps/georgepetri/keymap.c
@@ -64,7 +64,7 @@ void keyboard_post_init_user(void) {
}
void update_led(void) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _BASE:
rgblight_sethsv_noeeprom(HSV_BLUE);
break;
diff --git a/keyboards/keycapsss/o4l_5x12/keymaps/default/keymap.c b/keyboards/keycapsss/o4l_5x12/keymaps/default/keymap.c
index 050b5a2c3e..2f64a56e9a 100644
--- a/keyboards/keycapsss/o4l_5x12/keymaps/default/keymap.c
+++ b/keyboards/keycapsss/o4l_5x12/keymaps/default/keymap.c
@@ -92,7 +92,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[_ADJUST] = LAYOUT_ortho_5x12(
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
- _______, QK_BOOT, DEBUG, _______, _______, _______, _______, TERM_ON, TERM_OFF,_______, _______, KC_DEL,
+ _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______,_______, _______, KC_DEL,
_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, _______, _______, _______, _______,
_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/keyboards/keychron/q2/config.h b/keyboards/keychron/q2/config.h
index d019bcee15..e513536056 100644
--- a/keyboards/keychron/q2/config.h
+++ b/keyboards/keychron/q2/config.h
@@ -64,7 +64,8 @@
#define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 2047
/* EEPROM Driver Configuration */
-#define EXTERNAL_EEPROM_I2C_BASE_ADDRESS 0b10100010
+#define WEAR_LEVELING_LOGICAL_SIZE 2048
+#define WEAR_LEVELING_BACKING_SIZE (WEAR_LEVELING_LOGICAL_SIZE * 2)
// RGB Matrix Animation modes. Explicitly enabled
// For full list of effects, see:
diff --git a/keyboards/keychron/q2/rev_0110/rules.mk b/keyboards/keychron/q2/rev_0110/rules.mk
index 30394028b3..38d48f0b27 100644
--- a/keyboards/keychron/q2/rev_0110/rules.mk
+++ b/keyboards/keychron/q2/rev_0110/rules.mk
@@ -20,7 +20,8 @@ ENCODER_ENABLE = no # Enable Encoder
DIP_SWITCH_ENABLE = yes
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = CKLED2001
-EEPROM_DRIVER = i2c
+EEPROM_DRIVER = wear_leveling
+WEAR_LEVELING_DRIVER = embedded_flash
# Enter lower-power sleep mode when on the ChibiOS idle thread
OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE
diff --git a/keyboards/keychron/q2/rev_0111/rules.mk b/keyboards/keychron/q2/rev_0111/rules.mk
index a295f48e10..9332d29432 100644
--- a/keyboards/keychron/q2/rev_0111/rules.mk
+++ b/keyboards/keychron/q2/rev_0111/rules.mk
@@ -20,7 +20,8 @@ ENCODER_ENABLE = yes # Enable Encoder
DIP_SWITCH_ENABLE = yes
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = CKLED2001
-EEPROM_DRIVER = i2c
+EEPROM_DRIVER = wear_leveling
+WEAR_LEVELING_DRIVER = embedded_flash
# Enter lower-power sleep mode when on the ChibiOS idle thread
OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE
diff --git a/keyboards/keychron/q2/rev_0112/rules.mk b/keyboards/keychron/q2/rev_0112/rules.mk
index 30394028b3..38d48f0b27 100644
--- a/keyboards/keychron/q2/rev_0112/rules.mk
+++ b/keyboards/keychron/q2/rev_0112/rules.mk
@@ -20,7 +20,8 @@ ENCODER_ENABLE = no # Enable Encoder
DIP_SWITCH_ENABLE = yes
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = CKLED2001
-EEPROM_DRIVER = i2c
+EEPROM_DRIVER = wear_leveling
+WEAR_LEVELING_DRIVER = embedded_flash
# Enter lower-power sleep mode when on the ChibiOS idle thread
OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE
diff --git a/keyboards/keychron/q2/rev_0113/rules.mk b/keyboards/keychron/q2/rev_0113/rules.mk
index a295f48e10..9332d29432 100644
--- a/keyboards/keychron/q2/rev_0113/rules.mk
+++ b/keyboards/keychron/q2/rev_0113/rules.mk
@@ -20,7 +20,8 @@ ENCODER_ENABLE = yes # Enable Encoder
DIP_SWITCH_ENABLE = yes
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = CKLED2001
-EEPROM_DRIVER = i2c
+EEPROM_DRIVER = wear_leveling
+WEAR_LEVELING_DRIVER = embedded_flash
# Enter lower-power sleep mode when on the ChibiOS idle thread
OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE
diff --git a/keyboards/keyhive/honeycomb/keymaps/default/keymap.c b/keyboards/keyhive/honeycomb/keymaps/default/keymap.c
index d0a5961873..429624822e 100755
--- a/keyboards/keyhive/honeycomb/keymaps/default/keymap.c
+++ b/keyboards/keyhive/honeycomb/keymaps/default/keymap.c
@@ -37,7 +37,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
report_mouse_t currentReport = {};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
- //uint8_t layer = biton32(layer_state); // get the current layer
+ //uint8_t layer = get_highest_layer(layer_state); // get the current layer
// Basic example functions
switch (keycode) {
diff --git a/keyboards/keyhive/navi10/keymaps/default/keymap.c b/keyboards/keyhive/navi10/keymaps/default/keymap.c
index d1b3127760..c4295b1553 100644
--- a/keyboards/keyhive/navi10/keymaps/default/keymap.c
+++ b/keyboards/keyhive/navi10/keymaps/default/keymap.c
@@ -127,5 +127,5 @@ void tk_reset(qk_tap_dance_state_t *state, void *user_data){
//associate the tap dance key with its functionality
qk_tap_dance_action_t tap_dance_actions[] = {
- [TAPPY_KEY] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, tk_finished, tk_reset, 275)
+ [TAPPY_KEY] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, tk_finished, tk_reset)
};
diff --git a/keyboards/keyhive/navi10/keymaps/devdev/keymap.c b/keyboards/keyhive/navi10/keymaps/devdev/keymap.c
index b0d43ebc69..0fc20cbbd4 100644
--- a/keyboards/keyhive/navi10/keymaps/devdev/keymap.c
+++ b/keyboards/keyhive/navi10/keymaps/devdev/keymap.c
@@ -259,5 +259,5 @@ void tk_reset(qk_tap_dance_state_t *state, void *user_data){
//associate the tap dance key with its functionality
qk_tap_dance_action_t tap_dance_actions[] = {
- [TAPPY_KEY] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, tk_finished, tk_reset, TAPPING_TERM)
+ [TAPPY_KEY] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, tk_finished, tk_reset)
};
diff --git a/keyboards/keyhive/navi10/keymaps/emdarcher/keymap.c b/keyboards/keyhive/navi10/keymaps/emdarcher/keymap.c
index 40efed48d5..37850e28f3 100644
--- a/keyboards/keyhive/navi10/keymaps/emdarcher/keymap.c
+++ b/keyboards/keyhive/navi10/keymaps/emdarcher/keymap.c
@@ -178,5 +178,5 @@ void tk_reset(qk_tap_dance_state_t *state, void *user_data){
//associate the tap dance key with its functionality
qk_tap_dance_action_t tap_dance_actions[] = {
- [TAPPY_KEY] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, tk_finished, tk_reset, 275)
+ [TAPPY_KEY] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, tk_finished, tk_reset)
};
diff --git a/keyboards/kinesis/keymaps/milestogo/keymap.c b/keyboards/kinesis/keymaps/milestogo/keymap.c
index 8c01bcb83d..72687195ef 100644
--- a/keyboards/kinesis/keymaps/milestogo/keymap.c
+++ b/keyboards/kinesis/keymaps/milestogo/keymap.c
@@ -330,7 +330,7 @@ void matrix_init_user(void) {
void matrix_scan_user(void) {
#ifdef ALVICSTEP_CONFIG_H
- int8_t layer = biton32(layer_state);
+ int8_t layer = get_highest_layer(layer_state);
switch (layer) {
case 1:
diff --git a/keyboards/kprepublic/cospad/keymaps/detrus/keymap.c b/keyboards/kprepublic/cospad/keymaps/detrus/keymap.c
index af56305e5c..84324c6e0d 100644
--- a/keyboards/kprepublic/cospad/keymaps/detrus/keymap.c
+++ b/keyboards/kprepublic/cospad/keymaps/detrus/keymap.c
@@ -271,7 +271,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Makes sure to update the good tri-layer if a layer changes
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(default_layer_state)) {
+ switch (get_highest_layer(default_layer_state)) {
case _QWERTY_LAYER:
state = update_tri_layer_state(state, _RAISE_LAYER, _QWERTY_LOWER_LAYER, _ALTER_LAYER);
break;
@@ -289,8 +289,8 @@ layer_state_t layer_state_set_user(layer_state_t state) {
}
// Makes the tri-layer
-uint32_t default_layer_state_set_kb(uint32_t state) {
- switch (biton32(state)) {
+layer_state_t default_layer_state_set_kb(layer_state_t state) {
+ switch (get_highest_layer(state)) {
case _QWERTY_LAYER:
state = update_tri_layer_state(state, _RAISE_LAYER, _QWERTZ_LOWER_LAYER, _ALTER_LAYER);
state = update_tri_layer_state(state, _RAISE_LAYER, _COLEMA_LOWER_LAYER, _ALTER_LAYER);
diff --git a/keyboards/kprepublic/jj50/keymaps/abstractkb/keymap.c b/keyboards/kprepublic/jj50/keymaps/abstractkb/keymap.c
index e257649369..c096aaea10 100644
--- a/keyboards/kprepublic/jj50/keymaps/abstractkb/keymap.c
+++ b/keyboards/kprepublic/jj50/keymaps/abstractkb/keymap.c
@@ -42,7 +42,7 @@ void keyboard_post_init_user(void) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _RAISE:
rgblight_sethsv_noeeprom(170,255,255);
rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
diff --git a/keyboards/kprepublic/jj50/keymaps/abstractkb_gergomatch/keymap.c b/keyboards/kprepublic/jj50/keymaps/abstractkb_gergomatch/keymap.c
index baedbb4dd2..af4c3c84bb 100644
--- a/keyboards/kprepublic/jj50/keymaps/abstractkb_gergomatch/keymap.c
+++ b/keyboards/kprepublic/jj50/keymaps/abstractkb_gergomatch/keymap.c
@@ -42,7 +42,7 @@ void keyboard_post_init_user(void) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _FUNC:
rgblight_sethsv_noeeprom(170,255,255);
rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
diff --git a/keyboards/kprepublic/jj50/keymaps/archetype/config.h b/keyboards/kprepublic/jj50/keymaps/archetype/config.h
index a12e070b4f..9604ac719c 100644
--- a/keyboards/kprepublic/jj50/keymaps/archetype/config.h
+++ b/keyboards/kprepublic/jj50/keymaps/archetype/config.h
@@ -6,4 +6,5 @@
#define AUTO_SHIFT_TIMEOUT 150
#define NO_AUTO_SHIFT_ALPHA
#define TAPPING_TERM 150
+#define TAPPING_TERM_PER_KEY
//#define BOOTMAGIC_KEY_SALT KC_LCTL
diff --git a/keyboards/kprepublic/jj50/keymaps/archetype/keymap.c b/keyboards/kprepublic/jj50/keymaps/archetype/keymap.c
index 82c615f135..ff59ef43e5 100644
--- a/keyboards/kprepublic/jj50/keymaps/archetype/keymap.c
+++ b/keyboards/kprepublic/jj50/keymaps/archetype/keymap.c
@@ -167,9 +167,18 @@ qk_tap_dance_action_t tap_dance_actions[] = {
// Single tap = ) | Double tap = ] | Triple tap = } | Single hold = KC_LALT
[TD_LALT_RBRC] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, right_brackets, right_brackets_reset),
// Layer Switcher ESC
- [TD_ESC_LAYER] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, layer_switcher, layer_switcher_reset, 100),
+ [TD_ESC_LAYER] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, layer_switcher, layer_switcher_reset),
};
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case TD(TD_ESC_LAYER):
+ return 100;
+ default:
+ return TAPPING_TERM;
+ }
+}
+
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/ktec/ergodone/keymaps/eozaki/keymap.c b/keyboards/ktec/ergodone/keymaps/eozaki/keymap.c
index 09854ee89c..3910756f81 100644
--- a/keyboards/ktec/ergodone/keymaps/eozaki/keymap.c
+++ b/keyboards/ktec/ergodone/keymaps/eozaki/keymap.c
@@ -179,7 +179,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ktec/ergodone/keymaps/erovia/keymap.c b/keyboards/ktec/ergodone/keymaps/erovia/keymap.c
index 279c8a57c1..502c0dafe6 100644
--- a/keyboards/ktec/ergodone/keymaps/erovia/keymap.c
+++ b/keyboards/ktec/ergodone/keymaps/erovia/keymap.c
@@ -204,7 +204,7 @@ void matrix_init_user(void) {
layer_state_t layer_state_set_user(layer_state_t state) {
ergodox_led_all_off();
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case FN:
// Red led on Pro Micro for Fn layer
ergodox_board_led_on();
diff --git a/keyboards/ktec/ergodone/keymaps/kloki/keymap.c b/keyboards/ktec/ergodone/keymaps/kloki/keymap.c
index 87e96d20fd..1347f8f501 100644
--- a/keyboards/ktec/ergodone/keymaps/kloki/keymap.c
+++ b/keyboards/ktec/ergodone/keymaps/kloki/keymap.c
@@ -198,7 +198,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/ktec/ergodone/keymaps/vega/keymap.c b/keyboards/ktec/ergodone/keymaps/vega/keymap.c
index ee6c56bf95..21db785345 100644
--- a/keyboards/ktec/ergodone/keymaps/vega/keymap.c
+++ b/keyboards/ktec/ergodone/keymaps/vega/keymap.c
@@ -534,7 +534,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/keyboards/leeku/finger65/keymaps/madhatter/keymap.c b/keyboards/leeku/finger65/keymaps/madhatter/keymap.c
index a69fe69153..f73b0371a1 100644
--- a/keyboards/leeku/finger65/keymaps/madhatter/keymap.c
+++ b/keyboards/leeku/finger65/keymaps/madhatter/keymap.c
@@ -40,7 +40,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
// layer_state_t layer_state_set_user(layer_state_t state) {
-// switch(biton32(state)) {
+// switch(get_highest_layer(state)) {
// case _FNMS:
// led_off();
// rgb_on();
diff --git a/keyboards/lets_split/keymaps/bbaserdem/keymap.c b/keyboards/lets_split/keymaps/bbaserdem/keymap.c
index f9eab059ef..296b3ccd23 100755
--- a/keyboards/lets_split/keymaps/bbaserdem/keymap.c
+++ b/keyboards/lets_split/keymaps/bbaserdem/keymap.c
@@ -13,7 +13,7 @@
void matrix_init_keymap (void) {
}
-uint32_t layer_state_set_keymap(uint32_t state) {
+layer_state_t layer_state_set_keymap(layer_state_t state) {
return state;
}
diff --git a/keyboards/lets_split/keymaps/cpeters1982/keymap.c b/keyboards/lets_split/keymaps/cpeters1982/keymap.c
index c4c26d56bc..27cd9db8b4 100644
--- a/keyboards/lets_split/keymaps/cpeters1982/keymap.c
+++ b/keyboards/lets_split/keymaps/cpeters1982/keymap.c
@@ -183,7 +183,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
#ifdef RGBLIGHT_ENABLE
uint8_t default_layer = eeconfig_read_default_layer();
if (rgb_layer_change) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _RAISE:
rgblight_set_orange;
rgblight_mode(5);
diff --git a/keyboards/lets_split/keymaps/geripgeri/keymap.c b/keyboards/lets_split/keymaps/geripgeri/keymap.c
index 62e3570468..eb22a1509e 100644
--- a/keyboards/lets_split/keymaps/geripgeri/keymap.c
+++ b/keyboards/lets_split/keymaps/geripgeri/keymap.c
@@ -255,7 +255,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
state = update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
writePin(B0, !(state & (1UL << (_NUMPAD))));
- switch(biton32(state)) {
+ switch(get_highest_layer(state)) {
case _RAISE:
rgblight_setrgb_at(255, 255, 255, RGBLED_NUM / 2);
rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
diff --git a/keyboards/lets_split/keymaps/pitty/keymap.c b/keyboards/lets_split/keymaps/pitty/keymap.c
index d723e0c026..8bc32a1eb7 100644
--- a/keyboards/lets_split/keymaps/pitty/keymap.c
+++ b/keyboards/lets_split/keymaps/pitty/keymap.c
@@ -128,7 +128,7 @@ void persistent_default_layer_set(uint16_t default_layer) {
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _NAV:
if (RGB_INIT) {} else {
diff --git a/keyboards/lily58/lib/layer_state_reader.c b/keyboards/lily58/lib/layer_state_reader.c
index 0e9dd7039b..868d8e5cb4 100644
--- a/keyboards/lily58/lib/layer_state_reader.c
+++ b/keyboards/lily58/lib/layer_state_reader.c
@@ -28,7 +28,7 @@ const char *read_layer_state(void) {
snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Adjust");
break;
default:
- snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Undef-%ld", layer_state);
+ snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Undef-%u", layer_state);
}
return layer_state_str;
diff --git a/keyboards/m10a/keymaps/gam3cat/keymap.c b/keyboards/m10a/keymaps/gam3cat/keymap.c
index f962246ef3..86231f8406 100644
--- a/keyboards/m10a/keymaps/gam3cat/keymap.c
+++ b/keyboards/m10a/keymaps/gam3cat/keymap.c
@@ -115,7 +115,7 @@ void matrix_scan_user(void) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _L0:
custom_backlight_level(0);
break;
diff --git a/keyboards/maple_computing/lets_split_eh/keymaps/bbaserdem/keymap.c b/keyboards/maple_computing/lets_split_eh/keymaps/bbaserdem/keymap.c
index 92e72bbf1c..73329c3114 100755
--- a/keyboards/maple_computing/lets_split_eh/keymaps/bbaserdem/keymap.c
+++ b/keyboards/maple_computing/lets_split_eh/keymaps/bbaserdem/keymap.c
@@ -5,7 +5,7 @@
void matrix_init_keymap (void) {
}
-uint32_t layer_state_set_keymap(uint32_t state) {
+layer_state_t layer_state_set_keymap(layer_state_t state) {
return state;
}
diff --git a/keyboards/maple_computing/lets_split_eh/keymaps/romus/keymap.c b/keyboards/maple_computing/lets_split_eh/keymaps/romus/keymap.c
index ba5b75a5cf..398a324a0f 100644
--- a/keyboards/maple_computing/lets_split_eh/keymaps/romus/keymap.c
+++ b/keyboards/maple_computing/lets_split_eh/keymaps/romus/keymap.c
@@ -5,8 +5,8 @@
void matrix_init_keymap (void) {
}
-uint32_t layer_state_set_keymap(uint32_t state) {
-
+layer_state_t layer_state_set_keymap(layer_state_t state) {
+
return state;
}
diff --git a/keyboards/massdrop/alt/keymaps/pregame/rules.mk b/keyboards/massdrop/alt/keymaps/pregame/rules.mk
index 184405662a..5981633f7c 100644
--- a/keyboards/massdrop/alt/keymaps/pregame/rules.mk
+++ b/keyboards/massdrop/alt/keymaps/pregame/rules.mk
@@ -8,7 +8,6 @@ DYNAMIC_MACRO_ENABLE = no # Dynamic macro recording and play
MOUSEKEY_ENABLE = no # Enable mouse control keycodes. Increases firmware size.
TAP_DANCE_ENABLE = no # Enable tap dance keys
CONSOLE_ENABLE = no # Enable debugging console. Increases firmware size.
-TERMINAL_ENABLE = no
EXTRAKEY_ENABLE = yes # Audio control and System control
# RAW_ENABLE = yes # Raw HID has not yet been implemented for this keyboard
# COMBO_ENABLE # Key combo feature
diff --git a/keyboards/massdrop/ctrl/keymaps/endgame/rules.mk b/keyboards/massdrop/ctrl/keymaps/endgame/rules.mk
index 9502c242dd..c4fab8ad53 100644
--- a/keyboards/massdrop/ctrl/keymaps/endgame/rules.mk
+++ b/keyboards/massdrop/ctrl/keymaps/endgame/rules.mk
@@ -7,7 +7,6 @@ MOUSEKEY_ENABLE = yes # Enable mouse control keycodes. Increases firmware size
TAP_DANCE_ENABLE = yes # Enable tap dance keys
CONSOLE_ENABLE = yes # Enable debugging console. Increases firmware size.
SRC += config_led.c # Used to add files to the compilation/linking list.
-TERMINAL_ENABLE = yes
EXTRAKEY_ENABLE = yes # Audio control and System control
# RAW_ENABLE = yes # Raw HID has not yet been implemented for this keyboard
# COMBO_ENABLE # Key combo feature
diff --git a/keyboards/massdrop/ctrl/keymaps/matthewrobo/rules.mk b/keyboards/massdrop/ctrl/keymaps/matthewrobo/rules.mk
index e834404e29..4bb43f525b 100644
--- a/keyboards/massdrop/ctrl/keymaps/matthewrobo/rules.mk
+++ b/keyboards/massdrop/ctrl/keymaps/matthewrobo/rules.mk
@@ -7,7 +7,6 @@ MOUSEKEY_ENABLE = no # Enable mouse control keycodes. Increases firmware size.
TAP_DANCE_ENABLE = no # Enable tap dance keys
CONSOLE_ENABLE = no # Enable debugging console. Increases firmware size.
SRC += config_led.c # Used to add files to the compilation/linking list.
-TERMINAL_ENABLE = no
EXTRAKEY_ENABLE = yes # Audio control and System control
#RAW_ENABLE = yes #Raw HID has not yet been implemented for this keyboard
#COMBO_ENABLE #Key combo feature
diff --git a/keyboards/massdrop/ctrl/keymaps/xanimos/rules.mk b/keyboards/massdrop/ctrl/keymaps/xanimos/rules.mk
index 43a312ce4e..2913eff83b 100644
--- a/keyboards/massdrop/ctrl/keymaps/xanimos/rules.mk
+++ b/keyboards/massdrop/ctrl/keymaps/xanimos/rules.mk
@@ -8,7 +8,6 @@ TAP_DANCE_ENABLE = yes # Enable tap dance keys
CONSOLE_ENABLE = no # Enable debugging console. Increases firmware size.
SRC += config_led.c # Used to add files to the compilation/linking list.
EXTRAKEY_ENABLE = yes # Audio control and System control
-TERMINAL_ENABLE = no
# RAW_ENABLE = yes # Raw HID has not yet been implemented for this keyboard
# COMBO_ENABLE # Key combo feature
# LEADER_ENABLE # Enable leader key chording
diff --git a/keyboards/mechkeys/mechmini/v2/keymaps/wsturgiss/keymap.c b/keyboards/mechkeys/mechmini/v2/keymaps/wsturgiss/keymap.c
index 218936a19b..689a9ce36e 100644
--- a/keyboards/mechkeys/mechmini/v2/keymaps/wsturgiss/keymap.c
+++ b/keyboards/mechkeys/mechmini/v2/keymaps/wsturgiss/keymap.c
@@ -87,7 +87,7 @@ void matrix_scan_user(void) {
//change colors and rgb modes on layer change
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case raise:
rgblight_mode_noeeprom(1);
rgblight_setrgb(0xc7, 0x00, 0xf4);
@@ -103,4 +103,3 @@ layer_state_t layer_state_set_user(layer_state_t state) {
}
return state;
};
-
diff --git a/keyboards/mechllama/g35/keymaps/default/keymap.c b/keyboards/mechllama/g35/keymaps/default/keymap.c
index 4568f54f54..09d7afe171 100644
--- a/keyboards/mechllama/g35/keymaps/default/keymap.c
+++ b/keyboards/mechllama/g35/keymaps/default/keymap.c
@@ -67,7 +67,7 @@ const char* get_layer_name(uint8_t layer) {
}
bool oled_task_user(void) {
- oled_write_ln_P(get_layer_name(biton32(layer_state)), false);
+ oled_write_ln_P(get_layer_name(get_highest_layer(layer_state)), false);
return false;
}
#endif
diff --git a/keyboards/mechlovin/hannah910/hannah910.c b/keyboards/mechlovin/hannah910/hannah910.c
index 3237636be2..70c1a7b8e3 100644
--- a/keyboards/mechlovin/hannah910/hannah910.c
+++ b/keyboards/mechlovin/hannah910/hannah910.c
@@ -34,20 +34,20 @@ void led_set_kb(uint8_t usb_led) {
layer_state_t layer_state_set_user(layer_state_t state)
{
// if on layer 1, turn on D2 LED, otherwise off.
- if (biton32(state) == 1) {
+ if (get_highest_layer(state) == 1) {
writePinHigh(D2);
} else {
writePinLow(D2);
}
// if on layer 2, turn on D1 LED, otherwise off.
- if (biton32(state) == 2) {
+ if (get_highest_layer(state) == 2) {
writePinHigh(D1);
} else {
writePinLow(D1);
}
// if on layer 3, turn on D0 LED, otherwise off.
- if (biton32(state) == 3) {
+ if (get_highest_layer(state) == 3) {
writePinHigh(D0);
} else {
writePinLow(D0);
diff --git a/keyboards/mechlovin/hex4b/keymaps/nazzer/keymap.c b/keyboards/mechlovin/hex4b/keymaps/nazzer/keymap.c
index 437233be52..e0634d85dc 100644
--- a/keyboards/mechlovin/hex4b/keymaps/nazzer/keymap.c
+++ b/keyboards/mechlovin/hex4b/keymaps/nazzer/keymap.c
@@ -53,9 +53,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
bool led_update_user(led_t led_state) {
-
+
// Toggle CAPS_LOCK LED normally
-
+
# if LED_PIN_ON_STATE == 0
// invert the whole thing to avoid having to conditionally !led_state.x later
led_state.raw = ~led_state.raw;
@@ -69,30 +69,30 @@ bool led_update_user(led_t led_state) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
-
- uint8_t layer = biton32(state);
-
+
+ uint8_t layer = get_highest_layer(state);
+
#if defined(LED_NUM_LOCK_PIN) && defined(LED_SCROLL_LOCK_PIN)
switch (layer) {
case 0:
- writePin(LED_SCROLL_LOCK_PIN, !LED_PIN_ON_STATE);
- writePin(LED_NUM_LOCK_PIN, !LED_PIN_ON_STATE);
+ writePin(LED_SCROLL_LOCK_PIN, !LED_PIN_ON_STATE);
+ writePin(LED_NUM_LOCK_PIN, !LED_PIN_ON_STATE);
break;
case 1:
- writePin(LED_SCROLL_LOCK_PIN, LED_PIN_ON_STATE);
- writePin(LED_NUM_LOCK_PIN, !LED_PIN_ON_STATE);
+ writePin(LED_SCROLL_LOCK_PIN, LED_PIN_ON_STATE);
+ writePin(LED_NUM_LOCK_PIN, !LED_PIN_ON_STATE);
break;
case 2:
- writePin(LED_SCROLL_LOCK_PIN, !LED_PIN_ON_STATE);
- writePin(LED_NUM_LOCK_PIN, LED_PIN_ON_STATE);
+ writePin(LED_SCROLL_LOCK_PIN, !LED_PIN_ON_STATE);
+ writePin(LED_NUM_LOCK_PIN, LED_PIN_ON_STATE);
break;
case 3:
- writePin(LED_SCROLL_LOCK_PIN, LED_PIN_ON_STATE);
- writePin(LED_NUM_LOCK_PIN, LED_PIN_ON_STATE);
+ writePin(LED_SCROLL_LOCK_PIN, LED_PIN_ON_STATE);
+ writePin(LED_NUM_LOCK_PIN, LED_PIN_ON_STATE);
break;
}
#endif
- return state;
+ return state;
}
diff --git a/keyboards/minimacro5/keymaps/devdev/keymap.c b/keyboards/minimacro5/keymaps/devdev/keymap.c
index d7f998fa3a..3c203fcc37 100644
--- a/keyboards/minimacro5/keymaps/devdev/keymap.c
+++ b/keyboards/minimacro5/keymaps/devdev/keymap.c
@@ -37,7 +37,7 @@ enum tap_dances{
bool encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) { /* First encoder*/
- switch(biton32(layer_state)){
+ switch(get_highest_layer(layer_state)){
case _MAIN:
if (clockwise) {
tap_code(KC_VOLU);
diff --git a/keyboards/mitosis/keymaps/carvac_dv/keymap.c b/keyboards/mitosis/keymaps/carvac_dv/keymap.c
index c67f2e387c..842556324f 100644
--- a/keyboards/mitosis/keymaps/carvac_dv/keymap.c
+++ b/keyboards/mitosis/keymaps/carvac_dv/keymap.c
@@ -105,7 +105,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _STD:
@@ -121,4 +121,3 @@ void matrix_scan_user(void) {
break;
}
};
-
diff --git a/keyboards/mitosis/keymaps/datagrok/keymap.c b/keyboards/mitosis/keymaps/datagrok/keymap.c
index 220c140af0..2611e1194c 100644
--- a/keyboards/mitosis/keymaps/datagrok/keymap.c
+++ b/keyboards/mitosis/keymaps/datagrok/keymap.c
@@ -102,7 +102,7 @@ const size_t defaultlayers_n = sizeof(defaultlayers) / sizeof(defaultlayers[0]);
// New keycode KC_LAYO rotates between available default layers (for e.g.,
// selecting a base layout). Shift+KC_LAYO makes the current one persistent.
bool process_record_layout(uint16_t keycode, keyrecord_t *record) {
- uint32_t default_layer;
+ uint8_t default_layer;
uint8_t i;
#if defined(AUDIO_ENABLE)
float saved_song[][2] = SONG(COIN_SOUND);
@@ -121,7 +121,7 @@ bool process_record_layout(uint16_t keycode, keyrecord_t *record) {
} else {
// rotate default layer.
// find the current default layer
- default_layer = biton32(default_layer_state);
+ default_layer = get_highest_layer(default_layer_state);
// find next valid default layer
for (i = 1; i < defaultlayers_n; i++) {
if (defaultlayers[(default_layer + i) % defaultlayers_n]) {
diff --git a/keyboards/mitosis/keymaps/default/keymap.c b/keyboards/mitosis/keymaps/default/keymap.c
index 6132ad6f78..27b2eb2525 100644
--- a/keyboards/mitosis/keymaps/default/keymap.c
+++ b/keyboards/mitosis/keymaps/default/keymap.c
@@ -77,7 +77,7 @@ static bool singular_key = false;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
uint8_t layer;
- layer = biton32(layer_state); // get the current layer
+ layer = get_highest_layer(layer_state); // get the current layer
//custom layer handling for tri_layer,
switch (keycode) {
@@ -174,7 +174,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
};
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _MALT:
@@ -193,4 +193,3 @@ void matrix_scan_user(void) {
break;
}
};
-
diff --git a/keyboards/mitosis/keymaps/mjt/keymap.c b/keyboards/mitosis/keymaps/mjt/keymap.c
index f00bf59556..0946e40b8e 100644
--- a/keyboards/mitosis/keymaps/mjt/keymap.c
+++ b/keyboards/mitosis/keymaps/mjt/keymap.c
@@ -181,7 +181,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
}
uint8_t layer;
- layer = biton32(layer_state); // get the current layer
+ layer = get_highest_layer(layer_state); // get the current layer
//custom layer handling for tri_layer,
switch (keycode) {
@@ -310,7 +310,7 @@ void music_scale_user(void)
#endif
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _QWERTY:
diff --git a/keyboards/mitosis/keymaps/nzen/keymap.c b/keyboards/mitosis/keymaps/nzen/keymap.c
index d9fd3641bc..c981441bc9 100644
--- a/keyboards/mitosis/keymaps/nzen/keymap.c
+++ b/keyboards/mitosis/keymaps/nzen/keymap.c
@@ -175,7 +175,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _QWERTY:
@@ -205,5 +205,3 @@ void matrix_scan_user(void) {
void matrix_init_user(void) {
set_unicode_input_mode(UC_LNX); // or UC_WINC
};
-
-
diff --git a/keyboards/mlego/m48/keymaps/default/keymap.c b/keyboards/mlego/m48/keymaps/default/keymap.c
index 5eb40a332a..175f42b9b9 100644
--- a/keyboards/mlego/m48/keymaps/default/keymap.c
+++ b/keyboards/mlego/m48/keymaps/default/keymap.c
@@ -106,10 +106,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `-----------------------------------------------------------------------------------'
*/
[_ADJ] = LAYOUT_ortho_4x12(
- _______, QK_BOOT, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL ,
- _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, _______, _______, _______, _______, _______,
- _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+ _______, QK_BOOT, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL,
+ _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, _______, _______, _______, _______, _______,
+ _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
};
diff --git a/keyboards/mschwingen/modelm/modelm.c b/keyboards/mschwingen/modelm/modelm.c
index 7dcd4ac024..0ff58f4be3 100644
--- a/keyboards/mschwingen/modelm/modelm.c
+++ b/keyboards/mschwingen/modelm/modelm.c
@@ -163,8 +163,8 @@ void update_layer_leds(void) {
static uint8_t old_layer = 255;
static uint8_t old_default_layer = 255;
- layer = biton32(layer_state);
- default_layer = biton32(default_layer_state);
+ layer = get_highest_layer(layer_state);
+ default_layer = get_highest_layer(default_layer_state);
if (isRecording && timer_elapsed(blink_cycle_timer) > 150) {
blink_state = !blink_state;
diff --git a/keyboards/mwstudio/mw65_rgb/keymaps/via/keymap.c b/keyboards/mwstudio/mw65_rgb/keymaps/via/keymap.c
index 78a17233e3..ddcd3f6642 100644
--- a/keyboards/mwstudio/mw65_rgb/keymaps/via/keymap.c
+++ b/keyboards/mwstudio/mw65_rgb/keymaps/via/keymap.c
@@ -95,9 +95,9 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
bool encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) {
if (clockwise) {
- tap_code(dynamic_keymap_get_keycode(biton32(layer_state), 4, 3));
+ tap_code(dynamic_keymap_get_keycode(get_highest_layer(layer_state), 4, 3));
} else {
- tap_code(dynamic_keymap_get_keycode(biton32(layer_state), 4, 4));
+ tap_code(dynamic_keymap_get_keycode(get_highest_layer(layer_state), 4, 4));
}
}
return true;
diff --git a/keyboards/pearl/keymaps/cijanzen/keymap.c b/keyboards/pearl/keymaps/cijanzen/keymap.c
index 896e157fd6..5a3f1eb1cd 100644
--- a/keyboards/pearl/keymaps/cijanzen/keymap.c
+++ b/keyboards/pearl/keymaps/cijanzen/keymap.c
@@ -46,7 +46,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/**
* Status LED layer indicators courtesy of jetpacktuxedo's firmware
*/
-uint32_t layer_state_set_kb(uint32_t state)
+layer_state_t layer_state_set_kb(layer_state_t state)
{
if (state & (1<<1)) { // if we are on layer 1
PORTD |= (1 << PD0); // light num lock led
diff --git a/keyboards/pearl/keymaps/jetpacktuxedo/keymap.c b/keyboards/pearl/keymaps/jetpacktuxedo/keymap.c
index 759c6fdc7d..4fd35f63ce 100644
--- a/keyboards/pearl/keymaps/jetpacktuxedo/keymap.c
+++ b/keyboards/pearl/keymaps/jetpacktuxedo/keymap.c
@@ -27,7 +27,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
};
-uint32_t layer_state_set_kb(uint32_t state) {
+layer_state_t layer_state_set_kb(layer_state_t state) {
// if we are on layer 1
if (state & (1<<1)){
// light num lock led
diff --git a/keyboards/pearl/keymaps/phil/keymap.c b/keyboards/pearl/keymaps/phil/keymap.c
index 56326d423f..492c4cb0c5 100755
--- a/keyboards/pearl/keymaps/phil/keymap.c
+++ b/keyboards/pearl/keymaps/phil/keymap.c
@@ -64,7 +64,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
};
-uint32_t layer_state_set_kb(uint32_t state) {
+layer_state_t layer_state_set_kb(layer_state_t state) {
if (state & (1<<QWERTY)){
PORTD &= ~(1 << PD0);
} else {
diff --git a/keyboards/pearl/keymaps/rask/keymap.c b/keyboards/pearl/keymaps/rask/keymap.c
index bafb2b9738..30c8b6344f 100644
--- a/keyboards/pearl/keymaps/rask/keymap.c
+++ b/keyboards/pearl/keymaps/rask/keymap.c
@@ -43,7 +43,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/**
* Status LED layer indicators courtesy of jetpacktuxedo's firmware
*/
-uint32_t layer_state_set_kb(uint32_t state)
+layer_state_t layer_state_set_kb(layer_state_t state)
{
// if we are on layer 1
if (state & (1<<1)){
diff --git a/keyboards/percent/canoe/keymaps/dhertz/keymap.c b/keyboards/percent/canoe/keymaps/dhertz/keymap.c
index 7e8170aefc..7d855e8fa7 100644
--- a/keyboards/percent/canoe/keymaps/dhertz/keymap.c
+++ b/keyboards/percent/canoe/keymaps/dhertz/keymap.c
@@ -49,8 +49,8 @@ void keyboard_post_init_user(void) {
rgblight_sethsv_teal();
}
-uint32_t layer_state_set_keymap(uint32_t state) {
- switch (biton32(state)) {
+layer_state_t layer_state_set_keymap(layer_state_t state) {
+ switch (get_highest_layer(state)) {
case 1:
rgblight_sethsv_noeeprom_magenta();
break;
diff --git a/keyboards/phoenix/phoenix.c b/keyboards/phoenix/phoenix.c
index a8e9a42a04..706a65b4de 100644
--- a/keyboards/phoenix/phoenix.c
+++ b/keyboards/phoenix/phoenix.c
@@ -74,7 +74,7 @@ void manipulate_led(uint32_t led, bool on) {
}
-layer_state_t layer_state_set_kb(uint32_t state) {
+layer_state_t layer_state_set_kb(layer_state_t state) {
state = layer_state_set_user(state);
uint8_t layer = get_highest_layer(state);
diff --git a/keyboards/planck/keymaps/ariccb/config.h b/keyboards/planck/keymaps/ariccb/config.h
index 322aa9277f..464a8cd5db 100644
--- a/keyboards/planck/keymaps/ariccb/config.h
+++ b/keyboards/planck/keymaps/ariccb/config.h
@@ -40,6 +40,7 @@
//#define MIDI_ADVANCED
#define TAPPING_TERM 150
+#define TAPPING_TERM_PER_KEY
#define IGNORE_MOD_TAP_INTERRUPT
// #define IGNORE_MOD_TAP_INTERRUPT
// #define HOLD_ON_OTHER_KEY_PRESS
diff --git a/keyboards/planck/keymaps/ariccb/keymap.c b/keyboards/planck/keymaps/ariccb/keymap.c
index c0b4e490fa..33d0a26273 100644
--- a/keyboards/planck/keymaps/ariccb/keymap.c
+++ b/keyboards/planck/keymaps/ariccb/keymap.c
@@ -379,9 +379,18 @@ void usl_reset(qk_tap_dance_state_t *state, void *user_data) {
// Associate our tap dance key with its functionality
qk_tap_dance_action_t tap_dance_actions[] = {
- [UNDS_LOWER] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, usl_finished, usl_reset, 175)
+ [UNDS_LOWER] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, usl_finished, usl_reset)
};
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case TD(UNDS_LOWER):
+ return 175;
+ default:
+ return TAPPING_TERM;
+ }
+}
+
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (!process_select_word(keycode, record, SELWORD)) { return false; }
if (!process_caps_word(keycode, record)) { return false; }
@@ -661,4 +670,4 @@ void process_combo_event(uint16_t combo_index, bool pressed) {
}
break;
}
-} \ No newline at end of file
+}
diff --git a/keyboards/planck/keymaps/aviator/keymap.c b/keyboards/planck/keymaps/aviator/keymap.c
index 8fe66b3781..7ff410c767 100644
--- a/keyboards/planck/keymaps/aviator/keymap.c
+++ b/keyboards/planck/keymaps/aviator/keymap.c
@@ -142,7 +142,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
case LOWER:
if (record->event.pressed) {
layer_on(_LOWER);
- uint8_t default_layer = biton32(default_layer_state);
+ uint8_t default_layer = get_highest_layer(default_layer_state);
if (default_layer == _QWERTY) {
#ifdef BACKLIGHT_BREATHING
breathing_enable();
@@ -151,7 +151,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
update_tri_layer(_LOWER, _RAISE, _ADJUST);
} else {
layer_off(_LOWER);
- uint8_t default_layer = biton32(default_layer_state);
+ uint8_t default_layer = get_highest_layer(default_layer_state);
if (default_layer == _QWERTY) {
#ifdef BACKLIGHT_BREATHING
breathing_self_disable();
@@ -164,7 +164,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
case RAISE:
if (record->event.pressed) {
layer_on(_RAISE);
- uint8_t default_layer = biton32(default_layer_state);
+ uint8_t default_layer = get_highest_layer(default_layer_state);
if (default_layer == _QWERTY) {
#ifdef BACKLIGHT_BREATHING
breathing_enable();
@@ -173,7 +173,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
update_tri_layer(_LOWER, _RAISE, _ADJUST);
} else {
layer_off(_RAISE);
- uint8_t default_layer = biton32(default_layer_state);
+ uint8_t default_layer = get_highest_layer(default_layer_state);
if (default_layer == _QWERTY) {
#ifdef BACKLIGHT_BREATHING
breathing_self_disable();
diff --git a/keyboards/planck/keymaps/charlesrocket/keymap.c b/keyboards/planck/keymaps/charlesrocket/keymap.c
index cec3f0186a..bfe61294af 100644
--- a/keyboards/planck/keymaps/charlesrocket/keymap.c
+++ b/keyboards/planck/keymaps/charlesrocket/keymap.c
@@ -101,7 +101,7 @@ void set_layer_color(int layer) {
void rgb_matrix_indicators_user(void) {
if (g_suspend_state || keyboard_config.disable_layer_led) { return; }
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case 0:
set_layer_color(0);
break;
diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c
index 3453d41746..8041e0bada 100644
--- a/keyboards/planck/keymaps/default/keymap.c
+++ b/keyboards/planck/keymaps/default/keymap.c
@@ -165,7 +165,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_ADJUST] = LAYOUT_planck_grid(
_______, QK_BOOT, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL ,
_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______,
- _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______,
+ _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
diff --git a/keyboards/planck/keymaps/grahampheath/keymap.c b/keyboards/planck/keymaps/grahampheath/keymap.c
index babe67c442..eb5401eabd 100644
--- a/keyboards/planck/keymaps/grahampheath/keymap.c
+++ b/keyboards/planck/keymaps/grahampheath/keymap.c
@@ -231,7 +231,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
bool has_layer_changed = true;
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
static uint8_t old_layer = 0;
if (old_layer != layer) {
diff --git a/keyboards/planck/keymaps/oryx/keymap.c b/keyboards/planck/keymaps/oryx/keymap.c
index 0368c98420..fae5a94713 100644
--- a/keyboards/planck/keymaps/oryx/keymap.c
+++ b/keyboards/planck/keymaps/oryx/keymap.c
@@ -94,7 +94,7 @@ void rgb_matrix_indicators_user(void) {
if (keyboard_config.disable_layer_led) {
return;
}
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case 1:
set_layer_color(0);
break;
diff --git a/keyboards/planck/keymaps/roguepullrequest/rules.mk b/keyboards/planck/keymaps/roguepullrequest/rules.mk
index 9394c96e5b..5eb053e886 100644
--- a/keyboards/planck/keymaps/roguepullrequest/rules.mk
+++ b/keyboards/planck/keymaps/roguepullrequest/rules.mk
@@ -1,4 +1,3 @@
AUDIO_ENABLE = yes
COMMAND_ENABLE = no
-TERMINAL_ENABLE = no
TAP_DANCE_ENABLE = yes
diff --git a/keyboards/planck/keymaps/rootiest/config.h b/keyboards/planck/keymaps/rootiest/config.h
index fc1fc81761..5bb5a73a29 100644
--- a/keyboards/planck/keymaps/rootiest/config.h
+++ b/keyboards/planck/keymaps/rootiest/config.h
@@ -87,6 +87,7 @@
/*
* TAP-DANCE options
*/
+#define TAPPING_TERM_PER_KEY // Control Tap-Dance time individually by key
#define TAPPING_TERM 250 // Default time allowed before resetting a Tap-Dance combo
#define ONESHOT_TAP_TOGGLE 5 /* Tapping this number of times holds the key until tapped once again. */
#define ONESHOT_TIMEOUT 5000 /* Time (in ms) before the one shot key is released */
diff --git a/keyboards/planck/keymaps/rootiest/keymap.c b/keyboards/planck/keymaps/rootiest/keymap.c
index 634bf2829e..c289c50e5b 100644
--- a/keyboards/planck/keymaps/rootiest/keymap.c
+++ b/keyboards/planck/keymaps/rootiest/keymap.c
@@ -502,7 +502,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
} else {
if (index == 0) { /* First encoder */
uint16_t held_keycode_timer = timer_read();
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case 0: // Base Layer
if ((get_mods() & MOD_MASK_GUI)) { // GUI-ed
if (clockwise) {
@@ -1656,13 +1656,26 @@ void sml_reset(qk_tap_dance_state_t* state, void* user_data) { sml_state.state =
// Tap Dance definitions
qk_tap_dance_action_t tap_dance_actions[] = {
// Tap once for °, twice for ℉, thrice for ℃
- [TD_DEG_DEGF] = ACTION_TAP_DANCE_FN(send_degree_symbol), //
- [TD_LSHFT_CAPS] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, scap_finished, scap_reset, 200), //
- [TD_LCTL_STICKY] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, slctl_finished, slctl_reset, 200), //
- [TD_LALT_STICKY] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, slalt_finished, slalt_reset, 200), //
- [TD_SMILEY] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, sml_finished, sml_reset, 500),
+ [TD_DEG_DEGF] = ACTION_TAP_DANCE_FN(send_degree_symbol), //
+ [TD_LSHFT_CAPS] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, scap_finished, scap_reset), //
+ [TD_LCTL_STICKY] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, slctl_finished, slctl_reset), //
+ [TD_LALT_STICKY] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, slalt_finished, slalt_reset), //
+ [TD_SMILEY] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, sml_finished, sml_reset),
};
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case TD(TD_LSHFT_CAPS):
+ case TD(TD_LCTL_STICKY):
+ case TD(TD_LALT_STICKY):
+ return 200;
+ case TD(TD_SMILEY):
+ return 500;
+ default:
+ return TAPPING_TERM;
+ }
+}
+
// Dip-Switch controls
void dip_switch_update_user(uint8_t index, bool active) {
switch (index) {
diff --git a/keyboards/planck/keymaps/rootiest/rules.mk b/keyboards/planck/keymaps/rootiest/rules.mk
index b669d8bb7d..ca0f90b6e9 100644
--- a/keyboards/planck/keymaps/rootiest/rules.mk
+++ b/keyboards/planck/keymaps/rootiest/rules.mk
@@ -20,8 +20,5 @@ KEY_LOCK_ENABLE = yes # Enables using lock key to maintain holds
# SWAP_HANDS_ENABLE = yes # Enables the swap hands function
# DEBOUNCE_TYPE = sym_eager_pk # Change debounce algorithm
-# NOTE: The following requires a lot of memory to include
-TERMINAL_ENABLE = yes # Enables a command-line-like interface designed to communicate through a text editor with keystrokes
-
# NOTE: The following is not yet available in main qmk branch
KEY_OVERRIDE_ENABLE = yes # Allows overiding modifier combos (change Shift+1 without affecting 1 or Shift's normal operation)
diff --git a/keyboards/planck/keymaps/synth_sample/keymap.c b/keyboards/planck/keymaps/synth_sample/keymap.c
index 0a57b7ce9a..124c01cb05 100644
--- a/keyboards/planck/keymaps/synth_sample/keymap.c
+++ b/keyboards/planck/keymaps/synth_sample/keymap.c
@@ -160,10 +160,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `-----------------------------------------------------------------------------------'
*/
[_ADJUST] = LAYOUT_planck_grid(
- _______, RESET, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL ,
- _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______,
- _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+ _______, RESET, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL ,
+ _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______,
+ _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
};
diff --git a/keyboards/planck/keymaps/synth_wavetable/keymap.c b/keyboards/planck/keymaps/synth_wavetable/keymap.c
index d413d63896..a5c5491ebd 100644
--- a/keyboards/planck/keymaps/synth_wavetable/keymap.c
+++ b/keyboards/planck/keymaps/synth_wavetable/keymap.c
@@ -160,10 +160,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `-----------------------------------------------------------------------------------'
*/
[_ADJUST] = LAYOUT_planck_grid(
- _______, RESET, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL ,
- _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______,
- _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______,
- _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
+ _______, RESET, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL ,
+ _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______,
+ _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
};
diff --git a/keyboards/planck/keymaps/tom/keymap.c b/keyboards/planck/keymaps/tom/keymap.c
index 66beaf33b7..d888fb7b05 100644
--- a/keyboards/planck/keymaps/tom/keymap.c
+++ b/keyboards/planck/keymaps/tom/keymap.c
@@ -228,7 +228,7 @@ bool music_mask_user(uint16_t keycode) {
void rgb_matrix_indicators_user(void) {
#ifdef RGB_MATRIX_ENABLE
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _RAISE:
for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
if (HAS_FLAGS(g_led_config.flags[i], LED_FLAG_MODIFIER)) {
diff --git a/keyboards/planck/keymaps/tylerwince/keymap.c b/keyboards/planck/keymaps/tylerwince/keymap.c
index 5cbc47b2fb..b4c0f9af52 100644
--- a/keyboards/planck/keymaps/tylerwince/keymap.c
+++ b/keyboards/planck/keymaps/tylerwince/keymap.c
@@ -168,7 +168,7 @@ void set_layer_color(int layer) {
void rgb_matrix_indicators_user(void) {
if (g_suspend_state || disable_layer_color) { return; }
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case 0:
set_layer_color(0);
break;
@@ -276,7 +276,7 @@ bool music_mask_user(uint16_t keycode) {
layer_state_t layer_state_set_user(layer_state_t state) {
palClearPad(GPIOB, 8);
palClearPad(GPIOB, 9);
- uint8_t layer = biton32(state);
+ uint8_t layer = get_highest_layer(state);
switch (layer) {
case _LOWER:
palSetPad(GPIOB, 9);
diff --git a/keyboards/ploopyco/mouse/keymaps/drashna/config.h b/keyboards/ploopyco/mouse/keymaps/drashna/config.h
index 9aa9a40769..1dc1b7695f 100644
--- a/keyboards/ploopyco/mouse/keymaps/drashna/config.h
+++ b/keyboards/ploopyco/mouse/keymaps/drashna/config.h
@@ -28,4 +28,4 @@
#define RGBLIGHT_EFFECT_TWINKLE
#define RGBLIGHT_SLEEP
-#define MOUSE_EXT_REPORT
+#define MOUSE_EXTENDED_REPORT
diff --git a/keyboards/preonic/keymaps/default/keymap.c b/keyboards/preonic/keymaps/default/keymap.c
index ef7614393d..c1faf464d6 100644
--- a/keyboards/preonic/keymaps/default/keymap.c
+++ b/keyboards/preonic/keymaps/default/keymap.c
@@ -157,7 +157,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[_ADJUST] = LAYOUT_preonic_grid(
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
- _______, QK_BOOT, DEBUG, _______, _______, _______, _______, TERM_ON, TERM_OFF,_______, _______, KC_DEL,
+ _______, QK_BOOT, DEBUG, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL,
_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______,
_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
diff --git a/keyboards/preonic/keymaps/dudeofawesome/keymap.c b/keyboards/preonic/keymaps/dudeofawesome/keymap.c
index 2d2a252b23..812bf35a20 100644
--- a/keyboards/preonic/keymaps/dudeofawesome/keymap.c
+++ b/keyboards/preonic/keymaps/dudeofawesome/keymap.c
@@ -275,7 +275,7 @@ bool numpadActive = false;
float tone_numpad_on[][2] = SONG(NUMPAD_ON_SOUND);
void matrix_scan_user (void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _NUMPAD:
diff --git a/keyboards/preonic/keymaps/senseored/keymap.c b/keyboards/preonic/keymaps/senseored/keymap.c
index e152507835..0f896700e6 100644
--- a/keyboards/preonic/keymaps/senseored/keymap.c
+++ b/keyboards/preonic/keymaps/senseored/keymap.c
@@ -367,7 +367,7 @@ bool dip_switch_update_user(uint8_t index, bool active) {
layer_state_t layer_state_set_user(layer_state_t state) {
// if(rgblight_get_mode() == 1) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _QWERTY:
if(bnumlock) {
tap_code(KC_NLCK);
diff --git a/keyboards/primekb/prime_e/keymaps/via/keymap.c b/keyboards/primekb/prime_e/keymaps/via/keymap.c
index 195f845cc2..2d1d003d51 100644
--- a/keyboards/primekb/prime_e/keymaps/via/keymap.c
+++ b/keyboards/primekb/prime_e/keymaps/via/keymap.c
@@ -108,7 +108,7 @@ void led_set_user(uint8_t usb_led) {
//function for layer indicator LED
layer_state_t layer_state_set_user(layer_state_t state)
{
- if (biton32(state) == 1) {
+ if (get_highest_layer(state) == 1) {
writePinHigh(B3);
} else {
writePinLow(B3);
diff --git a/keyboards/redox_w/keymaps/italian/keymap.c b/keyboards/redox_w/keymaps/italian/keymap.c
index e67742c6a1..b4c815e4f5 100644
--- a/keyboards/redox_w/keymaps/italian/keymap.c
+++ b/keyboards/redox_w/keymaps/italian/keymap.c
@@ -53,7 +53,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
//├────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┠┌────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
KC_LSFT ,KC_Z ,KC_X ,KC_C ,KC_V ,KC_B ,KC_ADPU ,KC_PGDN , KC_HOME ,KC_ADEN ,KC_N ,KC_M ,KC_COMM ,KC_DOT ,IT_UGRV ,IT_SHSL ,
//├────────┼────────┼────────┼────────┼────┬───┴────┬───┼────────┼────────┤ ├────────┼────────┼───┬────┴───┬────┼────────┼────────┼────────┼────────┤
- GUI_LESS,KC_PPLS ,KC_PMNS ,KC_ALAS , KC_CTPL , KC_BSPC ,KC_DEL , KC_ENT ,KC_SPC , ALT_IACC, KC_LEFT ,KC_DOWN ,KC_UP ,KC_RGHT
+ GUI_LESS,KC_PPLS ,KC_PMNS ,KC_ALAS , KC_CTPL , KC_BSPC ,KC_DEL , KC_ENT ,KC_SPC , ALT_IACC, KC_LEFT ,KC_DOWN ,KC_UP ,KC_RGHT
//└────────┴────────┴────────┴────────┘ └────────┘ └────────┴────────┘ └────────┴────────┘ └────────┘ └────────┴────────┴────────┴────────┘
),
@@ -67,7 +67,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
//├────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┠┌────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
_______ ,IT_PERC ,IT_CIRC ,IT_LPRN ,IT_RPRN ,IT_TILD ,_______ ,_______ , _______ ,_______ ,XXXXXXX ,KC_KP_1 ,KC_KP_2 ,KC_KP_3 ,XXXXXXX ,XXXXXXX ,
//├────────┼────────┼────────┼────────┼────┬───┴────┬───┼────────┼────────┤ ├────────┼────────┼───┬────┴───┬────┼────────┼────────┼────────┼────────┤
- _______ ,_______ ,_______ ,_______ , _______ , _______ ,_______ , _______ ,_______ , KC_KP_0 , KC_KP_0 ,KC_PDOT ,XXXXXXX ,XXXXXXX
+ _______ ,_______ ,_______ ,_______ , _______ , _______ ,_______ , _______ ,_______ , KC_KP_0 , KC_KP_0 ,KC_PDOT ,XXXXXXX ,XXXXXXX
//└────────┴────────┴────────┴────────┘ └────────┘ └────────┴────────┘ └────────┴────────┘ └────────┘ └────────┴────────┴────────┴────────┘
),
@@ -81,7 +81,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
//├────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┠┌────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,_______ ,_______ , _______ ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,
//├────────┼────────┼────────┼────────┼────┬───┴────┬───┼────────┼────────┤ ├────────┼────────┼───┬────┴───┬────┼────────┼────────┼────────┼────────┤
- XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , KC_BTN1 , KC_BTN2 ,_______ , _______ ,_______ , XXXXXXX , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX
+ XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , KC_BTN1 , KC_BTN2 ,_______ , _______ ,_______ , XXXXXXX , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX
//└────────┴────────┴────────┴────────┘ └────────┘ └────────┴────────┘ └────────┴────────┘ └────────┘ └────────┴────────┴────────┴────────┘
),
@@ -95,14 +95,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
//├────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┠┌────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,_______ ,XXXXXXX , XXXXXXX ,_______ ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX ,
//├────────┼────────┼────────┼────────┼────┬───┴────┬───┼────────┼────────┤ ├────────┼────────┼───┬────┴───┬────┼────────┼────────┼────────┼────────┤
- XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , XXXXXXX , XXXXXXX ,XXXXXXX , XXXXXXX ,XXXXXXX , XXXXXXX , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX
+ XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX , XXXXXXX , XXXXXXX ,XXXXXXX , XXXXXXX ,XXXXXXX , XXXXXXX , XXXXXXX ,XXXXXXX ,XXXXXXX ,XXXXXXX
//└────────┴────────┴────────┴────────┘ └────────┘ └────────┴────────┘ └────────┴────────┘ └────────┘ └────────┴────────┴────────┴────────┘
)
};
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case _QWERTY:
@@ -121,5 +121,3 @@ void matrix_scan_user(void) {
break;
}
};
-
-
diff --git a/keyboards/redscarf_i/redscarf_i.c b/keyboards/redscarf_i/redscarf_i.c
index a8a685b13b..039e20664d 100644
--- a/keyboards/redscarf_i/redscarf_i.c
+++ b/keyboards/redscarf_i/redscarf_i.c
@@ -36,7 +36,7 @@ bool led_update_kb(led_t led_state) {
}
layer_state_t layer_state_set_kb(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case 1:
writePinHigh(F6);
writePinLow(F5);
diff --git a/keyboards/rgbkb/pan/keymaps/default/keymap.c b/keyboards/rgbkb/pan/keymaps/default/keymap.c
index dbc127616a..dcafeec765 100644
--- a/keyboards/rgbkb/pan/keymaps/default/keymap.c
+++ b/keyboards/rgbkb/pan/keymaps/default/keymap.c
@@ -75,7 +75,7 @@ bool oled_task_user(void) {
// Host Keyboard Layer Status
oled_write_P(PSTR("RGBKB Pan\n"), false);
oled_write_P(PSTR("Layer: "), false);
- uint8_t layer = layer_state ? biton(layer_state) : biton32(default_layer_state);
+ uint8_t layer = get_highest_layer(layer_state|default_layer_state);
switch (layer) {
case _QWERTY:
oled_write_P(PSTR("Default\n"), false);
diff --git a/keyboards/rgbkb/sol/keymaps/default/keymap.c b/keyboards/rgbkb/sol/keymaps/default/keymap.c
index c82259f5ee..1ce18bc1ab 100644
--- a/keyboards/rgbkb/sol/keymaps/default/keymap.c
+++ b/keyboards/rgbkb/sol/keymaps/default/keymap.c
@@ -233,7 +233,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
} else
#endif
{
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
uint16_t keycode = pgm_read_word(&encoders[layer][index][clockwise]);
while (keycode == KC_TRANSPARENT && layer > 0)
{
@@ -325,7 +325,7 @@ static void render_status(void) {
// Define layers here
oled_write_P(PSTR("Layer"), false);
- uint8_t layer = layer_state ? biton(layer_state) : biton32(default_layer_state);
+ uint8_t layer = get_highest_layer(layer_state|default_layer_state);
switch (layer) {
case _QWERTY:
oled_write_P(PSTR("BASE "), false);
diff --git a/keyboards/rgbkb/sol/keymaps/xyverz/keymap.c b/keyboards/rgbkb/sol/keymaps/xyverz/keymap.c
index bdcfbb1b93..bc0884c8e4 100644
--- a/keyboards/rgbkb/sol/keymaps/xyverz/keymap.c
+++ b/keyboards/rgbkb/sol/keymaps/xyverz/keymap.c
@@ -263,7 +263,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
} else
#endif
{
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
uint16_t keycode = encoders[layer][index][clockwise];
while (keycode == KC_TRANSPARENT && layer > 0)
{
@@ -306,7 +306,7 @@ static void render_status(void) {
// Define layers here
oled_write_P(PSTR(" Layer-----"), false);
- uint8_t layer = layer_state ? biton(layer_state) : biton32(default_layer_state);
+ uint8_t layer = layer_state ? get_highest_layer(layer_state) : get_highest_layer(default_layer_state);
switch (layer) {
case _DVORAK:
oled_write_P(PSTR("DVRAK"), false);
diff --git a/keyboards/rgbkb/zen/rev2/rev2.c b/keyboards/rgbkb/zen/rev2/rev2.c
index 5461890272..70e5531673 100644
--- a/keyboards/rgbkb/zen/rev2/rev2.c
+++ b/keyboards/rgbkb/zen/rev2/rev2.c
@@ -37,7 +37,7 @@ void render_status(void) {
// Define layers here, Have not worked out how to have text displayed for each layer. Copy down the number you see and add a case for it below
oled_set_cursor(0, 3); // Line 3
oled_write_P(PSTR("Layer"), false); // Line 4
- oled_write_P(layer_name_user(biton32(layer_state)), false);
+ oled_write_P(layer_name_user(get_highest_layer(layer_state)), false);
// Host Keyboard LED Status
uint8_t led_usb_state = host_keyboard_leds();
diff --git a/keyboards/rgbkb/zygomorph/keymaps/default_oled/keymap.c b/keyboards/rgbkb/zygomorph/keymaps/default_oled/keymap.c
index 48bd1a33f7..f4d5c82a71 100644
--- a/keyboards/rgbkb/zygomorph/keymaps/default_oled/keymap.c
+++ b/keyboards/rgbkb/zygomorph/keymaps/default_oled/keymap.c
@@ -198,7 +198,7 @@ static void render_status(void) {
// Define layers here, Have not worked out how to have text displayed for each layer. Copy down the number you see and add a case for it below
oled_write_P(PSTR("Layer: "), false);
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _QWERTY:
oled_write_ln_P(PSTR("QWERTY"), false);
break;
diff --git a/keyboards/salicylic_acid3/7skb/keymaps/salicylic/keymap.c b/keyboards/salicylic_acid3/7skb/keymaps/salicylic/keymap.c
index 4e1f2acd05..7221f8c612 100644
--- a/keyboards/salicylic_acid3/7skb/keymaps/salicylic/keymap.c
+++ b/keyboards/salicylic_acid3/7skb/keymaps/salicylic/keymap.c
@@ -32,8 +32,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESFL] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _FLOCK),
- [TD_ESQW] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESFL] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _FLOCK),
+ [TD_ESQW] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/salicylic_acid3/7splus/keymaps/salicylic/keymap.c b/keyboards/salicylic_acid3/7splus/keymaps/salicylic/keymap.c
index 06d7972a2e..bea5978c50 100644
--- a/keyboards/salicylic_acid3/7splus/keymaps/salicylic/keymap.c
+++ b/keyboards/salicylic_acid3/7splus/keymaps/salicylic/keymap.c
@@ -39,8 +39,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESMS] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _MOUSE),
- [TD_ESAR] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESMS] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _MOUSE),
+ [TD_ESAR] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/salicylic_acid3/jisplit89/keymaps/salicylic/keymap.c b/keyboards/salicylic_acid3/jisplit89/keymaps/salicylic/keymap.c
index 4e8addf6b7..eba01d4d65 100644
--- a/keyboards/salicylic_acid3/jisplit89/keymaps/salicylic/keymap.c
+++ b/keyboards/salicylic_acid3/jisplit89/keymaps/salicylic/keymap.c
@@ -39,8 +39,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESMS] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _MOUSE),
- [TD_ESAR] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESMS] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _MOUSE),
+ [TD_ESAR] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/salicylic_acid3/naked60/keymaps/salicylic/keymap.c b/keyboards/salicylic_acid3/naked60/keymaps/salicylic/keymap.c
index 8a2dbf051f..b70e68da54 100644
--- a/keyboards/salicylic_acid3/naked60/keymaps/salicylic/keymap.c
+++ b/keyboards/salicylic_acid3/naked60/keymaps/salicylic/keymap.c
@@ -23,8 +23,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESFL] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _FLOCK),
- [TD_ESQW] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESFL] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _FLOCK),
+ [TD_ESQW] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_nafuda/keymap.c b/keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_nafuda/keymap.c
index 4201d79a2e..c43803be35 100644
--- a/keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_nafuda/keymap.c
+++ b/keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_nafuda/keymap.c
@@ -34,8 +34,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESFL] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _FLOCK),
- [TD_ESQW] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESFL] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _FLOCK),
+ [TD_ESQW] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_setta21/keymap.c b/keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_setta21/keymap.c
index 23786da915..6dd2ef8863 100644
--- a/keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_setta21/keymap.c
+++ b/keyboards/salicylic_acid3/naked60/keymaps/salicylic_with_setta21/keymap.c
@@ -32,8 +32,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESFL] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _FLOCK),
- [TD_ESQW] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESFL] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _FLOCK),
+ [TD_ESQW] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/salicylic_acid3/naked64/keymaps/salicylic/keymap.c b/keyboards/salicylic_acid3/naked64/keymaps/salicylic/keymap.c
index db46075c8f..ae7843341a 100644
--- a/keyboards/salicylic_acid3/naked64/keymaps/salicylic/keymap.c
+++ b/keyboards/salicylic_acid3/naked64/keymaps/salicylic/keymap.c
@@ -33,8 +33,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESFL] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _FLOCK),
- [TD_ESQW] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESFL] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _FLOCK),
+ [TD_ESQW] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
diff --git a/keyboards/salicylic_acid3/naked64/keymaps/salicylic_with_setta21/keymap.c b/keyboards/salicylic_acid3/naked64/keymaps/salicylic_with_setta21/keymap.c
index c91716cdd4..6e2dd0886f 100644
--- a/keyboards/salicylic_acid3/naked64/keymaps/salicylic_with_setta21/keymap.c
+++ b/keyboards/salicylic_acid3/naked64/keymaps/salicylic_with_setta21/keymap.c
@@ -38,8 +38,8 @@ enum tapdances{
};
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_ESFL] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _FLOCK),
- [TD_ESQW] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _QWERTY),
+ [TD_ESFL] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _FLOCK),
+ [TD_ESQW] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _QWERTY),
};
#define LOWER MO(_LOWER)
diff --git a/keyboards/satt/comet46/keymaps/default-rgbled/keymap.c b/keyboards/satt/comet46/keymaps/default-rgbled/keymap.c
index 6c88b70bfe..1e96bd7fbc 100644
--- a/keyboards/satt/comet46/keymaps/default-rgbled/keymap.c
+++ b/keyboards/satt/comet46/keymaps/default-rgbled/keymap.c
@@ -173,7 +173,7 @@ void matrix_init_user(void) {
}
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
uint8_t default_layer = biton32(eeconfig_read_default_layer());
switch (layer) {
case _LOWER:
diff --git a/keyboards/satt/comet46/keymaps/default/keymap.c b/keyboards/satt/comet46/keymaps/default/keymap.c
index cf2c911d4c..bccca0a091 100644
--- a/keyboards/satt/comet46/keymaps/default/keymap.c
+++ b/keyboards/satt/comet46/keymaps/default/keymap.c
@@ -176,8 +176,8 @@ void render_status(struct CharacterMatrix *matrix) {
// Layer state
char layer_str[22];
matrix_write(matrix, "Layer: ");
- uint8_t layer = biton32(layer_state);
- uint8_t default_layer = biton32(eeconfig_read_default_layer());
+ uint8_t layer = get_highest_layer(layer_state);
+ uint8_t default_layer = get_highest_layer(eeconfig_read_default_layer());
switch (layer) {
case _QWERTY:
switch (default_layer) {
diff --git a/keyboards/satt/comet46/keymaps/satt/keymap.c b/keyboards/satt/comet46/keymaps/satt/keymap.c
index cdd094f747..54d1d791d7 100644
--- a/keyboards/satt/comet46/keymaps/satt/keymap.c
+++ b/keyboards/satt/comet46/keymaps/satt/keymap.c
@@ -165,7 +165,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _PSEUDO_US_LOWER:
case _PSEUDO_US_RAISE:
return update_tri_layer_state(state, _PSEUDO_US_RAISE, _PSEUDO_US_LOWER, _ADJUST);
@@ -204,7 +204,7 @@ void render_status(struct CharacterMatrix *matrix) {
// Layer state
char layer_str[22];
matrix_write(matrix, "Layer: ");
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
uint8_t default_layer = biton32(eeconfig_read_default_layer());
switch (layer) {
case _QWERTY:
diff --git a/keyboards/splitkb/kyria/keymaps/j-inc/keymap.c b/keyboards/splitkb/kyria/keymaps/j-inc/keymap.c
index af583a607f..f193c6e00c 100644
--- a/keyboards/splitkb/kyria/keymaps/j-inc/keymap.c
+++ b/keyboards/splitkb/kyria/keymaps/j-inc/keymap.c
@@ -341,7 +341,7 @@ bool oled_task_user(void) {
#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise) {
- switch(biton32(layer_state)){
+ switch(get_highest_layer(layer_state)){
case 1:
if (clockwise) {
tap_code16(C(KC_TAB));
diff --git a/keyboards/splitkb/kyria/keymaps/j-inc/rules.mk b/keyboards/splitkb/kyria/keymaps/j-inc/rules.mk
index 000c995025..ee07f52ff1 100644
--- a/keyboards/splitkb/kyria/keymaps/j-inc/rules.mk
+++ b/keyboards/splitkb/kyria/keymaps/j-inc/rules.mk
@@ -9,7 +9,6 @@ MOUSEKEY_ENABLE = no
TAP_DANCE_ENABLE = no
STENO_ENABLE = no
BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite
-TERMINAL_ENABLE = no
GRAVE_ESC_ENABLE = no
MAGIC_ENABLE = no
SPACE_CADET_ENABLE = no
diff --git a/keyboards/splitkb/kyria/keymaps/ninjonas/oled.c b/keyboards/splitkb/kyria/keymaps/ninjonas/oled.c
index 813328aa0c..d0f2a1b6cd 100644
--- a/keyboards/splitkb/kyria/keymaps/ninjonas/oled.c
+++ b/keyboards/splitkb/kyria/keymaps/ninjonas/oled.c
@@ -111,7 +111,7 @@ void oled_slash_separator(void){
void render_layout_state(void) {
oled_write_P(PSTR("Layout: "), false);
- switch (biton32(default_layer_state)) {
+ switch (get_highest_layer(default_layer_state)) {
case _COLEMAK:
oled_write_P(PSTR("Colemak"), false);
break;
diff --git a/keyboards/splitkb/kyria/keymaps/thomasbaart/keymap.c b/keyboards/splitkb/kyria/keymaps/thomasbaart/keymap.c
index 0a4f1887c3..3cd9df27fb 100644
--- a/keyboards/splitkb/kyria/keymaps/thomasbaart/keymap.c
+++ b/keyboards/splitkb/kyria/keymaps/thomasbaart/keymap.c
@@ -311,7 +311,7 @@ bool oled_task_user(void) {
#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case QWERTY:
// History scrubbing. For Adobe products, hold shift while moving
// backward to go forward instead.
@@ -336,7 +336,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
break;
}
} else if (index == 1) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case QWERTY:
// Scrolling with PageUp and PgDn.
if (clockwise) {
diff --git a/keyboards/splitography/keymaps/jeandeaual/keymap.c b/keyboards/splitography/keymaps/jeandeaual/keymap.c
index 6679d835f2..87c4159443 100644
--- a/keyboards/splitography/keymaps/jeandeaual/keymap.c
+++ b/keyboards/splitography/keymaps/jeandeaual/keymap.c
@@ -225,7 +225,7 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
}
return false;
case KC_QUOT:
- if ((base_layer != dvorak) || (biton32(layer_state) != _BLUE)) {
+ if ((base_layer != dvorak) || (get_highest_layer(layer_state) != _BLUE)) {
break;
}
if (record->event.pressed) {
diff --git a/keyboards/splitography/keymaps/multi/keymap.c b/keyboards/splitography/keymaps/multi/keymap.c
index af1cc1a801..7d847e40b6 100644
--- a/keyboards/splitography/keymaps/multi/keymap.c
+++ b/keyboards/splitography/keymaps/multi/keymap.c
@@ -331,7 +331,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
return false;
case KC_QUOT:
- if ((base_layer != dvorak) || (biton32(layer_state) != _BLUE)) {
+ if ((base_layer != dvorak) || (get_highest_layer(layer_state) != _BLUE)) {
break;
}
if (record->event.pressed) {
diff --git a/keyboards/tetris/keymaps/default/keymap.c b/keyboards/tetris/keymaps/default/keymap.c
index 1b53ea80b9..9e2a96ffc3 100755
--- a/keyboards/tetris/keymaps/default/keymap.c
+++ b/keyboards/tetris/keymaps/default/keymap.c
@@ -37,7 +37,7 @@ void matrix_init_user(void) {
}
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if (RGB_encoder_dir != 0) {
if (timer_elapsed(RGB_encoder_timer) > 1400) {
@@ -152,7 +152,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t * record) {
bool encoder_update_user(uint8_t index, bool clockwise) {
RGB_encoder_timer = timer_read();
RGB_encoder_timer2 = timer_read();
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if (clockwise) {
RGB_encoder_dir = 1;
} else {
diff --git a/keyboards/thevankeyboards/minivan/keymaps/belak/config.h b/keyboards/thevankeyboards/minivan/keymaps/belak/config.h
index 47d96a29d8..488ffa5418 100644
--- a/keyboards/thevankeyboards/minivan/keymaps/belak/config.h
+++ b/keyboards/thevankeyboards/minivan/keymaps/belak/config.h
@@ -4,5 +4,6 @@
#include "../../config.h"
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
#endif
diff --git a/keyboards/thevankeyboards/minivan/keymaps/belak/keymap.c b/keyboards/thevankeyboards/minivan/keymaps/belak/keymap.c
index 437b1881a4..0ed709747a 100644
--- a/keyboards/thevankeyboards/minivan/keymaps/belak/keymap.c
+++ b/keyboards/thevankeyboards/minivan/keymaps/belak/keymap.c
@@ -22,6 +22,9 @@
#define TD_LCTL TD(BE_TD_CTL)
#define TD_LALT TD(BE_TD_ALT)
+#define ACTION_TAP_DANCE_MOD_TAP(mod) \
+ { .fn = {mod_tap_fn, NULL, mod_reset_fn}, .user_data = (void *)&((uint8_t){mod}), }
+
enum belak_td {
BE_TD_GUI = 0,
BE_TD_CTL,
@@ -32,15 +35,9 @@ void mod_tap_fn(qk_tap_dance_state_t *state, void *user_data);
void mod_reset_fn(qk_tap_dance_state_t *state, void *user_data);
qk_tap_dance_action_t tap_dance_actions[] = {
- [BE_TD_GUI] = ACTION_TAP_DANCE_FN_ADVANCED(mod_tap_fn, NULL, mod_reset_fn),
- [BE_TD_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(mod_tap_fn, NULL, mod_reset_fn),
- [BE_TD_ALT] = ACTION_TAP_DANCE_FN_ADVANCED(mod_tap_fn, NULL, mod_reset_fn),
-};
-
-uint16_t tap_dance_keys[] = {
- [BE_TD_GUI] = KC_LGUI,
- [BE_TD_CTL] = KC_LCTL,
- [BE_TD_ALT] = KC_LALT,
+ [BE_TD_GUI] = ACTION_TAP_DANCE_MOD_TAP(KC_LGUI),
+ [BE_TD_CTL] = ACTION_TAP_DANCE_MOD_TAP(KC_LCTL),
+ [BE_TD_ALT] = ACTION_TAP_DANCE_MOD_TAP(KC_LALT),
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
@@ -74,7 +71,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
void mod_tap_fn(qk_tap_dance_state_t *state, void *user_data) {
switch (state->count) {
case 1:
- register_mods(MOD_BIT(tap_dance_keys[state->keycode - QK_TAP_DANCE]));
+ uint8_t *mod = (uint8_t *)user_data;
+ register_mods(MOD_BIT(*mod));
send_keyboard_report();
break;
case 2:
@@ -90,8 +88,9 @@ void mod_tap_fn(qk_tap_dance_state_t *state, void *user_data) {
}
void mod_reset_fn(qk_tap_dance_state_t *state, void *user_data) {
+ uint8_t *mod = (uint8_t *)user_data;
layer_off(_L1);
layer_off(_L2);
- unregister_mods(MOD_BIT(tap_dance_keys[state->keycode - QK_TAP_DANCE]));
+ unregister_mods(MOD_BIT(*mod));
send_keyboard_report();
}
diff --git a/keyboards/thevankeyboards/minivan/keymaps/halvves/config.h b/keyboards/thevankeyboards/minivan/keymaps/halvves/config.h
index 6be8d217bd..c6404f8ce5 100644
--- a/keyboards/thevankeyboards/minivan/keymaps/halvves/config.h
+++ b/keyboards/thevankeyboards/minivan/keymaps/halvves/config.h
@@ -1,6 +1,7 @@
#pragma once
#define TAPPING_TERM 505
+#define PERMISSIVE_HOLD
#define RETRO_TAPPING
// smooth mousekeys (copied from the ergo ez config)
diff --git a/keyboards/thevankeyboards/roadkit/keymaps/flipphone/keymap.c b/keyboards/thevankeyboards/roadkit/keymaps/flipphone/keymap.c
index b00cf80f5c..a6fa5ed722 100644
--- a/keyboards/thevankeyboards/roadkit/keymaps/flipphone/keymap.c
+++ b/keyboards/thevankeyboards/roadkit/keymaps/flipphone/keymap.c
@@ -147,7 +147,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return false;
}
uint8_t layer;
- layer = biton32(layer_state);
+ layer = get_highest_layer(layer_state);
switch (keycode) {
case FPH_1 ... FPH_9:
diff --git a/keyboards/tzarc/djinn/djinn.c b/keyboards/tzarc/djinn/djinn.c
index 23f59991a9..5e5fe44c67 100644
--- a/keyboards/tzarc/djinn/djinn.c
+++ b/keyboards/tzarc/djinn/djinn.c
@@ -70,7 +70,7 @@ void keyboard_post_init_kb(void) {
wait_ms(150);
// Initialise the LCD
- lcd = qp_ili9341_make_spi_device(320, 240, LCD_CS_PIN, LCD_DC_PIN, LCD_RST_PIN, 4, 3);
+ lcd = qp_ili9341_make_spi_device(320, 240, LCD_CS_PIN, LCD_DC_PIN, LCD_RST_PIN, 4, 0);
qp_init(lcd, QP_ROTATION_0);
// Turn on the LCD and clear the display
diff --git a/keyboards/v60_type_r/keymaps/xtonhasvim/keymap.c b/keyboards/v60_type_r/keymaps/xtonhasvim/keymap.c
index 82a7e52808..8927a8ee0a 100644
--- a/keyboards/v60_type_r/keymaps/xtonhasvim/keymap.c
+++ b/keyboards/v60_type_r/keymaps/xtonhasvim/keymap.c
@@ -104,7 +104,7 @@ void rgbflag(uint8_t r, uint8_t g, uint8_t b) {
}
void set_state_leds(void) {
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _MOVE:
rgbflag(C_BLU);
break;
@@ -192,4 +192,3 @@ void suspend_wakeup_init_user(void)
backlight_set(backlight_config.level);
rgblight_set();
}
-
diff --git a/keyboards/woodkeys/bigseries/1key/keymaps/dudeofawesome/config.h b/keyboards/woodkeys/bigseries/1key/keymaps/dudeofawesome/config.h
index 30b86224c6..131c755d4a 100644
--- a/keyboards/woodkeys/bigseries/1key/keymaps/dudeofawesome/config.h
+++ b/keyboards/woodkeys/bigseries/1key/keymaps/dudeofawesome/config.h
@@ -19,5 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define CONFIG_USER_H
#define TAPPING_TERM 1000
+#define PERMISSIVE_HOLD
#endif
diff --git a/keyboards/work_louder/work_board/keymaps/default/keymap.c b/keyboards/work_louder/work_board/keymaps/default/keymap.c
index 59bb437d9d..cae65ff5c2 100644
--- a/keyboards/work_louder/work_board/keymaps/default/keymap.c
+++ b/keyboards/work_louder/work_board/keymaps/default/keymap.c
@@ -144,9 +144,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `-----------------------------------------------------------------------------------'
*/
[_ADJUST] = LAYOUT(
- _______, QK_BOOT, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL , _______,
- _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______,
- _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______,
+ _______, QK_BOOT, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL , _______,
+ _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______,
+ _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
diff --git a/keyboards/xiudi/xd002/keymaps/tap_dance/config.h b/keyboards/xiudi/xd002/keymaps/tap_dance/config.h
index b86e862d30..1fd93f875f 100644
--- a/keyboards/xiudi/xd002/keymaps/tap_dance/config.h
+++ b/keyboards/xiudi/xd002/keymaps/tap_dance/config.h
@@ -1,3 +1,4 @@
#pragma once
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
diff --git a/keyboards/xiudi/xd60/keymaps/birkir/keymap.c b/keyboards/xiudi/xd60/keymaps/birkir/keymap.c
index fe7cd60662..ab129332c9 100644
--- a/keyboards/xiudi/xd60/keymaps/birkir/keymap.c
+++ b/keyboards/xiudi/xd60/keymaps/birkir/keymap.c
@@ -47,7 +47,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
edit = false;
}
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case 1:
rgblight_mode(1);
rgblight_setrgb(0xD3, 0x7F, 0xED);
diff --git a/keyboards/xiudi/xd60/keymaps/kmontag42/keymap.c b/keyboards/xiudi/xd60/keymaps/kmontag42/keymap.c
index 8e081c6731..d17fc2f35d 100644
--- a/keyboards/xiudi/xd60/keymaps/kmontag42/keymap.c
+++ b/keyboards/xiudi/xd60/keymaps/kmontag42/keymap.c
@@ -25,7 +25,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Loop
void matrix_scan_user(void) {
static uint8_t old_layer = 255;
- uint8_t new_layer = biton32(layer_state);
+ uint8_t new_layer = get_highest_layer(layer_state);
if (old_layer != new_layer) {
switch (new_layer) {
diff --git a/keyboards/xiudi/xd75/keymaps/arpinfidel/keymap.c b/keyboards/xiudi/xd75/keymaps/arpinfidel/keymap.c
index 5f7337d68b..c278df1b21 100644
--- a/keyboards/xiudi/xd75/keymaps/arpinfidel/keymap.c
+++ b/keyboards/xiudi/xd75/keymaps/arpinfidel/keymap.c
@@ -100,7 +100,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Runs whenever there is a layer state change.
layer_state_t layer_state_set_user(layer_state_t state) {
- uint8_t layer = biton32(state);
+ uint8_t layer = get_highest_layer(state);
gp100_led_off();
gp103_led_off();
diff --git a/keyboards/xiudi/xd75/keymaps/cbbrowne/keymap.c b/keyboards/xiudi/xd75/keymaps/cbbrowne/keymap.c
index 1b29686cff..a0295f2f45 100644
--- a/keyboards/xiudi/xd75/keymaps/cbbrowne/keymap.c
+++ b/keyboards/xiudi/xd75/keymaps/cbbrowne/keymap.c
@@ -286,7 +286,7 @@ void matrix_init_user(void) {
}
layer_state_t layer_state_set_user(layer_state_t state) {
- switch(biton32(state)) {
+ switch(get_highest_layer(state)) {
case _QWERTY:
rgblight_sethsv_white();
break;
diff --git a/keyboards/xiudi/xd75/keymaps/kloki/keymap.c b/keyboards/xiudi/xd75/keymaps/kloki/keymap.c
index a630019347..d25a16fbb6 100644
--- a/keyboards/xiudi/xd75/keymaps/kloki/keymap.c
+++ b/keyboards/xiudi/xd75/keymaps/kloki/keymap.c
@@ -70,7 +70,7 @@ bool WINDOWN = false;
bool SHIFTDOWN = false;
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
case 0:
diff --git a/keyboards/xiudi/xd75/keymaps/tdl-jturner/keymap.c b/keyboards/xiudi/xd75/keymaps/tdl-jturner/keymap.c
index b7b98cd4c5..f48eb94214 100644
--- a/keyboards/xiudi/xd75/keymaps/tdl-jturner/keymap.c
+++ b/keyboards/xiudi/xd75/keymaps/tdl-jturner/keymap.c
@@ -180,7 +180,7 @@ void matrix_init_user(void) {
//Set a color based on the layer
layer_state_t layer_state_set_user(layer_state_t state) {
- switch(biton32(state)) {
+ switch(get_highest_layer(state)) {
case _LYFK:
rgblight_setrgb_user_LYFK();
break;
diff --git a/keyboards/zfrontier/big_switch/config.h b/keyboards/zfrontier/big_switch/config.h
index ddec2b2796..99bd790cae 100644
--- a/keyboards/zfrontier/big_switch/config.h
+++ b/keyboards/zfrontier/big_switch/config.h
@@ -51,3 +51,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* long tapping config */
#define TAPPING_TERM 500
+#define PERMISSIVE_HOLD
diff --git a/layouts/community/66_ansi/xyverz/config.h b/layouts/community/66_ansi/xyverz/config.h
index 06e5830af8..37a57dbffd 100644
--- a/layouts/community/66_ansi/xyverz/config.h
+++ b/layouts/community/66_ansi/xyverz/config.h
@@ -1,5 +1,6 @@
#pragma once
#define TAPPING_TERM 600 // ms
+#define PERMISSIVE_HOLD
#undef RGBLIGHT_HUE_STEP
#define RGBLIGHT_HUE_STEP 8
diff --git a/layouts/community/ergodox/ab/keymap.c b/layouts/community/ergodox/ab/keymap.c
index 001123e286..e85d5d528c 100644
--- a/layouts/community/ergodox/ab/keymap.c
+++ b/layouts/community/ergodox/ab/keymap.c
@@ -130,7 +130,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/absenth/keymap.c b/layouts/community/ergodox/absenth/keymap.c
index d84b68f0ef..884167aa31 100644
--- a/layouts/community/ergodox/absenth/keymap.c
+++ b/layouts/community/ergodox/absenth/keymap.c
@@ -157,7 +157,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/adam/config.h b/layouts/community/ergodox/adam/config.h
index 62e82d8b2b..1555ae11fd 100644
--- a/layouts/community/ergodox/adam/config.h
+++ b/layouts/community/ergodox/adam/config.h
@@ -1,5 +1,5 @@
#pragma once
#undef TAPPING_TERM
-#define TAPPING_TERM 300 //At 500 some bad logic takes hold
+#define TAPPING_TERM 300
#define IGNORE_MOD_TAP_INTERRUPT
diff --git a/layouts/community/ergodox/adam/keymap.c b/layouts/community/ergodox/adam/keymap.c
index 50270838aa..9dd611e03e 100644
--- a/layouts/community/ergodox/adam/keymap.c
+++ b/layouts/community/ergodox/adam/keymap.c
@@ -129,7 +129,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
// TODO: Make this relevant to the ErgoDox EZ.
diff --git a/layouts/community/ergodox/adnw_k_o_y/keymap.c b/layouts/community/ergodox/adnw_k_o_y/keymap.c
index 589a9ea873..6aa309c2cc 100644
--- a/layouts/community/ergodox/adnw_k_o_y/keymap.c
+++ b/layouts/community/ergodox/adnw_k_o_y/keymap.c
@@ -139,7 +139,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/alexjj/keymap.c b/layouts/community/ergodox/alexjj/keymap.c
index 64e7c94433..c9adf7af63 100644
--- a/layouts/community/ergodox/alexjj/keymap.c
+++ b/layouts/community/ergodox/alexjj/keymap.c
@@ -206,7 +206,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/andrew_osx/keymap.c b/layouts/community/ergodox/andrew_osx/keymap.c
index 990fea4f45..4f3f6ef0cb 100644
--- a/layouts/community/ergodox/andrew_osx/keymap.c
+++ b/layouts/community/ergodox/andrew_osx/keymap.c
@@ -141,7 +141,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/berfarah/keymap.c b/layouts/community/ergodox/berfarah/keymap.c
index 164d026ef3..7dc09e7543 100644
--- a/layouts/community/ergodox/berfarah/keymap.c
+++ b/layouts/community/ergodox/berfarah/keymap.c
@@ -219,7 +219,7 @@ static inline void mod_layer_with_rgb(keyrecord_t *record, uint8_t layer) {
bf_set_led(layer);
} else {
layer_off(layer);
- uint8_t currentLayer = biton32(layer_state);
+ uint8_t currentLayer = get_highest_layer(layer_state);
bf_set_led(currentLayer);
};
};
@@ -266,7 +266,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_right_led_1_off();
ergodox_right_led_2_off();
diff --git a/layouts/community/ergodox/bryan/keymap.c b/layouts/community/ergodox/bryan/keymap.c
index acae77d5fc..ab301e8922 100644
--- a/layouts/community/ergodox/bryan/keymap.c
+++ b/layouts/community/ergodox/bryan/keymap.c
@@ -200,7 +200,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/choromanski/keymap.c b/layouts/community/ergodox/choromanski/keymap.c
index 8be3c7ea7e..933f13b25f 100644
--- a/layouts/community/ergodox/choromanski/keymap.c
+++ b/layouts/community/ergodox/choromanski/keymap.c
@@ -30,15 +30,15 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
OSL(3), TG(2), TO(5), TO(1), KC_CAPS,
KC_LCTL, KC_LALT,
KC_MUTE,
- KC_BSPC, KC_DEL, KC_LGUI,
+ KC_BSPC, KC_DEL, KC_LGUI,
- KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
+ KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
KC_RPRN, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSLS,
- KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT,
+ KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT,
KC_RBRC, KC_K, KC_M, KC_COMM, ALT_T(KC_DOT), CTL_T(KC_SLSH), KC_RSFT,
- KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, TG(4),
- KC_RALT, KC_RCTL,
- KC_WH_U,
+ KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, TG(4),
+ KC_RALT, KC_RCTL,
+ KC_WH_U,
KC_WH_D, KC_ENT, KC_SPC
),
@@ -106,22 +106,22 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[2] = LAYOUT_ergodox(
KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,
- KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS,
+ KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
),
/* Keymap 3: Symbols
@@ -147,9 +147,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
*/
[3] = LAYOUT_ergodox(
KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6,
- KC_TRNS, KC_PIPE, KC_PLUS, KC_LABK, KC_RABK, KC_HASH, KC_TRNS,
- KC_TRNS, KC_EXLM, KC_MINS, KC_EQL, KC_PERC, KC_AT,
- KC_TRNS, KC_ASTR, KC_AMPR, KC_SLSH, KC_DLR, KC_CIRC, KC_TRNS,
+ KC_TRNS, KC_PIPE, KC_PLUS, KC_LABK, KC_RABK, KC_HASH, KC_TRNS,
+ KC_TRNS, KC_EXLM, KC_MINS, KC_EQL, KC_PERC, KC_AT,
+ KC_TRNS, KC_ASTR, KC_AMPR, KC_SLSH, KC_DLR, KC_CIRC, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
@@ -229,8 +229,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[5] = LAYOUT_ergodox(
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_TRNS,
- KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G,
- KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_MPLY,
+ KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_MPLY,
KC_LCTL, LALT(KC_TAB), TO(0), KC_LALT, KC_SPC,
KC_MPRV, KC_MNXT,
KC_VOLU,
@@ -249,7 +249,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/colemak/keymap.c b/layouts/community/ergodox/colemak/keymap.c
index 54b0c5834a..db2addd6d9 100644
--- a/layouts/community/ergodox/colemak/keymap.c
+++ b/layouts/community/ergodox/colemak/keymap.c
@@ -138,7 +138,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/colemak_code_friendly/keymap.c b/layouts/community/ergodox/colemak_code_friendly/keymap.c
index 936ddbc2a5..6350bd9ee2 100644
--- a/layouts/community/ergodox/colemak_code_friendly/keymap.c
+++ b/layouts/community/ergodox/colemak_code_friendly/keymap.c
@@ -59,7 +59,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D,
KC_LSFT, LCTL_T(KC_Z), LGUI_T(KC_X), KC_C, KC_V, RALT_T(KC_B), KC_LCBR,
KC_LCTL, KC_LGUI, KC_LALT, KC_LBRC, KC_RBRC,
-
+
KC_HOME, KC_END,
KC_PSCR,
MO(LAYER_LNUM), KC_ENT, KC_LGUI,
@@ -101,7 +101,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_F8, KC_F7, KC_F6, KC_F5, M_IN_PRN,
KC_TRNS, KC_F4, KC_F3, KC_F2, KC_F1, M_IN_BRC, KC_TRNS,
KC_MUTE, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS,
-
+
KC_TRNS, KC_TRNS,
DYN_REC_START1,
KC_TRNS, KC_TRNS, DYN_MACRO_PLAY1,
@@ -126,8 +126,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |--------+------+------+------+------+------| | | } |------+------+------+------+------+--------|
* | | F4 | F3 | F2 | F1 | [] | | | |K/RAlt| M | , |./Supe|/ RCtl| RShift |
* '--------+------+------+------+------+-------------' '-------------+------+------+------+------+--------'
- * | MUTE | VOLD | VOLU | | | | Left | Down | Up |Right | Del |
- * '----------------------------------' '----------------------------------'
+ * | MUTE | VOLD | VOLU | | | | Left | Down | Up |Right | Del |
+ * '----------------------------------' '----------------------------------'
* .-------------. .-------------.
* | | | | Ins |ScrLck|
* .------+------+------| |------+------+------.
@@ -143,7 +143,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_F8, KC_F7, KC_F6, KC_F5, M_IN_PRN,
KC_TRNS, KC_F4, KC_F3, KC_F2, KC_F1, M_IN_BRC, KC_TRNS,
KC_MUTE, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS,
-
+
KC_TRNS, KC_TRNS,
DYN_REC_START1,
KC_TRNS, KC_TRNS, DYN_MACRO_PLAY1,
@@ -185,7 +185,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
S(KC_ESC), S(KC_A), S(KC_R), S(KC_S), S(KC_T), S(KC_D),
KC_LSFT, S(KC_Z), S(KC_X), S(KC_C), S(KC_V), S(KC_B), KC_LCBR,
S(KC_LCTL), S(KC_LGUI), S(KC_LALT), S(KC_LBRC), S(KC_RBRC),
-
+
S(KC_HOME), S(KC_END),
S(KC_PSCR),
KC_CAPS, S(KC_ENT), S(KC_LGUI),
@@ -227,7 +227,7 @@ static bool process_record_dynamic_macro_wrapper(uint16_t keycode, keyrecord_t *
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
-
+
/* the purpose of the ..._wrapper is to detect START/ST0P keys to
light the blue led during recording */
if (!process_record_dynamic_macro_wrapper(keycode, record)) {
@@ -308,19 +308,19 @@ void matrix_init_user(void) {
/* Runs constantly in the background, in a loop. */
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
//led 1, RED, Caps-Lock ON
//if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) ergodox_right_led_1_on();
//led 2, GREEN
- if (layer == LAYER_NUM)
+ if (layer == LAYER_NUM)
ergodox_right_led_2_on();
else
ergodox_right_led_2_off();
//led 3, BLUE
- if (recording_dynamic_macro)
+ if (recording_dynamic_macro)
ergodox_right_led_3_on();
else
ergodox_right_led_3_off();
diff --git a/layouts/community/ergodox/colemak_programmer/keymap.c b/layouts/community/ergodox/colemak_programmer/keymap.c
index 46cd28dc8c..b4ace197de 100644
--- a/layouts/community/ergodox/colemak_programmer/keymap.c
+++ b/layouts/community/ergodox/colemak_programmer/keymap.c
@@ -23,7 +23,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |symbol|N-Lock| End | | PgDn | | |
* `---------------------' `---------------------'
*/
-[0] = LAYOUT_ergodox( // layer 0 : default
+[0] = LAYOUT_ergodox( // layer 0 : default
// left hand
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6,
KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, TG(3),
@@ -68,7 +68,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* | | | | | | | |
* `--------------------' `----------------------'
*/
-[1] = LAYOUT_ergodox( // layer 1: QWERTY layer (games)
+[1] = LAYOUT_ergodox( // layer 1: QWERTY layer (games)
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_TRNS,
KC_TRNS, KC_A, KC_S, KC_D, KC_F, KC_G,
@@ -78,7 +78,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,
-
+
// right hand
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_TRNS,
@@ -243,7 +243,7 @@ void matrix_scan_user(void) {
//bit 1: default layer 1 - QWERTY
if (default_layer_state & (1UL << 1)) ergodox_right_led_1_on();
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
//layer 2 : Symbols (& Fs)
//if (layer == 2) ergodox_right_led_2_on();
diff --git a/layouts/community/ergodox/common_nighthawk/keymap.c b/layouts/community/ergodox/common_nighthawk/keymap.c
index cb13822e4e..a7ed10d715 100644
--- a/layouts/community/ergodox/common_nighthawk/keymap.c
+++ b/layouts/community/ergodox/common_nighthawk/keymap.c
@@ -188,7 +188,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/csharp_dev/keymap.c b/layouts/community/ergodox/csharp_dev/keymap.c
index 221389ef24..f22938429d 100644
--- a/layouts/community/ergodox/csharp_dev/keymap.c
+++ b/layouts/community/ergodox/csharp_dev/keymap.c
@@ -57,7 +57,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_RPRN, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_BSPACE,
KC_LCBR, KC_A, KC_S, KC_D, KC_F, KC_G,
KC_RCBR, ALT_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_SLASH,
- CTL_T(KC_TAB), LSFT(KC_COMMA),LSFT(KC_DOT),KC_PIPE,KC_AMPR,
+ CTL_T(KC_TAB), LSFT(KC_COMMA),LSFT(KC_DOT),KC_PIPE,KC_AMPR,
LT(1,KC_DOT), KC_COMM,
LCTL(KC_C),
GUI_T(KC_ENTER),SFT_T(KC_SPACE),LCTL(KC_V),
@@ -125,81 +125,81 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
case MACRO_PUBLIC:
if (record->event.pressed) {
return MACRO( T(P), T(U), T(B), T(L), T(I), T(C), T(SPACE),END);
- }
+ }
break;
case MACRO_PRIVATE:
if (record->event.pressed) {
return MACRO( T(P), T(R), T(I), T(V), T(A), T(T), T(E), T(SPACE),END);
- }
+ }
break;
case MACRO_STATIC:
if (record->event.pressed) {
return MACRO( T(S), T(T), T(A), T(T), T(I), T(C), T(SPACE), END);
- }
+ }
break;
case MACRO_CONST:
if (record->event.pressed) {
return MACRO( T(C), T(O), T(N), T(S), T(T), T(SPACE), END);
- }
+ }
break;
case MACRO_VOID:
if (record->event.pressed) {
return MACRO( T(V), T(O), T(I), T(D), T(SPACE), END);
- }
+ }
break;
case MACRO_VAR:
if (record->event.pressed) {
return MACRO( T(V), T(A), T(R), T(SPACE), END);
- }
+ }
break;
case MACRO_STRING:
if (record->event.pressed) {
return MACRO( T(S), T(T), T(R), T(I), T(N), T(G), T(SPACE), END);
- }
- break;
+ }
+ break;
case MACRO_BOOL:
if (record->event.pressed) {
return MACRO( T(B), T(O), T(O), T(L), T(SPACE), END);
- }
- break;
+ }
+ break;
case MACRO_INT:
if (record->event.pressed) {
return MACRO( T(I), T(N), T(T), T(SPACE), END);
- }
+ }
break;
case MACRO_FLOAT:
if (record->event.pressed) {
return MACRO( T(F), T(L), T(O), T(A),T(T),T(SPACE), END);
- }
+ }
break;
case MACRO_RETURN:
if (record->event.pressed) {
return MACRO( T(R), T(E), T(T), T(U),T(R),T(N), END);
- }
+ }
break;
case MACRO_NULL:
if (record->event.pressed) {
return MACRO( T(N), T(U), T(L), T(L), END);
- }
+ }
case MACRO_BREAK:
if (record->event.pressed) {
return MACRO( T(B), T(R), T(E), T(A), T(K), T(SCOLON), END);
- }
+ }
break;
case MACRO_TODO:
if (record->event.pressed) {
return MACRO( T(SLASH), T(SLASH), D(LSHIFT) ,T(T), T(O), T(D), T(O),U(LSHIFT), T(SPACE),END);
- }
+ }
break;
case MACRO_NEW:
if (record->event.pressed) {
return MACRO( T(N), T(E), T(W), T(SPACE), END);
- }
+ }
break;
case MACRO_PARENTHESE:
if (record->event.pressed) {
return MACRO( D(LSHIFT),T(9), T(0),U(LSHIFT), T(SCOLON), END);
- }
+ }
break;
}
return MACRO_NONE;
@@ -213,7 +213,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/dave/keymap.c b/layouts/community/ergodox/dave/keymap.c
index efa270c406..c54e50ba98 100644
--- a/layouts/community/ergodox/dave/keymap.c
+++ b/layouts/community/ergodox/dave/keymap.c
@@ -147,7 +147,7 @@ void matrix_scan_user(void) {
*/
static uint8_t leds[4];
uint8_t led;
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
diff --git a/layouts/community/ergodox/deadcyclo/keymap.c b/layouts/community/ergodox/deadcyclo/keymap.c
index 345e25e03e..76f5279257 100644
--- a/layouts/community/ergodox/deadcyclo/keymap.c
+++ b/layouts/community/ergodox/deadcyclo/keymap.c
@@ -90,10 +90,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_LALT, KC_RALT,KC_LEAD,LCTL(LSFT(KC_U)), LT(SYMB,KC_TILD),
KC_PGUP, KC_INS,
KC_PGDN,
- KC_RBRC,KC_BSPC, KC_ENT
+ KC_RBRC,KC_BSPC, KC_ENT
),
-/* Keymap 1: Symbol Layer LCTL(LSFT(KC_U))
- *
+/* Keymap 1: Symbol Layer LCTL(LSFT(KC_U))
+ *
* ,--------------------------------------------------. ,--------------------------------------------------.
* | | F1 | F2 | F3 | F4 | F5 | F6 | | F6 | F7 | F8 | F9 | F10 | F11 | F12 |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
@@ -192,7 +192,7 @@ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, I3_RUN, KC_TRNS, KC_TRNS,
* ,-------------. ,-------------.
* | | | | â–’ | â–“ |
* ,------|------|------| |------+------+------.
- * | | | | | | | |
+ * | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
@@ -218,7 +218,7 @@ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, I3_RUN, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
),
-/* Keymap 4: Unicode 2
+/* Keymap 4: Unicode 2
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | | ¹ | ² | ³ | ⴠ| ⵠ| ⶠ| | ⶠ| ⷠ| ⸠| ⹠| Ⱐ| ℃ | ™ |
@@ -234,12 +234,12 @@ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, I3_RUN, KC_TRNS, KC_TRNS,
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
- * | | | | | | | |
+ * | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
*/
-// Unicode 2
+// Unicode 2
[UNI2] = LAYOUT_ergodox(
KC_TRNS, UC(0x00b9), UC(0x00b2), UC(0x00b3), UC(0x2074), UC(0x2075), UC(0x2076),
KC_TRNS, UC(0x2081), UC(0x2082), UC(0x2083), UC(0x2084), UC(0x2085), UC(0x2086),
@@ -346,7 +346,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/dragon788/keymap.c b/layouts/community/ergodox/dragon788/keymap.c
index 956a592b6d..b32346a9df 100644
--- a/layouts/community/ergodox/dragon788/keymap.c
+++ b/layouts/community/ergodox/dragon788/keymap.c
@@ -183,7 +183,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/dvorak/keymap.c b/layouts/community/ergodox/dvorak/keymap.c
index 68b575fd68..664d8055a4 100644
--- a/layouts/community/ergodox/dvorak/keymap.c
+++ b/layouts/community/ergodox/dvorak/keymap.c
@@ -138,7 +138,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/dvorak_emacs/keymap.c b/layouts/community/ergodox/dvorak_emacs/keymap.c
index 6055fd770d..14c592f27f 100644
--- a/layouts/community/ergodox/dvorak_emacs/keymap.c
+++ b/layouts/community/ergodox/dvorak_emacs/keymap.c
@@ -120,7 +120,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/dvorak_emacs_software/keymap.c b/layouts/community/ergodox/dvorak_emacs_software/keymap.c
index 4f90f193c6..c2bc1ef8f2 100644
--- a/layouts/community/ergodox/dvorak_emacs_software/keymap.c
+++ b/layouts/community/ergodox/dvorak_emacs_software/keymap.c
@@ -121,7 +121,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/dvorak_intl_squisher/keymap.c b/layouts/community/ergodox/dvorak_intl_squisher/keymap.c
index 3ebbd2df09..2d3ec3806b 100644
--- a/layouts/community/ergodox/dvorak_intl_squisher/keymap.c
+++ b/layouts/community/ergodox/dvorak_intl_squisher/keymap.c
@@ -139,7 +139,7 @@ LAYOUT_ergodox( // layer 0 : default
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/dvorak_plover/keymap.c b/layouts/community/ergodox/dvorak_plover/keymap.c
index 989aafb90a..51f7e61203 100644
--- a/layouts/community/ergodox/dvorak_plover/keymap.c
+++ b/layouts/community/ergodox/dvorak_plover/keymap.c
@@ -181,7 +181,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/dvorak_programmer/keymap.c b/layouts/community/ergodox/dvorak_programmer/keymap.c
index 33115d21f3..a8acee119a 100644
--- a/layouts/community/ergodox/dvorak_programmer/keymap.c
+++ b/layouts/community/ergodox/dvorak_programmer/keymap.c
@@ -45,7 +45,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, MO(KEY_SEL),
MO(BRACKETS), KC_A, KC_O, KC_E, KC_U, KC_I,
MO(SHELL_NAV), KC_SCLN, KC_Q, KC_J, KC_K, KC_X, MO(KEY_NAV),
- OSL(SHORTCUTS),OSM(MOD_LCTL), OSM(MOD_LALT),OSL(SYMBOL),MO(NUMBER),
+ OSL(SHORTCUTS),OSM(MOD_LCTL), OSM(MOD_LALT),OSL(SYMBOL),MO(NUMBER),
// thumb cluster
OSM(MOD_LSFT), RCTL(KC_S),
RCTL(KC_DEL),
@@ -62,10 +62,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_UP,
KC_DOWN,KC_ENT, KC_SPC
),
-
-
-
+
+
+
// shell navigation layer
[SHELL_NAV] = LAYOUT_ergodox(
// left hand
@@ -92,7 +92,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_TRNS, KC_TRNS
),
-
+
// key navigation layer
[KEY_NAV] = LAYOUT_ergodox(
// left hand
@@ -177,7 +177,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
- KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,
KC_TRNS,
@@ -187,7 +187,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_PLUS, KC_AMPR, KC_ASTR, KC_GRAVE,KC_TILD, KC_TRNS,
KC_MINS, KC_DLR, KC_PERC, KC_CIRC, KC_PIPE, KC_TRNS,
KC_TRNS, KC_EQUAL,KC_EXLM, KC_AT, KC_HASH, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
M(SEMICOLON_NEWLINE), M(END_NEWLINE),
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
@@ -198,7 +198,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,M(OPEN_CLOSE_CURLY), M(OPEN_CLOSE_PAREN),M(OPEN_CLOSE_BRACKET), KC_TRNS,KC_TRNS,
KC_TRNS,KC_LPRN, KC_RPRN, KC_LBRC, KC_RBRC, KC_TRNS,
- KC_TRNS,KC_TRNS,KC_TRNS, KC_LCBR, KC_RCBR, KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS, KC_LCBR, KC_RCBR, KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS,KC_TRNS,
KC_TRNS,
@@ -207,8 +207,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
KC_TRNS, KC_TRNS, M(OPEN_CLOSE_BRACKET),M(OPEN_CLOSE_PAREN),M(OPEN_CLOSE_CURLY),KC_TRNS,KC_TRNS,
KC_TRNS, KC_LBRC, KC_RBRC, KC_LPRN, KC_RPRN, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_LCBR, KC_RCBR, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LCBR, KC_RCBR, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
@@ -219,7 +219,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_NO, MEH(KC_F1), MEH(KC_F2), MEH(KC_F3), MEH(KC_F4), MEH(KC_F5), MEH(KC_F6),
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
- KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
MEH(KC_0),MEH(KC_1),
MEH(KC_2),
@@ -272,12 +272,12 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
case MC_CUT_LINE:
if (record->event.pressed) {
return MACRO( T(HOME), D(LSFT), T(END), U(LSFT), D(LCTL), T(X), U(LCTL), END);
- }
+ }
break;
case MC_PASTE_LINE:
if (record->event.pressed) {
return MACRO( T(END), T(ENTER), D(LCTL), T(V), U(LCTL), END);
- }
+ }
break;
case MC_NEW_SEARCH_TAB:
if (record->event.pressed) {
@@ -287,17 +287,17 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
case SCREEN_TAB_LEFT:
if (record->event.pressed) {
return MACRO( D(LCTL), T(A), U(LCTL), T(P), END);
- }
+ }
break;
case SCREEN_TAB_RIGHT:
if (record->event.pressed) {
return MACRO( D(LCTL), T(A), U(LCTL), T(N), END);
- }
+ }
break;
case SCREEN_NEW_TAB:
if (record->event.pressed) {
return MACRO( D(LCTL), T(A), U(LCTL), T(C), END);
- }
+ }
break;
case SCREEN_COPY_MODE:
if (record->event.pressed) {
@@ -306,14 +306,14 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
break;
case SCREEN_PASTE:
if (record->event.pressed) {
- return MACRO( D(LCTL), T(A), U(LCTL), T(RBRC), END);
+ return MACRO( D(LCTL), T(A), U(LCTL), T(RBRC), END);
}
- break;
+ break;
case SWITCH_NDS:
if (record->event.pressed) {
return MACRO( D(LSFT), T(F11), U(LSFT), W(255), D(LALT), T(TAB), U(LALT), END);
- }
- break;
+ }
+ break;
case OPEN_CLOSE_PAREN:
if (record->event.pressed) {
return MACRO( D(LSFT), T(9), T(0), U(LSFT), T(LEFT), END);
@@ -323,39 +323,39 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
if (record->event.pressed) {
return MACRO( T(LBRC), T(RBRC), T(LEFT), END);
}
- break;
+ break;
case OPEN_CLOSE_CURLY:
if (record->event.pressed) {
return MACRO( D(LSFT), T(LBRC), T(RBRC), U(LSFT), T(LEFT), END);
}
- break;
+ break;
case OPEN_CLOSE_SINGLE_QUOTE:
if (record->event.pressed) {
return MACRO( T(QUOT), T(QUOT), T(LEFT), END);
}
- break;
+ break;
case OPEN_CLOSE_DOUBLE_QUOTE:
if (record->event.pressed) {
return MACRO( D(LSFT), T(QUOT), T(QUOT), U(LSFT), T(LEFT), END);
}
- break;
+ break;
case SHELL_RECALL_LAST_ARG_REMOVE_FIRST_COMMAND:
if (record->event.pressed) {
return MACRO( T(UP), T(HOME), D(LALT), T(D), U(LALT), END);
}
- break;
+ break;
case SEMICOLON_NEWLINE:
if (record->event.pressed) {
return MACRO( T(END), T(SCLN), T(ENTER), END);
- }
+ }
break;
case END_NEWLINE:
if (record->event.pressed) {
return MACRO( T(END), T(ENTER), END);
- }
- break;
-
-
+ }
+ break;
+
+
}
return MACRO_NONE;
};
@@ -378,7 +378,7 @@ void led_set_user(uint8_t usb_led) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_2_off();
@@ -387,13 +387,13 @@ void matrix_scan_user(void) {
case NUMBER:
case SYMBOL:
case BRACKETS:
- //case SHELL_LAYER:
+ //case SHELL_LAYER:
ergodox_right_led_2_on();
break;
case KEY_NAV:
case KEY_SEL:
ergodox_right_led_3_on();
- break;
+ break;
case SHORTCUTS:
ergodox_right_led_2_on();
ergodox_right_led_3_on();
@@ -401,6 +401,6 @@ void matrix_scan_user(void) {
default:
// none
break;
- }
+ }
return;
};
diff --git a/layouts/community/ergodox/dvorak_programmer_swe/keymap.c b/layouts/community/ergodox/dvorak_programmer_swe/keymap.c
index a8a428a04b..2578547f17 100644
--- a/layouts/community/ergodox/dvorak_programmer_swe/keymap.c
+++ b/layouts/community/ergodox/dvorak_programmer_swe/keymap.c
@@ -306,7 +306,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/dvorak_spanish/keymap.c b/layouts/community/ergodox/dvorak_spanish/keymap.c
index 98aa638a0f..805abb0b77 100644
--- a/layouts/community/ergodox/dvorak_spanish/keymap.c
+++ b/layouts/community/ergodox/dvorak_spanish/keymap.c
@@ -192,13 +192,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
if (record->event.pressed) {
key_timer = timer_read();
register_code(KC_RSFT);
- } else {
+ } else {
unregister_code(KC_RSFT);
- if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
- register_code(KC_RALT);
- register_code(KC_BSLS);
- unregister_code(KC_BSLS);
- unregister_code(KC_RALT);
+ if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
+ register_code(KC_RALT);
+ register_code(KC_BSLS);
+ unregister_code(KC_BSLS);
+ unregister_code(KC_RALT);
}
}
break;
@@ -207,13 +207,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
if (record->event.pressed) {
key_timer = timer_read();
register_code(KC_LALT);
- } else {
+ } else {
unregister_code(KC_LALT);
- if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
- register_code(KC_RALT);
- register_code(KC_LBRACKET);
- unregister_code(KC_LBRACKET);
- unregister_code(KC_RALT);
+ if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
+ register_code(KC_RALT);
+ register_code(KC_LBRACKET);
+ unregister_code(KC_LBRACKET);
+ unregister_code(KC_RALT);
}
}
break;
@@ -222,13 +222,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
if (record->event.pressed) {
key_timer = timer_read();
register_code(KC_LALT);
- } else {
+ } else {
unregister_code(KC_LALT);
- if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
- register_code(KC_RALT);
- register_code(KC_RBRACKET);
- unregister_code(KC_RBRACKET);
- unregister_code(KC_RALT);
+ if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
+ register_code(KC_RALT);
+ register_code(KC_RBRACKET);
+ unregister_code(KC_RBRACKET);
+ unregister_code(KC_RALT);
}
}
break;
@@ -236,7 +236,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
case CAPS: {
if (record->event.pressed) {
register_code(KC_CAPSLOCK);
- } else {
+ } else {
unregister_code(KC_CAPSLOCK);
}
break;
@@ -253,7 +253,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
@@ -270,11 +270,10 @@ void matrix_scan_user(void) {
// none
break;
}
-
+
// Turn the caps lock led on
if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) {
ergodox_right_led_1_on();
}
}
-
diff --git a/layouts/community/ergodox/dvorak_svorak_a5/keymap.c b/layouts/community/ergodox/dvorak_svorak_a5/keymap.c
index 3ecef9d9b6..6729dbeeb6 100644
--- a/layouts/community/ergodox/dvorak_svorak_a5/keymap.c
+++ b/layouts/community/ergodox/dvorak_svorak_a5/keymap.c
@@ -186,7 +186,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/emacs_osx_dk/keymap.c b/layouts/community/ergodox/emacs_osx_dk/keymap.c
index 1de894616b..2c3430c236 100644
--- a/layouts/community/ergodox/emacs_osx_dk/keymap.c
+++ b/layouts/community/ergodox/emacs_osx_dk/keymap.c
@@ -138,7 +138,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/french_hacker/keymap.c b/layouts/community/ergodox/french_hacker/keymap.c
index 44b0c47860..73e3076475 100644
--- a/layouts/community/ergodox/french_hacker/keymap.c
+++ b/layouts/community/ergodox/french_hacker/keymap.c
@@ -147,7 +147,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/galson/keymap.c b/layouts/community/ergodox/galson/keymap.c
index 2b7994b11d..83c6638d57 100644
--- a/layouts/community/ergodox/galson/keymap.c
+++ b/layouts/community/ergodox/galson/keymap.c
@@ -53,7 +53,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
/* Keymap 1: Symbol Layer
*
- * ,--------------------------------------------------.
+ * ,--------------------------------------------------.
* |Version | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
@@ -157,7 +157,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/german-kinergo/keymap.c b/layouts/community/ergodox/german-kinergo/keymap.c
index 9f8b72596e..eae02d8925 100644
--- a/layouts/community/ergodox/german-kinergo/keymap.c
+++ b/layouts/community/ergodox/german-kinergo/keymap.c
@@ -165,7 +165,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/german-lukas/keymap.c b/layouts/community/ergodox/german-lukas/keymap.c
index 76a77acdb2..a63a13c12d 100644
--- a/layouts/community/ergodox/german-lukas/keymap.c
+++ b/layouts/community/ergodox/german-lukas/keymap.c
@@ -188,7 +188,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/german-manuneo/compile_keymap.py b/layouts/community/ergodox/german-manuneo/compile_keymap.py
index df5d429842..ae7ff50397 100644
--- a/layouts/community/ergodox/german-manuneo/compile_keymap.py
+++ b/layouts/community/ergodox/german-manuneo/compile_keymap.py
@@ -27,29 +27,34 @@ PY2 = sys.version_info.major == 2
if PY2:
chr = unichr
-
KEYBOARD_LAYOUTS = {
# These map positions in the parsed layout to
# positions in the LAYOUT_ergodox MATRIX
'ergodox_ez': [
- [ 0, 1, 2, 3, 4, 5, 6], [38, 39, 40, 41, 42, 43, 44],
- [ 7, 8, 9, 10, 11, 12, 13], [45, 46, 47, 48, 49, 50, 51],
- [14, 15, 16, 17, 18, 19 ], [ 52, 53, 54, 55, 56, 57],
- [20, 21, 22, 23, 24, 25, 26], [58, 59, 60, 61, 62, 63, 64],
- [27, 28, 29, 30, 31 ], [ 65, 66, 67, 68, 69],
- [ 32, 33], [70, 71 ],
- [ 34], [72 ],
- [ 35, 36, 37], [73, 74, 75 ],
+ [0, 1, 2, 3, 4, 5, 6],
+ [38, 39, 40, 41, 42, 43, 44],
+ [7, 8, 9, 10, 11, 12, 13],
+ [45, 46, 47, 48, 49, 50, 51],
+ [14, 15, 16, 17, 18, 19],
+ [52, 53, 54, 55, 56, 57],
+ [20, 21, 22, 23, 24, 25, 26],
+ [58, 59, 60, 61, 62, 63, 64],
+ [27, 28, 29, 30, 31],
+ [65, 66, 67, 68, 69],
+ [32, 33],
+ [70, 71],
+ [34],
+ [72],
+ [35, 36, 37],
+ [73, 74, 75],
]
}
-ROW_INDENTS = {
- 'ergodox_ez': [0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 5, 0, 6, 0, 4, 0]
-}
+ROW_INDENTS = {'ergodox_ez': [0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 5, 0, 6, 0, 4, 0]}
BLANK_LAYOUTS = [
-# Compact Layout
-"""
+ # Compact Layout
+ """
.------------------------------------.------------------------------------.
| | | | | | | | | | | | | | |
!-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
@@ -70,8 +75,8 @@ BLANK_LAYOUTS = [
'-----------------' '-----------------'
""",
-# Wide Layout
-"""
+ # Wide Layout
+ """
.---------------------------------------------. .---------------------------------------------.
| | | | | | | | ! | | | | | | |
!-------+-----+-----+-----+-----+-------------! !-------+-----+-----+-----+-----+-----+-------!
@@ -93,26 +98,22 @@ BLANK_LAYOUTS = [
""",
]
-
DEFAULT_CONFIG = {
- "keymaps_includes": [
- "keymap_common.h",
- ],
+ "keymaps_includes": ["keymap_common.h",],
'filler': "-+.'!:x",
'separator': "|",
'default_key_prefix': ["KC_"],
}
-
SECTIONS = [
'layout_config',
'layers',
]
-
# Markdown Parsing
-ONELINE_COMMENT_RE = re.compile(r"""
+ONELINE_COMMENT_RE = re.compile(
+ r"""
^ # comment must be at the start of the line
\s* # arbitrary whitespace
// # start of the comment
@@ -121,22 +122,26 @@ ONELINE_COMMENT_RE = re.compile(r"""
""", re.MULTILINE | re.VERBOSE
)
-INLINE_COMMENT_RE = re.compile(r"""
+INLINE_COMMENT_RE = re.compile(
+ r"""
([\,\"\[\]\{\}\d]) # anythig that might end a expression
\s+ # comment must be preceded by whitespace
// # start of the comment
\s # and succeded by whitespace
(?:[^\"\]\}\{\[]*) # the comment (except things which might be json)
$ # until the end of line
-""", re.MULTILINE | re.VERBOSE)
+""", re.MULTILINE | re.VERBOSE
+)
-TRAILING_COMMA_RE = re.compile(r"""
+TRAILING_COMMA_RE = re.compile(
+ r"""
, # the comma
(?:\s*) # arbitrary whitespace
$ # only works if the trailing comma is followed by newline
(\s*) # arbitrary whitespace
([\]\}]) # end of an array or object
-""", re.MULTILINE | re.VERBOSE)
+""", re.MULTILINE | re.VERBOSE
+)
def loads(raw_data):
@@ -178,9 +183,7 @@ def parse_config(path):
def end_section():
if section['start_line'] >= 0:
if section['name'] == 'layout_config':
- config.update(loads("\n".join(
- section['code_lines']
- )))
+ config.update(loads("\n".join(section['code_lines'])))
elif section['sub_name'].startswith('layer'):
layer_name = section['sub_name']
config['layer_lines'][layer_name] = section['code_lines']
@@ -215,6 +218,7 @@ def parse_config(path):
assert 'layout' in config
return config
+
# header file parsing
IF0_RE = re.compile(r"""
@@ -224,7 +228,6 @@ IF0_RE = re.compile(r"""
#endif
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
-
COMMENT_RE = re.compile(r"""
/\*
.*?
@@ -244,6 +247,7 @@ def regex_partial(re_str_fmt, flags):
def partial(*args, **kwargs):
re_str = re_str_fmt.format(*args, **kwargs)
return re.compile(re_str, flags)
+
return partial
@@ -256,7 +260,6 @@ KEYDEF_REP = regex_partial(r"""
) # capture group end
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
-
ENUM_RE = re.compile(r"""
(
enum
@@ -268,7 +271,6 @@ ENUM_RE = re.compile(r"""
) # capture group end
""", re.MULTILINE | re.DOTALL | re.VERBOSE)
-
ENUM_KEY_REP = regex_partial(r"""
(
{} # the prefixes
@@ -309,14 +311,13 @@ def parse_valid_keys(config, out_path):
include_path = os.path.join(dirpath, include)
if os.path.exists(include_path):
header_data = read_header_file(include_path)
- valid_keycodes.update(
- parse_keydefs(config, header_data)
- )
+ valid_keycodes.update(parse_keydefs(config, header_data))
return valid_keycodes
# Keymap Parsing
+
def iter_raw_codes(layer_lines, filler, separator):
filler_re = re.compile("[" + filler + " ]")
for line in layer_lines:
@@ -346,28 +347,21 @@ LAYER_CHANGE_RE = re.compile(r"""
(DF|TG|MO)\(\d+\)
""", re.VERBOSE)
-
MACRO_RE = re.compile(r"""
M\(\w+\)
""", re.VERBOSE)
-
UNICODE_RE = re.compile(r"""
U[0-9A-F]{4}
""", re.VERBOSE)
-
NON_CODE = re.compile(r"""
^[^A-Z0-9_]$
""", re.VERBOSE)
def parse_uni_code(raw_code):
- macro_id = "UC_" + (
- unicodedata.name(raw_code)
- .replace(" ", "_")
- .replace("-", "_")
- )
+ macro_id = "UC_" + (unicodedata.name(raw_code).replace(" ", "_").replace("-", "_"))
code = "M({})".format(macro_id)
uc_hex = "{:04X}".format(ord(raw_code))
return code, macro_id, uc_hex
@@ -407,19 +401,13 @@ def parse_code(raw_code, key_prefixes, valid_keycodes):
def parse_keymap(config, key_indexes, layer_lines, valid_keycodes):
keymap = {}
- raw_codes = list(iter_raw_codes(
- layer_lines, config['filler'], config['separator']
- ))
+ raw_codes = list(iter_raw_codes(layer_lines, config['filler'], config['separator']))
indexed_codes = iter_indexed_codes(raw_codes, key_indexes)
key_prefixes = config['key_prefixes']
for raw_code, key_index, row_index in indexed_codes:
- code, macro_id, uc_hex = parse_code(
- raw_code, key_prefixes, valid_keycodes
- )
+ code, macro_id, uc_hex = parse_code(raw_code, key_prefixes, valid_keycodes)
# TODO: line numbers for invalid codes
- err_msg = "Could not parse key '{}' on row {}".format(
- raw_code, row_index
- )
+ err_msg = "Could not parse key '{}' on row {}".format(raw_code, row_index)
assert code is not None, err_msg
# print(repr(raw_code), repr(code), macro_id, uc_hex)
if macro_id:
@@ -432,17 +420,14 @@ def parse_keymap(config, key_indexes, layer_lines, valid_keycodes):
def parse_keymaps(config, valid_keycodes):
keymaps = collections.OrderedDict()
- key_indexes = config.get(
- 'key_indexes', KEYBOARD_LAYOUTS[config['layout']]
- )
+ key_indexes = config.get('key_indexes', KEYBOARD_LAYOUTS[config['layout']])
# TODO: maybe validate key_indexes
for layer_name, layer_lines, in config['layer_lines'].items():
- keymaps[layer_name] = parse_keymap(
- config, key_indexes, layer_lines, valid_keycodes
- )
+ keymaps[layer_name] = parse_keymap(config, key_indexes, layer_lines, valid_keycodes)
return keymaps
+
# keymap.c output
USERCODE = """
@@ -453,7 +438,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
@@ -572,7 +557,6 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {{
}};
"""
-
UNICODE_MACRO_TEMPLATE = """
case {macro_id}:
unicode_action_function(0x{hi:02x}, 0x{lo:02x});
@@ -584,9 +568,7 @@ def unicode_macro_cases(config):
for macro_id, uc_hex in config['unicode_macros'].items():
hi = int(uc_hex, 16) >> 8
lo = int(uc_hex, 16) & 0xFF
- yield UNICODE_MACRO_TEMPLATE.format(
- macro_id=macro_id, hi=hi, lo=lo
- )
+ yield UNICODE_MACRO_TEMPLATE.format(macro_id=macro_id, hi=hi, lo=lo)
def iter_keymap_lines(keymap, row_indents=None):
diff --git a/layouts/community/ergodox/german-manuneo/keymap.c b/layouts/community/ergodox/german-manuneo/keymap.c
index 9b24df83db..b6217800c3 100644
--- a/layouts/community/ergodox/german-manuneo/keymap.c
+++ b/layouts/community/ergodox/german-manuneo/keymap.c
@@ -741,7 +741,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/german/keymap.c b/layouts/community/ergodox/german/keymap.c
index 99dda5185c..150aaf3a73 100644
--- a/layouts/community/ergodox/german/keymap.c
+++ b/layouts/community/ergodox/german/keymap.c
@@ -140,7 +140,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/haegin/keymap.c b/layouts/community/ergodox/haegin/keymap.c
index c3c2afecb8..cf5db6333b 100644
--- a/layouts/community/ergodox/haegin/keymap.c
+++ b/layouts/community/ergodox/haegin/keymap.c
@@ -226,7 +226,7 @@ qk_tap_dance_action_t tap_dance_actions[] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/ishigoya-jp/keymap.c b/layouts/community/ergodox/ishigoya-jp/keymap.c
index e9d89d1bbc..8fe2b7e415 100644
--- a/layouts/community/ergodox/ishigoya-jp/keymap.c
+++ b/layouts/community/ergodox/ishigoya-jp/keymap.c
@@ -109,7 +109,7 @@ static uint16_t start;
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: Basic layer
*
- *
+ *
* ,----------------------------------------------------. ,--------------------------------------------------.
* | En / 和 | | ^ | % | | |Selall| | Undo | | $ | @ | LT | UP | RT |
* |----------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
@@ -129,9 +129,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* | | | Num | | Esc | | |
* `--------------------' `----------------------'
*
- *
+ *
* tmux prefix set to C-b
- *
+ *
*/
// If it accepts an argument (i.e, is a function), it doesn't need KC_.
// Otherwise, it needs KC_*
@@ -175,9 +175,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* | shift| fn |------| |------| |kazari|
* | | | Num | | | | |
* `--------------------' `--------------------'
- *
- *
- *
+ *
+ *
+ *
*/
[JP] = LAYOUT_ergodox(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
@@ -218,14 +218,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
- *
- *
- *
+ *
+ *
+ *
*/
[JPXON] = LAYOUT_ergodox(
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO, M(JPXE), KC_NO, M(JPXKE), KC_NO, KC_NO,
- KC_NO, KC_NO, KC_NO, M(JPXKA), KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_NO, M(JPXKA), KC_NO, KC_NO,
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO,
@@ -261,14 +261,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
- *
- *
- *
+ *
+ *
+ *
*/
[JPKAZARI] = LAYOUT_ergodox(
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO, M(JPGO), M(JPZA), M(JPBE), M(JPGE), KC_NO,
- KC_NO, M(JPDO), M(JPJI), M(JPGA), M(JPGI), M(JPZU),
+ KC_NO, M(JPDO), M(JPJI), M(JPGA), M(JPGI), M(JPZU),
KC_NO, KC_NO, M(JPZO), M(JPBI), M(JPDI), KC_NO, KC_NO,
KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO,
@@ -304,14 +304,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
- *
- *
- *
+ *
+ *
+ *
*/
[JPTOPROW] = LAYOUT_ergodox(
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO, KC_E, KC_MINS, M(JPRE), KC_NO, KC_NO,
- KC_NO, M(JPRA), M(JPRI), M(JPNA), M(JPNO), M(JPMI),
+ KC_NO, M(JPRA), M(JPRI), M(JPNA), M(JPNO), M(JPMI),
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO,
@@ -348,14 +348,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
- *
- *
- *
+ *
+ *
+ *
*/
[JPTRKZ] = LAYOUT_ergodox(
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO, KC_NO, KC_NO, M(JPPE),KC_NO, KC_NO,
- KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO, KC_NO, M(JPPI), KC_NO, KC_NO, KC_NO,
KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO,
@@ -397,7 +397,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// left hand
KC_NO, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_NO,
KC_NO, KC_NO, KC_NO, JP_DQUO, KC_RBRACKET, KC_BSPC, KC_SCLN,
- KC_NO, KC_NO, KC_SLSH, JP_PLUS, LSFT(KC_RBRACKET), JP_RCBR,
+ KC_NO, KC_NO, KC_SLSH, JP_PLUS, LSFT(KC_RBRACKET), JP_RCBR,
KC_NO, KC_NO, JP_ASTR, KC_MINS, LSFT(KC_8), LSFT(KC_9), JP_COLN,
KC_TRNS, KC_NO, KC_NO, KC_NO, KC_HASH,
KC_NO, KC_NO,
@@ -417,7 +417,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
-
+
// MACRO only works in this function
switch(id) {
case 0:
@@ -445,9 +445,9 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
}
}
break;
-
+
// kana macros start here
-
+
case JPVU:
if (record->event.pressed) {
return MACRO( I(1), T(V), T(U), END);
@@ -641,7 +641,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
case JPDI:
if (record->event.pressed) {
return MACRO( I(1), T(D), T(I), END);
- }
+ }
break;
case JPZE:
if (record->event.pressed) {
@@ -838,9 +838,9 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
return MACRO( I(1), T(B), T(U), END);
}
break;
-
+
// kana macros end here
-
+
break;
case SHIFT:
if (record->event.pressed) {
@@ -848,8 +848,8 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
if (layer_state == (1<<JPKAZARI)) {
layer_state = (1<<JPTOPROW)| (1<<JPTRKZ);
} else {
- layer_state = (1<<JPTOPROW);
- }
+ layer_state = (1<<JPTOPROW);
+ }
} else {
layer_state = (0<<JPTOPROW);
clear_keyboard_but_mods();
@@ -864,8 +864,8 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
if (layer_state == (1<<JPTOPROW)) {
layer_state = (1<<JPKAZARI)| (1<<JPTRKZ);
} else {
- layer_state = (1<<JPKAZARI);
- }
+ layer_state = (1<<JPKAZARI);
+ }
break;
} else {
layer_state = (0<<JPKAZARI);
@@ -874,7 +874,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
return MACRO( T(ENTER), END);
}
}
- break;
+ break;
case JPFN:
if (record->event.pressed) {
start = timer_read();
@@ -917,7 +917,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
break;
*/
}
- return MACRO_NONE;
+ return MACRO_NONE;
};
// Runs just one time when the keyboard initializes.
@@ -927,15 +927,15 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
- uint8_t deflayer = biton32(default_layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
+ uint8_t deflayer = get_highest_layer(default_layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
ergodox_right_led_3_off();
-
-
+
+
switch (layer) {
case 0:
//none
diff --git a/layouts/community/ergodox/issmirnov/keymap.c b/layouts/community/ergodox/issmirnov/keymap.c
index b129148b08..2743a04e93 100644
--- a/layouts/community/ergodox/issmirnov/keymap.c
+++ b/layouts/community/ergodox/issmirnov/keymap.c
@@ -125,7 +125,7 @@ _______, _______, KC_LGUI
// called by QMK during key processing before the actual key event is handled. Useful for macros.
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (keycode) {
case TAP_TOG_LAYER:
process_tap_tog(_SYMB,record);
@@ -157,7 +157,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Runs constantly in the background, in a loop every 100ms or so.
// Best used for LED status output triggered when user isn't actively typing.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
if (layer == 0) {
// Set up LED indicators for stuck modifier keys.
// https://github.com/qmk/qmk_firmware/blob/master/tmk_core/common/report.h#L118
@@ -202,7 +202,7 @@ void matrix_scan_user(void) {
// only runs when when the layer is changed, good for updating LED's and clearing sticky state
layer_state_t layer_state_set_user(layer_state_t state) {
- uint8_t layer = biton32(state);
+ uint8_t layer = get_highest_layer(state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/italian/keymap.c b/layouts/community/ergodox/italian/keymap.c
index 64dd51db67..3a81cc213b 100644
--- a/layouts/community/ergodox/italian/keymap.c
+++ b/layouts/community/ergodox/italian/keymap.c
@@ -43,7 +43,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, TT(SYMB),
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G,
- KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LALT,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LALT,
MT(MOD_LGUI,KC_NONUS_BSLASH),KC_PPLS, KC_PMNS,KC_PAST,MT(MOD_LCTL,KC_PSLS),
KC_INS, KC_LGUI,
KC_HOME,
@@ -197,7 +197,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/j3rn/keymap.c b/layouts/community/ergodox/j3rn/keymap.c
index 5081ddf527..8ff8db2381 100644
--- a/layouts/community/ergodox/j3rn/keymap.c
+++ b/layouts/community/ergodox/j3rn/keymap.c
@@ -141,7 +141,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/jackhumbert/keymap.c b/layouts/community/ergodox/jackhumbert/keymap.c
index 9d357881e2..b6d1b33e33 100644
--- a/layouts/community/ergodox/jackhumbert/keymap.c
+++ b/layouts/community/ergodox/jackhumbert/keymap.c
@@ -23,7 +23,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_NO, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, KC_P, KC_BSPC,
RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_SCLN, KC_QUOT,
KC_NO, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_ENT,
- MO(1), KC_LEFT,KC_DOWN,KC_UP, KC_RGHT,
+ MO(1), KC_LEFT,KC_DOWN,KC_UP, KC_RGHT,
RGB_TOG, RGB_HUI,
RGB_MOD,
M(2), KC_SPC,KC_SPC
@@ -32,7 +32,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// left hand
KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_TRNS,
- KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5,
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5,
KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
KC_TRNS,KC_TRNS,
@@ -43,7 +43,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS,
KC_TRNS, KC_F12, KC_NO, KC_NO, KC_NO, RESET, KC_TRNS,
- KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY,
+ KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
@@ -51,9 +51,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[MDIA] = LAYOUT_ergodox(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_TRNS,
- KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5,
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5,
KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,
@@ -62,7 +62,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC,
KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE,
KC_TRNS, KC_F12, KC_NO, KC_NO, KC_NO, RESET, KC_TRNS,
- KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY,
+ KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
@@ -97,7 +97,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/jacobono/keymap.c b/layouts/community/ergodox/jacobono/keymap.c
index e97209fc84..7c5b914872 100644
--- a/layouts/community/ergodox/jacobono/keymap.c
+++ b/layouts/community/ergodox/jacobono/keymap.c
@@ -227,7 +227,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/jafo/keymap.c b/layouts/community/ergodox/jafo/keymap.c
index b8b8e63517..28c95d6540 100644
--- a/layouts/community/ergodox/jafo/keymap.c
+++ b/layouts/community/ergodox/jafo/keymap.c
@@ -139,7 +139,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/jgarr/keymap.c b/layouts/community/ergodox/jgarr/keymap.c
index ac4e562263..38eaa5fca0 100644
--- a/layouts/community/ergodox/jgarr/keymap.c
+++ b/layouts/community/ergodox/jgarr/keymap.c
@@ -138,7 +138,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/josh/keymap.c b/layouts/community/ergodox/josh/keymap.c
index 07ee97ec82..3f9d8779e1 100644
--- a/layouts/community/ergodox/josh/keymap.c
+++ b/layouts/community/ergodox/josh/keymap.c
@@ -188,7 +188,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/kastyle/keymap.c b/layouts/community/ergodox/kastyle/keymap.c
index c9789955b3..268080c7dc 100644
--- a/layouts/community/ergodox/kastyle/keymap.c
+++ b/layouts/community/ergodox/kastyle/keymap.c
@@ -1,5 +1,5 @@
/* Setup to approximate a Kinesis Advantage with an eye to use in a
- * Mac/OSX environment
+ * Mac/OSX environment
* This version adds a hand swap feature to flip the keyboard */
#include QMK_KEYBOARD_H
#include "debug.h"
@@ -143,7 +143,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/kejadlen/keymap.c b/layouts/community/ergodox/kejadlen/keymap.c
index 6ce209f806..92a667dec0 100644
--- a/layouts/community/ergodox/kejadlen/keymap.c
+++ b/layouts/community/ergodox/kejadlen/keymap.c
@@ -74,7 +74,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
};
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/kines-ish/keymap.c b/layouts/community/ergodox/kines-ish/keymap.c
index 2d1513667f..718bf6cee1 100644
--- a/layouts/community/ergodox/kines-ish/keymap.c
+++ b/layouts/community/ergodox/kines-ish/keymap.c
@@ -138,7 +138,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/kristian/keymap.c b/layouts/community/ergodox/kristian/keymap.c
index 3fdccb790a..3f84823b99 100644
--- a/layouts/community/ergodox/kristian/keymap.c
+++ b/layouts/community/ergodox/kristian/keymap.c
@@ -35,7 +35,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/maz/keymap.c b/layouts/community/ergodox/maz/keymap.c
index 3244f2152d..4d313dee43 100644
--- a/layouts/community/ergodox/maz/keymap.c
+++ b/layouts/community/ergodox/maz/keymap.c
@@ -183,7 +183,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/mclennon_osx/keymap.c b/layouts/community/ergodox/mclennon_osx/keymap.c
index 72e9d505a1..ae67d8fb40 100644
--- a/layouts/community/ergodox/mclennon_osx/keymap.c
+++ b/layouts/community/ergodox/mclennon_osx/keymap.c
@@ -98,7 +98,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/meagerfindings/keymap.c b/layouts/community/ergodox/meagerfindings/keymap.c
index f4340b8e1b..c780c1a9fb 100644
--- a/layouts/community/ergodox/meagerfindings/keymap.c
+++ b/layouts/community/ergodox/meagerfindings/keymap.c
@@ -538,7 +538,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
};
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/msc/keymap.c b/layouts/community/ergodox/msc/keymap.c
index 5d9de3239b..62d18798dd 100644
--- a/layouts/community/ergodox/msc/keymap.c
+++ b/layouts/community/ergodox/msc/keymap.c
@@ -138,7 +138,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/naps62/keymap.c b/layouts/community/ergodox/naps62/keymap.c
index 230b3376b2..fe6289097b 100644
--- a/layouts/community/ergodox/naps62/keymap.c
+++ b/layouts/community/ergodox/naps62/keymap.c
@@ -141,7 +141,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/neo2_on_qwertz_hardware/keymap.c b/layouts/community/ergodox/neo2_on_qwertz_hardware/keymap.c
index 7c91b3fbb0..7c57820c43 100644
--- a/layouts/community/ergodox/neo2_on_qwertz_hardware/keymap.c
+++ b/layouts/community/ergodox/neo2_on_qwertz_hardware/keymap.c
@@ -5,7 +5,7 @@
#define UM 0
#define L0 0 // layer_0
-#define L1 1 // layer_1
+#define L1 1 // layer_1
#define L2 2 // layer_2
#define L3 3 // layer_3
#define L4 4 // layer_4
@@ -344,7 +344,7 @@ void unicode_action_function(uint16_t hi, uint16_t lo) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/osx_de/keymap.c b/layouts/community/ergodox/osx_de/keymap.c
index 5c3d7e49ea..cbbfc42280 100644
--- a/layouts/community/ergodox/osx_de/keymap.c
+++ b/layouts/community/ergodox/osx_de/keymap.c
@@ -31,117 +31,117 @@
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[BASE]=LAYOUT_ergodox(
//left half
- KC_ESC, DE_1, DE_2, DE_3, DE_4, DE_5, M(M_CTL_SFT_HASH),
- KC_TAB, DE_Q, DE_W, DE_E, DE_R, DE_T, KC_LGUI,
- KC_LALT, DE_A, DE_S, DE_D, DE_F, DE_G,
- KC_LSFT, CTL_T(DE_Y), DE_X, DE_C, DE_V, DE_B, KC_LALT,
- LT(SYMB,DE_LABK), M(M_DE_CIRC_CTRLCMD), M(M_DE_PLUS_CTRLALT), KC_UP, KC_DOWN,
- M(M_MEH_SH_ACUT), TG(MDIA),
- KC_HOME,
- KC_BSPC, KC_DEL, LT(SMLY,KC_END),
+ KC_ESC, DE_1, DE_2, DE_3, DE_4, DE_5, M(M_CTL_SFT_HASH),
+ KC_TAB, DE_Q, DE_W, DE_E, DE_R, DE_T, KC_LGUI,
+ KC_LALT, DE_A, DE_S, DE_D, DE_F, DE_G,
+ KC_LSFT, CTL_T(DE_Y), DE_X, DE_C, DE_V, DE_B, KC_LALT,
+ LT(SYMB,DE_LABK), M(M_DE_CIRC_CTRLCMD), M(M_DE_PLUS_CTRLALT), KC_UP, KC_DOWN,
+ M(M_MEH_SH_ACUT), TG(MDIA),
+ KC_HOME,
+ KC_BSPC, KC_DEL, LT(SMLY,KC_END),
//right half
- M(M_CTL_SFT_HASH), DE_6, DE_7, DE_8, DE_9, DE_0, DE_SS,
- KC_RGUI, DE_Z, DE_U, DE_I, DE_O, DE_P, DE_UDIA,
- DE_H, DE_J, DE_K, DE_L, DE_ODIA, ALT_T(DE_ADIA),
- KC_RALT, DE_N, DE_M, DE_COMM, DE_DOT, CTL_T(DE_MINS), KC_RSFT,
- KC_LEFT, KC_RIGHT, LGUI(KC_LSFT), LALT(KC_LSFT), LT(SYMB,DE_PLUS),
- TG(NUMB), ALL_T(DE_ACUT),
- KC_PGUP,
+ M(M_CTL_SFT_HASH), DE_6, DE_7, DE_8, DE_9, DE_0, DE_SS,
+ KC_RGUI, DE_Z, DE_U, DE_I, DE_O, DE_P, DE_UDIA,
+ DE_H, DE_J, DE_K, DE_L, DE_ODIA, ALT_T(DE_ADIA),
+ KC_RALT, DE_N, DE_M, DE_COMM, DE_DOT, CTL_T(DE_MINS), KC_RSFT,
+ KC_LEFT, KC_RIGHT, LGUI(KC_LSFT), LALT(KC_LSFT), LT(SYMB,DE_PLUS),
+ TG(NUMB), ALL_T(DE_ACUT),
+ KC_PGUP,
KC_PGDN, KC_ENT, KC_SPC),
[SYMB]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
- KC_TRNS, DE_LABK, DE_RABK, DE_EXLM, DE_QUES, KC_TRNS, KC_TRNS,
- KC_TRNS, DE_HASH, DE_DLR, DE_BSLS, DE_SLSH, KC_DOT,
- KC_TRNS, KC_TRNS, DE_LABK, DE_PERC, DE_PIPE, DE_TILD, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_DEL, KC_TRNS,
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, DE_LABK, DE_RABK, DE_EXLM, DE_QUES, KC_TRNS, KC_TRNS,
+ KC_TRNS, DE_HASH, DE_DLR, DE_BSLS, DE_SLSH, KC_DOT,
+ KC_TRNS, KC_TRNS, DE_LABK, DE_PERC, DE_PIPE, DE_TILD, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_DEL, KC_TRNS,
//right half
- M(M_TOGGLE_5), KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
- KC_TRNS, LALT(LSFT(KC_7)), LALT(KC_5), LALT(KC_6), DE_LABK, DE_RABK, DE_EXLM,
- DE_SLSH, DE_LPRN, DE_RPRN, LALT(KC_8), LALT(KC_9), DE_HASH,
- KC_TRNS, DE_PIPE, DE_TILD, DE_CIRC, KC_UP, DE_MINS, LSFT(KC_4),
- DE_QUOT, KC_LEFT, KC_DOWN, KC_RIGHT, KC_TRNS,
- KC_F13, KC_F12,
- KC_F14,
+ M(M_TOGGLE_5), KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, LALT(LSFT(KC_7)), LALT(KC_5), LALT(KC_6), DE_LABK, DE_RABK, DE_EXLM,
+ DE_SLSH, DE_LPRN, DE_RPRN, LALT(KC_8), LALT(KC_9), DE_HASH,
+ KC_TRNS, DE_PIPE, DE_TILD, DE_CIRC, KC_UP, DE_MINS, LSFT(KC_4),
+ DE_QUOT, KC_LEFT, KC_DOWN, KC_RIGHT, KC_TRNS,
+ KC_F13, KC_F12,
+ KC_F14,
KC_F15, KC_TRNS, KC_TRNS),
[MDIA]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_WH_U, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_D,
- KC_TRNS, KC_TRNS, KC_WH_L, KC_WH_D, KC_WH_R, KC_BTN3, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_WH_U, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_D,
+ KC_TRNS, KC_TRNS, KC_WH_L, KC_WH_D, KC_WH_R, KC_BTN3, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
//right half
- KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_VOLD, KC_TRNS, KC_MPRV, KC_MNXT, KC_UP, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RIGHT,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_VOLD, KC_TRNS, KC_MPRV, KC_MNXT, KC_UP, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RIGHT,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_WBAK),
[SMLY]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
//right half
- M(SM_SMILE), M(SM_SMIRK), M(SM_LAUGH), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, M(SM_FROWN), M(SM_SAD), M(SM_CRY), KC_TRNS, KC_TRNS, KC_TRNS,
- M(SM_HEART), M(SM_KISS), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ M(SM_SMILE), M(SM_SMIRK), M(SM_LAUGH), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, M(SM_FROWN), M(SM_SAD), M(SM_CRY), KC_TRNS, KC_TRNS, KC_TRNS,
+ M(SM_HEART), M(SM_KISS), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS),
[NUMB]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
//right half
- KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
- KC_TRNS, KC_UP, KC_7, KC_8, KC_9, LSFT(KC_RBRC), KC_F12,
- KC_DOWN, KC_4, KC_5, KC_6, KC_RBRC, DE_MINS,
- KC_TRNS, LSFT(KC_6), KC_1, KC_2, KC_3, LSFT(KC_7), KC_TRNS,
- KC_0, KC_DOT, KC_COMM, DE_EQL, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, LSFT(KC_RBRC), KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_RBRC, DE_MINS,
+ KC_TRNS, LSFT(KC_6), KC_1, KC_2, KC_3, LSFT(KC_7), KC_TRNS,
+ KC_0, KC_DOT, KC_COMM, DE_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS),
[EGOS]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_LSFT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_LCTL, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_F1, KC_F2,
- KC_F3,
- KC_SPC, KC_LCTL, KC_F4,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LSFT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LCTL, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_F1, KC_F2,
+ KC_F3,
+ KC_SPC, KC_LCTL, KC_F4,
//right half
- M(M_TOGGLE_5), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ M(M_TOGGLE_5), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS),
};
@@ -318,7 +318,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
-uint8_t layer = biton32(layer_state);
+uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
@@ -328,22 +328,22 @@ switch (layer) {
case SYMB:
ergodox_right_led_1_on();
-
-
+
+
break;
case MDIA:
-
+
ergodox_right_led_2_on();
-
+
break;
case SMLY:
-
-
+
+
ergodox_right_led_3_on();
break;
case NUMB:
ergodox_right_led_1_on();
-
+
ergodox_right_led_3_on();
break;
case EGOS:
@@ -357,4 +357,3 @@ break;
}
};
-
diff --git a/layouts/community/ergodox/osx_de_adnw_koy/keymap.c b/layouts/community/ergodox/osx_de_adnw_koy/keymap.c
index b8ffc2e51f..cd09d066a6 100644
--- a/layouts/community/ergodox/osx_de_adnw_koy/keymap.c
+++ b/layouts/community/ergodox/osx_de_adnw_koy/keymap.c
@@ -27,105 +27,105 @@
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[BASE]=LAYOUT_ergodox(
//left half
- KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LCTL,
- KC_TAB, KC_K, KC_DOT, KC_O, KC_COMM, KC_Z, KC_LGUI,
- TG(QWERTZ), KC_H, KC_A, KC_E, KC_I, KC_U,
- KC_LSFT, CTL_T(KC_X), KC_Q, DE_ADIA, DE_UDIA, DE_ODIA, KC_LALT,
- LT(SYMB,KC_GRV), DE_LABK, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
- TG(MDIA), MEH_T(LSFT(DE_ACUT)),
- KC_HOME,
- KC_BSPC, KC_DEL, KC_END,
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LCTL,
+ KC_TAB, KC_K, KC_DOT, KC_O, KC_COMM, KC_Z, KC_LGUI,
+ TG(QWERTZ), KC_H, KC_A, KC_E, KC_I, KC_U,
+ KC_LSFT, CTL_T(KC_X), KC_Q, DE_ADIA, DE_UDIA, DE_ODIA, KC_LALT,
+ LT(SYMB,KC_GRV), DE_LABK, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
+ TG(MDIA), MEH_T(LSFT(DE_ACUT)),
+ KC_HOME,
+ KC_BSPC, KC_DEL, KC_END,
//right half
- KC_RCTL, KC_6, KC_7, KC_8, KC_9, KC_0, DE_MINS,
- KC_RGUI, KC_V, KC_G, KC_C, KC_L, KC_MINS, KC_Y,
- KC_D, KC_T, KC_R, KC_N, KC_S, LT(MDIA,KC_F),
- KC_RALT, KC_B, KC_P, KC_W, KC_M, CTL_T(KC_J), KC_RSFT,
- KC_UP, KC_DOWN, LGUI(KC_LSFT), KC_RBRC, LT(SYMB,KC_BSLS),
- ALL_T(DE_ACUT), TG(NUMB),
- KC_PGUP,
+ KC_RCTL, KC_6, KC_7, KC_8, KC_9, KC_0, DE_MINS,
+ KC_RGUI, KC_V, KC_G, KC_C, KC_L, KC_MINS, KC_Y,
+ KC_D, KC_T, KC_R, KC_N, KC_S, LT(MDIA,KC_F),
+ KC_RALT, KC_B, KC_P, KC_W, KC_M, CTL_T(KC_J), KC_RSFT,
+ KC_UP, KC_DOWN, LGUI(KC_LSFT), KC_RBRC, LT(SYMB,KC_BSLS),
+ ALL_T(DE_ACUT), TG(NUMB),
+ KC_PGUP,
KC_PGDN, KC_ENT, KC_SPC),
[SYMB]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
- KC_TRNS, KC_GRV, LSFT(KC_GRV), DE_EXLM, DE_QUES, KC_TRNS, KC_TRNS,
- KC_TRNS, DE_HASH, DE_DLR, LALT(LSFT(KC_7)), DE_SLSH, KC_DOT,
- KC_TRNS, KC_TRNS, DE_LABK, DE_PERC, LALT(KC_7), LALT(KC_N), KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_DEL, KC_TRNS,
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, KC_GRV, LSFT(KC_GRV), DE_EXLM, DE_QUES, KC_TRNS, KC_TRNS,
+ KC_TRNS, DE_HASH, DE_DLR, LALT(LSFT(KC_7)), DE_SLSH, KC_DOT,
+ KC_TRNS, KC_TRNS, DE_LABK, DE_PERC, LALT(KC_7), LALT(KC_N), KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_DEL, KC_TRNS,
//right half
- KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
- KC_TRNS, LALT(LSFT(KC_7)), LALT(KC_5), LALT(KC_6), LALT(KC_7), DE_HASH, KC_F12,
- DE_SLSH, DE_LPRN, DE_RPRN, LALT(KC_8), LALT(KC_9), KC_TRNS,
- KC_TRNS, DE_AMPR, KC_GRV, LSFT(KC_GRV), DE_DQUO, DE_QUOT, DE_QUES,
- KC_TRNS, KC_DOT, KC_EXLM, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, LALT(LSFT(KC_7)), LALT(KC_5), LALT(KC_6), LALT(KC_7), DE_HASH, KC_F12,
+ DE_SLSH, DE_LPRN, DE_RPRN, LALT(KC_8), LALT(KC_9), KC_TRNS,
+ KC_TRNS, DE_AMPR, KC_GRV, LSFT(KC_GRV), DE_DQUO, DE_QUOT, DE_QUES,
+ KC_TRNS, KC_DOT, KC_EXLM, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS),
[MDIA]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
- KC_TRNS, KC_WH_L, KC_WH_U, KC_WH_D, KC_WH_R, KC_BTN3, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_WH_L, KC_WH_U, KC_WH_D, KC_WH_R, KC_BTN3, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
//right half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_MUTE, KC_MPRV, KC_MNXT, KC_UP, KC_TRNS,
- KC_VOLU, KC_VOLD, KC_LEFT, KC_DOWN, KC_RIGHT,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MUTE, KC_MPRV, KC_MNXT, KC_UP, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_LEFT, KC_DOWN, KC_RIGHT,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_WBAK),
[QWERTZ]=LAYOUT_ergodox(
//left half
- KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, LGUI(KC_V),
- KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LGUI,
- KC_TRNS, KC_A, KC_S, KC_D, KC_F, KC_G,
- KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_LALT,
- LT(SYMB,KC_GRV), DE_LABK, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
- KC_TRNS, MEH_T(LSFT(DE_ACUT)),
- KC_HOME,
- KC_BSPC, KC_DEL, KC_END,
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, LGUI(KC_V),
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LGUI,
+ KC_TRNS, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_LALT,
+ LT(SYMB,KC_GRV), DE_LABK, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
+ KC_TRNS, MEH_T(LSFT(DE_ACUT)),
+ KC_HOME,
+ KC_BSPC, KC_DEL, KC_END,
//right half
- LGUI(KC_C), KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
- KC_RGUI, KC_Y, KC_U, KC_I, KC_O, KC_P, DE_UDIA,
- KC_H, KC_J, KC_K, KC_L, KC_SCLN, LT(MDIA,DE_ADIA),
- KC_RALT, KC_N, KC_M, KC_COMM, KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
- KC_UP, KC_DOWN, LGUI(KC_LSFT), KC_RBRC, LT(SYMB,KC_BSLS),
- ALL_T(DE_ACUT), KC_TRNS,
- KC_PGUP,
+ LGUI(KC_C), KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ KC_RGUI, KC_Y, KC_U, KC_I, KC_O, KC_P, DE_UDIA,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, LT(MDIA,DE_ADIA),
+ KC_RALT, KC_N, KC_M, KC_COMM, KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN, LGUI(KC_LSFT), KC_RBRC, LT(SYMB,KC_BSLS),
+ ALL_T(DE_ACUT), KC_TRNS,
+ KC_PGUP,
KC_PGDN, KC_ENT, KC_SPC),
[NUMB]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
//right half
- KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
- KC_TRNS, KC_UP, KC_7, KC_8, KC_9, LSFT(KC_RBRC), KC_F12,
- KC_DOWN, KC_4, KC_5, KC_6, KC_RBRC, KC_TRNS,
- KC_TRNS, LSFT(KC_6), KC_1, KC_2, KC_3, LSFT(KC_7), KC_TRNS,
- KC_0, KC_DOT, KC_0, KC_EQL, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, LSFT(KC_RBRC), KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_RBRC, KC_TRNS,
+ KC_TRNS, LSFT(KC_6), KC_1, KC_2, KC_3, LSFT(KC_7), KC_TRNS,
+ KC_0, KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS),
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
-uint8_t layer = biton32(layer_state);
+uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
@@ -139,4 +139,3 @@ break;
}
};
-
diff --git a/layouts/community/ergodox/osx_de_experimental/keymap.c b/layouts/community/ergodox/osx_de_experimental/keymap.c
index 8228b5e371..faf238726f 100644
--- a/layouts/community/ergodox/osx_de_experimental/keymap.c
+++ b/layouts/community/ergodox/osx_de_experimental/keymap.c
@@ -66,315 +66,315 @@
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/**
* Layer: BASE
-* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
-* | ESC | 1 | 2 | 3 | 4 | 5 | Hold or toggle | | Hold or toggle | 6 | 7 | 8 | 9 | 0 | ß |
-* | | | | | | | Layer NUMB | | Layer MDIA | | | | | | |
-* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
-* | TAB | Q | W | E | R | T | Cmd | | Cmd | Z | U | I | O | P | Ü |
-* | | | | | | | | | | | | | | | |
-* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/\-------------------\ \-------------------\/-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
-* | Alt | A | S | D | F | G | | H | J | K | L | Ö | Ä |
-* | | | | | | | | | | | | | ALT |
-* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
-* | Shift | Y | X | C | V | B | Alt | | Alt | N | M | , | . | - | Shift |
-* | | Ctrl | | | | | | | | | | | | Ctrl | |
-* \-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\ \-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\
-*
-*
-* /-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------/
-* | < | LongPress / Type | LongPress / Type | Shift+Ctrl | Type | | # | ACUT | CMD+Shift | ALT+Shift | + |
-* | SYMB | DE_CIRC_CTRLCMD | DE_PLUS_CTRAlt | | Toggle SMLY | | Meh | Hyper | | | SYMB |
-* \-------------------\\-------------------\\-------------------\\-------------------\/-------------------//-------------------/ /-------------------//-------------------/ \-------------------\\-------------------\\-------------------\\-------------------\\-------------------\
-* | HOME | END | | LEFT | RIGHT |
-* | | | | | |
-* \-------------------\/-------------------/ /-------------------/\-------------------\
-* | PGUP | | UP |
-* | | | |
-* /-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------/
-* | BSPC | DEL | PGDN | | DOWN | ENT | SPC |
-* | | | | | | | |
-* \-------------------\\-------------------\\-------------------\ \-------------------\\-------------------\\-------------------\
-*
-*
+* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
+* | ESC | 1 | 2 | 3 | 4 | 5 | Hold or toggle | | Hold or toggle | 6 | 7 | 8 | 9 | 0 | ß |
+* | | | | | | | Layer NUMB | | Layer MDIA | | | | | | |
+* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
+* | TAB | Q | W | E | R | T | Cmd | | Cmd | Z | U | I | O | P | Ü |
+* | | | | | | | | | | | | | | | |
+* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/\-------------------\ \-------------------\/-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
+* | Alt | A | S | D | F | G | | H | J | K | L | Ö | Ä |
+* | | | | | | | | | | | | | ALT |
+* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
+* | Shift | Y | X | C | V | B | Alt | | Alt | N | M | , | . | - | Shift |
+* | | Ctrl | | | | | | | | | | | | Ctrl | |
+* \-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\ \-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\
+*
+*
+* /-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------/
+* | < | LongPress / Type | LongPress / Type | Shift+Ctrl | Type | | # | ACUT | CMD+Shift | ALT+Shift | + |
+* | SYMB | DE_CIRC_CTRLCMD | DE_PLUS_CTRAlt | | Toggle SMLY | | Meh | Hyper | | | SYMB |
+* \-------------------\\-------------------\\-------------------\\-------------------\/-------------------//-------------------/ /-------------------//-------------------/ \-------------------\\-------------------\\-------------------\\-------------------\\-------------------\
+* | HOME | END | | LEFT | RIGHT |
+* | | | | | |
+* \-------------------\/-------------------/ /-------------------/\-------------------\
+* | PGUP | | UP |
+* | | | |
+* /-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------/
+* | BSPC | DEL | PGDN | | DOWN | ENT | SPC |
+* | | | | | | | |
+* \-------------------\\-------------------\\-------------------\ \-------------------\\-------------------\\-------------------\
+*
+*
**/
[BASE]=LAYOUT_ergodox(
//left half
- KC_ESC, DE_1, DE_2, DE_3, DE_4, DE_5, M(TGH_NUM),
- KC_TAB, DE_Q, DE_W, DE_E, DE_R, DE_T, KC_LGUI,
- KC_LALT, DE_A, DE_S, DE_D, DE_F, DE_G,
- KC_LSFT, CTL_T(DE_Y), DE_X, DE_C, DE_V, DE_B, KC_LALT,
- LT(SYMB,DE_LABK), M(M_DE_CIRC_CTRLCMD), M(M_DE_PLUS_CTRLALT), LSFT(KC_LCTRL), M(SMLY_TOG_QUOT),
- KC_HOME, KC_END,
- KC_PGUP,
- KC_BSPC, KC_DEL, KC_PGDN,
+ KC_ESC, DE_1, DE_2, DE_3, DE_4, DE_5, M(TGH_NUM),
+ KC_TAB, DE_Q, DE_W, DE_E, DE_R, DE_T, KC_LGUI,
+ KC_LALT, DE_A, DE_S, DE_D, DE_F, DE_G,
+ KC_LSFT, CTL_T(DE_Y), DE_X, DE_C, DE_V, DE_B, KC_LALT,
+ LT(SYMB,DE_LABK), M(M_DE_CIRC_CTRLCMD), M(M_DE_PLUS_CTRLALT), LSFT(KC_LCTRL), M(SMLY_TOG_QUOT),
+ KC_HOME, KC_END,
+ KC_PGUP,
+ KC_BSPC, KC_DEL, KC_PGDN,
//right half
- M(TOG_HLD_MDIA), DE_6, DE_7, DE_8, DE_9, DE_0, DE_SS,
- KC_RGUI, DE_Z, DE_U, DE_I, DE_O, DE_P, DE_UDIA,
- DE_H, DE_J, DE_K, DE_L, DE_ODIA, ALT_T(DE_ADIA),
- KC_RALT, DE_N, DE_M, DE_COMM, DE_DOT, CTL_T(DE_MINS), KC_RSFT,
- MEH_T(DE_HASH), ALL_T(DE_ACUT), LGUI(KC_LSFT), LALT(KC_LSFT), LT(SYMB,DE_PLUS),
- KC_LEFT, KC_RIGHT,
- KC_UP,
+ M(TOG_HLD_MDIA), DE_6, DE_7, DE_8, DE_9, DE_0, DE_SS,
+ KC_RGUI, DE_Z, DE_U, DE_I, DE_O, DE_P, DE_UDIA,
+ DE_H, DE_J, DE_K, DE_L, DE_ODIA, ALT_T(DE_ADIA),
+ KC_RALT, DE_N, DE_M, DE_COMM, DE_DOT, CTL_T(DE_MINS), KC_RSFT,
+ MEH_T(DE_HASH), ALL_T(DE_ACUT), LGUI(KC_LSFT), LALT(KC_LSFT), LT(SYMB,DE_PLUS),
+ KC_LEFT, KC_RIGHT,
+ KC_UP,
KC_DOWN, KC_ENT, KC_SPC),
/**
* Layer: SYMB
-* /-----------//-----------//-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------//-----------//-----------/
-* | APPLICATION| F1 | F2 | F3 | F4 | F5 | F5 | | F6 | F6 | F7 | F8 | F9 | F10 | F11 |
-* | | | | | | | | | | | | | | | |
-* /-----------//-----------//-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------//-----------//-----------/
-* | | < | > | ! | ? | | | | | \ | [ | ] | < | > | ! |
-* | | | | | | | | | | | | | | | |
-* /-----------//-----------//-----------//-----------//-----------//-----------/\-----------\ \-----------\/-----------//-----------//-----------//-----------//-----------//-----------/
-* | | # | $ | \ | / | . | | / | ( | ) | { | } | # |
-* | | | | | | | | | | | | | |
-* /-----------//-----------//-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------//-----------//-----------/
-* | | | < | % | | | ~ | | | | | | ~ | | | | |
-* | | | | | | | | | | | | | | | |
-* \-----------\\-----------\\-----------\\-----------\\-----------\\-----------\\-----------\ \-----------\\-----------\\-----------\\-----------\\-----------\\-----------\\-----------\
-*
-*
-* /-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------/
-* | | | | | | | ' | DQOT | | Toggle 5 | |
-* | | | | | | | | | | | |
-* \-----------\\-----------\\-----------\\-----------\/-----------//-----------/ /-----------//-----------/ \-----------\\-----------\\-----------\\-----------\\-----------\
-* | | | | F13 | F12 |
-* | | | | | |
-* \-----------\/-----------/ /-----------/\-----------\
-* | | | F14 |
-* | | | |
-* /-----------//-----------//-----------/ /-----------//-----------//-----------/
-* | | DEL | | | F15 | | |
-* | | | | | | | |
-* \-----------\\-----------\\-----------\ \-----------\\-----------\\-----------\
-*
-*
+* /-----------//-----------//-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------//-----------//-----------/
+* | APPLICATION| F1 | F2 | F3 | F4 | F5 | F5 | | F6 | F6 | F7 | F8 | F9 | F10 | F11 |
+* | | | | | | | | | | | | | | | |
+* /-----------//-----------//-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------//-----------//-----------/
+* | | < | > | ! | ? | | | | | \ | [ | ] | < | > | ! |
+* | | | | | | | | | | | | | | | |
+* /-----------//-----------//-----------//-----------//-----------//-----------/\-----------\ \-----------\/-----------//-----------//-----------//-----------//-----------//-----------/
+* | | # | $ | \ | / | . | | / | ( | ) | { | } | # |
+* | | | | | | | | | | | | | |
+* /-----------//-----------//-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------//-----------//-----------/
+* | | | < | % | | | ~ | | | | | | ~ | | | | |
+* | | | | | | | | | | | | | | | |
+* \-----------\\-----------\\-----------\\-----------\\-----------\\-----------\\-----------\ \-----------\\-----------\\-----------\\-----------\\-----------\\-----------\\-----------\
+*
+*
+* /-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------/
+* | | | | | | | ' | DQOT | | Toggle 5 | |
+* | | | | | | | | | | | |
+* \-----------\\-----------\\-----------\\-----------\/-----------//-----------/ /-----------//-----------/ \-----------\\-----------\\-----------\\-----------\\-----------\
+* | | | | F13 | F12 |
+* | | | | | |
+* \-----------\/-----------/ /-----------/\-----------\
+* | | | F14 |
+* | | | |
+* /-----------//-----------//-----------/ /-----------//-----------//-----------/
+* | | DEL | | | F15 | | |
+* | | | | | | | |
+* \-----------\\-----------\\-----------\ \-----------\\-----------\\-----------\
+*
+*
**/
[SYMB]=LAYOUT_ergodox(
//left half
- KC_APPLICATION, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F5,
- KC_TRNS, DE_LABK, DE_RABK, DE_EXLM, DE_QST, KC_TRNS, KC_TRNS,
- KC_TRNS, DE_HASH, DE_DLR, DE_BSLS, DE_SLSH, KC_DOT,
- KC_TRNS, KC_TRNS, DE_LABK, DE_PERC, DE_PIPE, DE_TILD, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_DEL, KC_TRNS,
+ KC_APPLICATION, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F5,
+ KC_TRNS, DE_LABK, DE_RABK, DE_EXLM, DE_QST, KC_TRNS, KC_TRNS,
+ KC_TRNS, DE_HASH, DE_DLR, DE_BSLS, DE_SLSH, KC_DOT,
+ KC_TRNS, KC_TRNS, DE_LABK, DE_PERC, DE_PIPE, DE_TILD, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_DEL, KC_TRNS,
//right half
- KC_F6, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
- KC_TRNS, DE_BSLS, DE_LBRC, DE_RBRC, DE_LABK, DE_RABK, DE_EXLM,
- DE_SLSH, DE_LPRN, DE_RPRN, DE_LCBR, DE_RCBR, DE_HASH,
- KC_TRNS, DE_PIPE, DE_TILD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- DE_QUOT, DE_DQUO, KC_TRNS, M(M_TOGGLE_5), KC_TRNS,
- KC_F13, KC_F12,
- KC_F14,
+ KC_F6, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, DE_BSLS, DE_LBRC, DE_RBRC, DE_LABK, DE_RABK, DE_EXLM,
+ DE_SLSH, DE_LPRN, DE_RPRN, DE_LCBR, DE_RCBR, DE_HASH,
+ KC_TRNS, DE_PIPE, DE_TILD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ DE_QUOT, DE_DQUO, KC_TRNS, M(M_TOGGLE_5), KC_TRNS,
+ KC_F13, KC_F12,
+ KC_F14,
KC_F15, KC_TRNS, KC_TRNS),
/**
* Layer: MDIA
-* /-----//-----//-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----//-----//-----/
-* | | | | | | | | | | | | | | | |
-* | | | | | | | | | | | | | | | |
-* /-----//-----//-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----//-----//-----/
-* | | | BTN1 | U | BTN2 | U | | | | | | | | | |
-* | | | | | | | | | | | | | | | |
-* /-----//-----//-----//-----//-----//-----/\-----\ \-----\/-----//-----//-----//-----//-----//-----/
-* | | | L | D | R | D | | | | | | | |
-* | | | | | | | | | | | | | |
-* /-----//-----//-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----//-----//-----/
-* | | | L | D | R | BTN3 | | | | | | | | UP | |
-* | | | | | | | | | | | | | | | |
-* \-----\\-----\\-----\\-----\\-----\\-----\\-----\ \-----\\-----\\-----\\-----\\-----\\-----\\-----\
-*
-*
-* /-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----/
-* | | | | | | | | | LEFT | DOWN | RIGHT|
-* | | | | | | | | | | | |
-* \-----\\-----\\-----\\-----\/-----//-----/ /-----//-----/ \-----\\-----\\-----\\-----\\-----\
-* | | | | MPRV | MNXT |
-* | | | | | |
-* \-----\/-----/ /-----/\-----\
-* | | | VOLU |
-* | | | |
-* /-----//-----//-----/ /-----//-----//-----/
-* | | | | | VOLD | MUTE | MPLY |
-* | | | | | | | |
-* \-----\\-----\\-----\ \-----\\-----\\-----\
-*
-*
+* /-----//-----//-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----//-----//-----/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* /-----//-----//-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----//-----//-----/
+* | | | BTN1 | U | BTN2 | U | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* /-----//-----//-----//-----//-----//-----/\-----\ \-----\/-----//-----//-----//-----//-----//-----/
+* | | | L | D | R | D | | | | | | | |
+* | | | | | | | | | | | | | |
+* /-----//-----//-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----//-----//-----/
+* | | | L | D | R | BTN3 | | | | | | | | UP | |
+* | | | | | | | | | | | | | | | |
+* \-----\\-----\\-----\\-----\\-----\\-----\\-----\ \-----\\-----\\-----\\-----\\-----\\-----\\-----\
+*
+*
+* /-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----/
+* | | | | | | | | | LEFT | DOWN | RIGHT|
+* | | | | | | | | | | | |
+* \-----\\-----\\-----\\-----\/-----//-----/ /-----//-----/ \-----\\-----\\-----\\-----\\-----\
+* | | | | MPRV | MNXT |
+* | | | | | |
+* \-----\/-----/ /-----/\-----\
+* | | | VOLU |
+* | | | |
+* /-----//-----//-----/ /-----//-----//-----/
+* | | | | | VOLD | MUTE | MPLY |
+* | | | | | | | |
+* \-----\\-----\\-----\ \-----\\-----\\-----\
+*
+*
**/
[MDIA]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_WH_U, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_D,
- KC_TRNS, KC_TRNS, KC_WH_L, KC_WH_D, KC_WH_R, KC_BTN3, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_WH_U, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_D,
+ KC_TRNS, KC_TRNS, KC_WH_L, KC_WH_D, KC_WH_R, KC_BTN3, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
//right half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RIGHT,
- KC_MPRV, KC_MNXT,
- KC_VOLU,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RIGHT,
+ KC_MPRV, KC_MNXT,
+ KC_VOLU,
KC_VOLD, KC_MUTE, KC_MPLY),
/**
* Layer: SMLY
-* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
-* | | | | | | | | | Typing | Typing | Typing | | | | |
-* | | | | | | | | | SM_SMILE| SM_SMIRK| SM_LAUGH| | | | |
-* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
-* | | | | | | | | | | Typing | Typing | Typing | | | |
-* | | | | | | | | | | SM_FROWN| SM_SAD | SM_CRY | | | |
-* /--------//--------//--------//--------//--------//--------/\--------\ \--------\/--------//--------//--------//--------//--------//--------/
-* | | | | | | | | Typing | Typing | | | | |
-* | | | | | | | | SM_HEART| SM_KISS | | | | |
-* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
-* | | | | | | | | | | | | | | | |
-* | | | | | | | | | | | | | | | |
-* \--------\\--------\\--------\\--------\\--------\\--------\\--------\ \--------\\--------\\--------\\--------\\--------\\--------\\--------\
-*
-*
-* /--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------/
-* | | | | | | | | | | | |
-* | | | | | | | | | | | |
-* \--------\\--------\\--------\\--------\/--------//--------/ /--------//--------/ \--------\\--------\\--------\\--------\\--------\
-* | | | | | |
-* | | | | | |
-* \--------\/--------/ /--------/\--------\
-* | | | |
-* | | | |
-* /--------//--------//--------/ /--------//--------//--------/
-* | | | | | | | |
-* | | | | | | | |
-* \--------\\--------\\--------\ \--------\\--------\\--------\
-*
-*
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | Typing | Typing | Typing | | | | |
+* | | | | | | | | | SM_SMILE| SM_SMIRK| SM_LAUGH| | | | |
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | Typing | Typing | Typing | | | |
+* | | | | | | | | | | SM_FROWN| SM_SAD | SM_CRY | | | |
+* /--------//--------//--------//--------//--------//--------/\--------\ \--------\/--------//--------//--------//--------//--------//--------/
+* | | | | | | | | Typing | Typing | | | | |
+* | | | | | | | | SM_HEART| SM_KISS | | | | |
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* \--------\\--------\\--------\\--------\\--------\\--------\\--------\ \--------\\--------\\--------\\--------\\--------\\--------\\--------\
+*
+*
+* /--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------/
+* | | | | | | | | | | | |
+* | | | | | | | | | | | |
+* \--------\\--------\\--------\\--------\/--------//--------/ /--------//--------/ \--------\\--------\\--------\\--------\\--------\
+* | | | | | |
+* | | | | | |
+* \--------\/--------/ /--------/\--------\
+* | | | |
+* | | | |
+* /--------//--------//--------/ /--------//--------//--------/
+* | | | | | | | |
+* | | | | | | | |
+* \--------\\--------\\--------\ \--------\\--------\\--------\
+*
+*
**/
[SMLY]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
//right half
- M(SM_SMILE), M(SM_SMIRK), M(SM_LAUGH), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, M(SM_FROWN), M(SM_SAD), M(SM_CRY), KC_TRNS, KC_TRNS, KC_TRNS,
- M(SM_HEART), M(SM_KISS), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ M(SM_SMILE), M(SM_SMIRK), M(SM_LAUGH), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, M(SM_FROWN), M(SM_SAD), M(SM_CRY), KC_TRNS, KC_TRNS, KC_TRNS,
+ M(SM_HEART), M(SM_KISS), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS),
/**
* Layer: NUMB
-* /----//----//----//----//----//----//----/ /----//----//----//----//----//----//----/
-* | | | | | | | | | | F6 | F7 | F8 | F9 | F10 | F11 |
-* | | | | | | | | | | | | | | | |
-* /----//----//----//----//----//----//----/ /----//----//----//----//----//----//----/
-* | | | | UP | | | | | | / | 7 | 8 | 9 | * | F12 |
-* | | | | | | | | | | | | | | | |
-* /----//----//----//----//----//----/\----\ \----\/----//----//----//----//----//----/
-* | | | LEFT| DOWN| RGHT| | | / | 4 | 5 | 6 | + | - |
-* | | | | | | | | | | | | | |
-* /----//----//----//----//----//----//----/ /----//----//----//----//----//----//----/
-* | | | | | | | | | | % | 1 | 2 | 3 | | |
-* | | | | | | | | | | | | | | | |
-* \----\\----\\----\\----\\----\\----\\----\ \----\\----\\----\\----\\----\\----\\----\
-*
-*
-* /----//----//----//----//----/ /----//----//----//----//----/
-* | | | | | | | 0 | . | , | = | |
-* | | | | | | | | | | | |
-* \----\\----\\----\\----\/----//----/ /----//----/ \----\\----\\----\\----\\----\
-* | | | | | |
-* | | | | | |
-* \----\/----/ /----/\----\
-* | | | |
-* | | | |
-* /----//----//----/ /----//----//----/
-* | | | | | | | |
-* | | | | | | | |
-* \----\\----\\----\ \----\\----\\----\
-*
-*
+* /----//----//----//----//----//----//----/ /----//----//----//----//----//----//----/
+* | | | | | | | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+* | | | | | | | | | | | | | | | |
+* /----//----//----//----//----//----//----/ /----//----//----//----//----//----//----/
+* | | | | UP | | | | | | / | 7 | 8 | 9 | * | F12 |
+* | | | | | | | | | | | | | | | |
+* /----//----//----//----//----//----/\----\ \----\/----//----//----//----//----//----/
+* | | | LEFT| DOWN| RGHT| | | / | 4 | 5 | 6 | + | - |
+* | | | | | | | | | | | | | |
+* /----//----//----//----//----//----//----/ /----//----//----//----//----//----//----/
+* | | | | | | | | | | % | 1 | 2 | 3 | | |
+* | | | | | | | | | | | | | | | |
+* \----\\----\\----\\----\\----\\----\\----\ \----\\----\\----\\----\\----\\----\\----\
+*
+*
+* /----//----//----//----//----/ /----//----//----//----//----/
+* | | | | | | | 0 | . | , | = | |
+* | | | | | | | | | | | |
+* \----\\----\\----\\----\/----//----/ /----//----/ \----\\----\\----\\----\\----\
+* | | | | | |
+* | | | | | |
+* \----\/----/ /----/\----\
+* | | | |
+* | | | |
+* /----//----//----/ /----//----//----/
+* | | | | | | | |
+* | | | | | | | |
+* \----\\----\\----\ \----\\----\\----\
+*
+*
**/
[NUMB]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
//right half
- KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
- KC_TRNS, DE_SLSH, KC_7, KC_8, KC_9, DE_ASTR, KC_F12,
- DE_SLSH, KC_4, KC_5, KC_6, DE_PLUS, DE_MINS,
- KC_TRNS, DE_PERC, KC_1, KC_2, KC_3, KC_TRNS, KC_TRNS,
- KC_0, KC_DOT, KC_COMM, DE_EQL, KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, DE_SLSH, KC_7, KC_8, KC_9, DE_ASTR, KC_F12,
+ DE_SLSH, KC_4, KC_5, KC_6, DE_PLUS, DE_MINS,
+ KC_TRNS, DE_PERC, KC_1, KC_2, KC_3, KC_TRNS, KC_TRNS,
+ KC_0, KC_DOT, KC_COMM, DE_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS),
/**
* Layer: EGOS
-* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
-* | | | | | | | | | | | | | | | |
-* | | | | | | | | | | | | | | | |
-* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
-* | | | | | | | | | | | | | | | |
-* | | | | | | | | | | | | | | | |
-* /--------//--------//--------//--------//--------//--------/\--------\ \--------\/--------//--------//--------//--------//--------//--------/
-* | Shift | | | | | | | | | | | | |
-* | | | | | | | | | | | | | |
-* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
-* | | | | | | | | | | | | | | | |
-* | | | | | | | | | | | | | | | |
-* \--------\\--------\\--------\\--------\\--------\\--------\\--------\ \--------\\--------\\--------\\--------\\--------\\--------\\--------\
-*
-*
-* /--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------/
-* | Ctrl | | | | | | | | | Toggle 5| |
-* | | | | | | | | | | | |
-* \--------\\--------\\--------\\--------\/--------//--------/ /--------//--------/ \--------\\--------\\--------\\--------\\--------\
-* | F1 | F2 | | | |
-* | | | | | |
-* \--------\/--------/ /--------/\--------\
-* | F3 | | |
-* | | | |
-* /--------//--------//--------/ /--------//--------//--------/
-* | SPC | Ctrl | F4 | | | | |
-* | | | | | | | |
-* \--------\\--------\\--------\ \--------\\--------\\--------\
-*
-*
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* /--------//--------//--------//--------//--------//--------/\--------\ \--------\/--------//--------//--------//--------//--------//--------/
+* | Shift | | | | | | | | | | | | |
+* | | | | | | | | | | | | | |
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* \--------\\--------\\--------\\--------\\--------\\--------\\--------\ \--------\\--------\\--------\\--------\\--------\\--------\\--------\
+*
+*
+* /--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------/
+* | Ctrl | | | | | | | | | Toggle 5| |
+* | | | | | | | | | | | |
+* \--------\\--------\\--------\\--------\/--------//--------/ /--------//--------/ \--------\\--------\\--------\\--------\\--------\
+* | F1 | F2 | | | |
+* | | | | | |
+* \--------\/--------/ /--------/\--------\
+* | F3 | | |
+* | | | |
+* /--------//--------//--------/ /--------//--------//--------/
+* | SPC | Ctrl | F4 | | | | |
+* | | | | | | | |
+* \--------\\--------\\--------\ \--------\\--------\\--------\
+*
+*
**/
[EGOS]=LAYOUT_ergodox(
//left half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_LSFT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_LCTL, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_F1, KC_F2,
- KC_F3,
- KC_SPC, KC_LCTL, KC_F4,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LSFT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LCTL, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_F1, KC_F2,
+ KC_F3,
+ KC_SPC, KC_LCTL, KC_F4,
//right half
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, M(M_TOGGLE_5), KC_TRNS,
- KC_TRNS, KC_TRNS,
- KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, M(M_TOGGLE_5), KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS),
};
@@ -556,7 +556,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
-uint8_t layer = biton32(layer_state);
+uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
@@ -566,17 +566,17 @@ switch (layer) {
case SYMB:
ergodox_right_led_1_on();
-
-
+
+
break;
case MDIA:
-
+
ergodox_right_led_2_on();
-
+
break;
case NUMB:
-
-
+
+
ergodox_right_led_3_on();
break;
case EGOS:
@@ -590,4 +590,3 @@ break;
}
};
-
diff --git a/layouts/community/ergodox/osx_fr/keymap.c b/layouts/community/ergodox/osx_fr/keymap.c
index 886e54208a..22451c1a30 100644
--- a/layouts/community/ergodox/osx_fr/keymap.c
+++ b/layouts/community/ergodox/osx_fr/keymap.c
@@ -141,7 +141,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/osx_kinesis_pnut/keymap.c b/layouts/community/ergodox/osx_kinesis_pnut/keymap.c
index ad6ea27364..fb50a3407e 100644
--- a/layouts/community/ergodox/osx_kinesis_pnut/keymap.c
+++ b/layouts/community/ergodox/osx_kinesis_pnut/keymap.c
@@ -145,7 +145,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/osx_neo2/keymap.c b/layouts/community/ergodox/osx_neo2/keymap.c
index 3dbfceabc4..125cc43a8f 100644
--- a/layouts/community/ergodox/osx_neo2/keymap.c
+++ b/layouts/community/ergodox/osx_neo2/keymap.c
@@ -704,7 +704,7 @@ void matrix_init_user(void){
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/phoenix/keymap.c b/layouts/community/ergodox/phoenix/keymap.c
index a66462e3a8..4371e5f2e7 100644
--- a/layouts/community/ergodox/phoenix/keymap.c
+++ b/layouts/community/ergodox/phoenix/keymap.c
@@ -138,7 +138,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/plover/keymap.c b/layouts/community/ergodox/plover/keymap.c
index ffb869309a..7b34dde2ed 100644
--- a/layouts/community/ergodox/plover/keymap.c
+++ b/layouts/community/ergodox/plover/keymap.c
@@ -182,7 +182,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/qwerty_code_friendly/keymap.c b/layouts/community/ergodox/qwerty_code_friendly/keymap.c
index 6e285d5613..ed06446907 100644
--- a/layouts/community/ergodox/qwerty_code_friendly/keymap.c
+++ b/layouts/community/ergodox/qwerty_code_friendly/keymap.c
@@ -662,7 +662,7 @@ void matrix_init_user(void) {
/* Runs constantly in the background, in a loop. */
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/reset_eeprom/keymap.c b/layouts/community/ergodox/reset_eeprom/keymap.c
index 83c252a9a1..726447cbd0 100644
--- a/layouts/community/ergodox/reset_eeprom/keymap.c
+++ b/layouts/community/ergodox/reset_eeprom/keymap.c
@@ -96,7 +96,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/romanzolotarev-norman-plover-osx-hjkl/keymap.c b/layouts/community/ergodox/romanzolotarev-norman-plover-osx-hjkl/keymap.c
index 819944121e..6eb319ca63 100644
--- a/layouts/community/ergodox/romanzolotarev-norman-plover-osx-hjkl/keymap.c
+++ b/layouts/community/ergodox/romanzolotarev-norman-plover-osx-hjkl/keymap.c
@@ -88,7 +88,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
diff --git a/layouts/community/ergodox/romanzolotarev-norman-plover-osx/keymap.c b/layouts/community/ergodox/romanzolotarev-norman-plover-osx/keymap.c
index a0964fac77..adf420daa0 100644
--- a/layouts/community/ergodox/romanzolotarev-norman-plover-osx/keymap.c
+++ b/layouts/community/ergodox/romanzolotarev-norman-plover-osx/keymap.c
@@ -88,7 +88,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
diff --git a/layouts/community/ergodox/romanzolotarev-norman-qwerty-osx/keymap.c b/layouts/community/ergodox/romanzolotarev-norman-qwerty-osx/keymap.c
index 6aca3a6d5f..cf3941ee1d 100644
--- a/layouts/community/ergodox/romanzolotarev-norman-qwerty-osx/keymap.c
+++ b/layouts/community/ergodox/romanzolotarev-norman-qwerty-osx/keymap.c
@@ -48,7 +48,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
diff --git a/layouts/community/ergodox/sethbc/keymap.c b/layouts/community/ergodox/sethbc/keymap.c
index 26d3106ec4..f3a1f64309 100644
--- a/layouts/community/ergodox/sethbc/keymap.c
+++ b/layouts/community/ergodox/sethbc/keymap.c
@@ -77,7 +77,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/siroken3/keymap.c b/layouts/community/ergodox/siroken3/keymap.c
index fed8b4a0c8..dd5125d20e 100644
--- a/layouts/community/ergodox/siroken3/keymap.c
+++ b/layouts/community/ergodox/siroken3/keymap.c
@@ -141,7 +141,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/sneako/keymap.c b/layouts/community/ergodox/sneako/keymap.c
index 9d3cdd5a11..dffe797ab0 100644
--- a/layouts/community/ergodox/sneako/keymap.c
+++ b/layouts/community/ergodox/sneako/keymap.c
@@ -141,7 +141,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/software_neo2/keymap.c b/layouts/community/ergodox/software_neo2/keymap.c
index 5f600a5ab5..c191a034f2 100644
--- a/layouts/community/ergodox/software_neo2/keymap.c
+++ b/layouts/community/ergodox/software_neo2/keymap.c
@@ -98,7 +98,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/swedish-lindhe/keymap.c b/layouts/community/ergodox/swedish-lindhe/keymap.c
index 368e216cdc..b0abff9ec6 100644
--- a/layouts/community/ergodox/swedish-lindhe/keymap.c
+++ b/layouts/community/ergodox/swedish-lindhe/keymap.c
@@ -162,7 +162,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/swedish/keymap.c b/layouts/community/ergodox/swedish/keymap.c
index 90218aa886..5e2d47de57 100644
--- a/layouts/community/ergodox/swedish/keymap.c
+++ b/layouts/community/ergodox/swedish/keymap.c
@@ -203,7 +203,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/swissgerman/keymap.c b/layouts/community/ergodox/swissgerman/keymap.c
index 8ba9582934..8766d16ae0 100644
--- a/layouts/community/ergodox/swissgerman/keymap.c
+++ b/layouts/community/ergodox/swissgerman/keymap.c
@@ -222,7 +222,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
switch (layer) {
// TODO: Make this relevant to the ErgoDox EZ.
diff --git a/layouts/community/ergodox/techtomas/keymap.c b/layouts/community/ergodox/techtomas/keymap.c
index 742eca03a4..bdbb50be42 100644
--- a/layouts/community/ergodox/techtomas/keymap.c
+++ b/layouts/community/ergodox/techtomas/keymap.c
@@ -180,7 +180,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/tkuichooseyou/keymap.c b/layouts/community/ergodox/tkuichooseyou/keymap.c
index ea6c8f259f..08f1cfc9ab 100644
--- a/layouts/community/ergodox/tkuichooseyou/keymap.c
+++ b/layouts/community/ergodox/tkuichooseyou/keymap.c
@@ -138,7 +138,7 @@ LAYOUT_ergodox(
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/tonyabra_osx/keymap.c b/layouts/community/ergodox/tonyabra_osx/keymap.c
index 741a6396e8..9b8048dda3 100644
--- a/layouts/community/ergodox/tonyabra_osx/keymap.c
+++ b/layouts/community/ergodox/tonyabra_osx/keymap.c
@@ -138,7 +138,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/townk_osx/keymap.c b/layouts/community/ergodox/townk_osx/keymap.c
index 6799ad7460..c79d74d6eb 100644
--- a/layouts/community/ergodox/townk_osx/keymap.c
+++ b/layouts/community/ergodox/townk_osx/keymap.c
@@ -229,7 +229,7 @@ uint8_t current_layer = BASE;
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_led_all_off();
ergodox_led_all_set(LED_BRIGHTNESS_LO);
diff --git a/layouts/community/ergodox/twentylives_dvorak_with_hebrew/keymap.c b/layouts/community/ergodox/twentylives_dvorak_with_hebrew/keymap.c
index 4b5181a70d..12548ae0ea 100644
--- a/layouts/community/ergodox/twentylives_dvorak_with_hebrew/keymap.c
+++ b/layouts/community/ergodox/twentylives_dvorak_with_hebrew/keymap.c
@@ -36,7 +36,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_DELETE, KC_TRNS,
KC_LGUI,
KC_BSPACE,CTL_T(KC_NO),KC_LALT,
-
+
KC_TILD, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQUAL,
KC_TRNS, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLASH,
KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINUS,
@@ -77,7 +77,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,
-
+
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_Y, KC_U, KC_E, KC_O, KC_P, KC_TRNS,
KC_H, KC_J, KC_K, KC_L, KC_SCOLON, KC_TRNS,
@@ -110,9 +110,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `--------------------' `--------------------'
*/
[2] = LAYOUT_ergodox(
- KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_UP, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
@@ -120,12 +120,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRNS,
- KC_F11, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_F11, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_LEFT, KC_DOWN, KC_RIGHT, KC_TRNS, KC_TRNS,
KC_F12, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_MS_BTN1, KC_MS_BTN2, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
- KC_TRNS,
+ KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
),
@@ -154,19 +154,19 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Left Hand
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
- KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS,KC_TRNS,
KC_TRNS,
KC_TRNS,KC_TRNS,KC_TRNS,
// Right Hand
- KC_TRNS, KC_TRNS, KC_LOCKING_NUM, KC_KP_SLASH, KC_KP_ASTERISK, KC_KP_MINUS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LOCKING_NUM, KC_KP_SLASH, KC_KP_ASTERISK, KC_KP_MINUS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_KP_7, KC_KP_8, KC_KP_9, KC_KP_PLUS, KC_TRNS,
- KC_TRNS, KC_KP_4, KC_KP_5, KC_KP_6, KC_KP_PLUS, KC_TRNS,
+ KC_TRNS, KC_KP_4, KC_KP_5, KC_KP_6, KC_KP_PLUS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_KP_1, KC_KP_2, KC_KP_3, KC_ENTER, KC_TRNS,
KC_KP_0, KC_KP_0, KC_KP_DOT, KC_ENTER, KC_TRNS,
- KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
),
@@ -175,7 +175,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/win10_writers-block/keymap.c b/layouts/community/ergodox/win10_writers-block/keymap.c
index 05adaed759..443e403b18 100644
--- a/layouts/community/ergodox/win10_writers-block/keymap.c
+++ b/layouts/community/ergodox/win10_writers-block/keymap.c
@@ -4,8 +4,8 @@
#include "version.h"
#include "wait.h"
-#define BASE 0 // default layer - helpful for writing in Office-style word processors.
-#define SYMB 1 // symbol layer - NumPad, etc. - same as Ergodox EZ default but no EEPROM or Version key
+#define BASE 0 // default layer - helpful for writing in Office-style word processors.
+#define SYMB 1 // symbol layer - NumPad, etc. - same as Ergodox EZ default but no EEPROM or Version key
#define RIMW 2 // rimworld layer - made for the game RimWorld, by Tynan Sylvester | feel free to remap for your favorite game!
#define MDIA 3 // media layer - mouse and music - close to Ergodox EZ default media layer
@@ -27,19 +27,19 @@ enum {
};
void cake_count (qk_tap_dance_state_t *state, void *user_data) {
- if (state->count == 2) {
+ if (state->count == 2) {
layer_on (SYMB); //define double tap here
layer_off (MDIA);
- }
- else {
+ }
+ else {
layer_off (SYMB); //define single tap or hold here
layer_off (MDIA);
}
- if (state->count == 3) {
+ if (state->count == 3) {
layer_on (RIMW); //define triple tap here
layer_off (MDIA);
- }
- else {
+ }
+ else {
layer_off (RIMW); //define single tap or hold here
layer_off (MDIA);
reset_tap_dance (state);
@@ -83,7 +83,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* ,--------------------------------------------------. ,--------------------------------------------------.
* | ` | 1 | 2 | 3 | 4 | 5 | 6 | | 7 | 7 | 8 | 9 | 0 | - | = |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
- * | F12/L1 | Q | W | E | R | T | {/[ | |TD(L0 | Y | U | I | O | P | \ |
+ * | F12/L1 | Q | W | E | R | T | {/[ | |TD(L0 | Y | U | I | O | P | \ |
* |--------+------+------+------+------+------| | |L1 L2)|------+------+------+------+------+--------|
* |Caps/Win| A | S | D | F | G |------| |------| H | J | K | L | ; | ' |
* |--------+------+------+------+------+------| }/] | TD(ctrl|------+------+------+------+------+--------|
@@ -163,8 +163,8 @@ LT(SYMB, KC_F12), KC_Q, KC_W, KC_E, KC_R, KC_T,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
-),
-
+),
+
/* Keymap 2: RimWorld Layer
*
* ,--------------------------------------------------. ,--------------------------------------------------.
@@ -186,7 +186,7 @@ LT(SYMB, KC_F12), KC_Q, KC_W, KC_E, KC_R, KC_T,
* | | | Q | | | | |
* `--------------------' `--------------------'
*/
-// RIMWORLD
+// RIMWORLD
[RIMW] = LAYOUT_ergodox(
// left hand
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6,
@@ -300,7 +300,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
@@ -315,7 +315,7 @@ void matrix_scan_user(void) {
break;
case 3:
ergodox_right_led_3_on();
- break;
+ break;
default:
// none
break;
diff --git a/layouts/community/ergodox/xyverz/keymap.c b/layouts/community/ergodox/xyverz/keymap.c
index c77920bb13..f348736c6e 100644
--- a/layouts/community/ergodox/xyverz/keymap.c
+++ b/layouts/community/ergodox/xyverz/keymap.c
@@ -1,6 +1,6 @@
/*
* About this keymap:
- *
+ *
* The Dvorak layout shown here stems from my early Kinesis years, using the Contour PS/2 with a Dvorak
* software layout. Because of this, the RBRC and LBRC were on opposite sides of the board in the corner
* keys. When I originally set up this keymap, I'd decided to continue using this layout with my ErgoDox.
@@ -14,7 +14,7 @@
* layouts.
*
* What's New:
- *
+ *
* I've overhauled this Dvorak layout a bit to more match what I've got on my other Ortho boards. For
* some keys, I'm moving away from my old Kinesis keymap and adding the brackets and braces to the
* inner column vertical keys. I figure this will help me have better ease of use. In this update, I
@@ -246,7 +246,7 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ergodox/zweihander-macos/keymap.c b/layouts/community/ergodox/zweihander-macos/keymap.c
index b2ddeb0d6b..0aecc24e67 100644
--- a/layouts/community/ergodox/zweihander-macos/keymap.c
+++ b/layouts/community/ergodox/zweihander-macos/keymap.c
@@ -140,7 +140,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
+ uint8_t layer = get_highest_layer(layer_state);
ergodox_board_led_off();
ergodox_right_led_1_off();
diff --git a/layouts/community/ortho_4x12/peej/keymap.c b/layouts/community/ortho_4x12/peej/keymap.c
index d78f03da41..1e2874ac99 100644
--- a/layouts/community/ortho_4x12/peej/keymap.c
+++ b/layouts/community/ortho_4x12/peej/keymap.c
@@ -56,7 +56,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
writePinLow(LED_RED);
writePinLow(LED_GREEN);
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _FUNCTION:
writePinHigh(LED_RED);
break;
diff --git a/lib/chibios b/lib/chibios
-Subproject 257302333c31f1f710800c2b97acf3550de043e
+Subproject f836d24b06d7265696a33d1cea010bd6a931791
diff --git a/lib/fnv/Makefile b/lib/fnv/Makefile
new file mode 100644
index 0000000000..c0673ded40
--- /dev/null
+++ b/lib/fnv/Makefile
@@ -0,0 +1,304 @@
+#!/bin/make
+#
+# hash - makefile for FNV hash tools
+#
+# @(#) $Revision: 5.2 $
+# @(#) $Id: Makefile,v 5.2 2012/03/21 01:42:15 chongo Exp $
+# @(#) $Source: /usr/local/src/cmd/fnv/RCS/Makefile,v $
+#
+# See:
+# http://www.isthe.com/chongo/tech/comp/fnv/index.html
+#
+# for the most up to date copy of this code and the FNV hash home page.
+#
+# Please do not copyright this code. This code is in the public domain.
+#
+# LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+# EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+#
+# By:
+# chongo <Landon Curt Noll> /\oo/\
+# http://www.isthe.com/chongo/
+#
+# Share and Enjoy! :-)
+
+# make tools
+#
+SHELL= /bin/sh
+CFLAGS= -O3 -g3
+#CFLAGS= -O2 -g3
+#CC= cc
+AR= ar
+TAR= tar
+EGREP= egrep
+GZIP_BIN= gzip
+INSTALL= install
+
+# If your system needs ranlib use:
+# RANLIB= ranlib
+# otherwise use:
+# RANLIB= :
+#
+#RANLIB= ranlib
+RANLIB= :
+
+# where to install things
+#
+DESTBIN= /usr/local/bin
+DESTLIB= /usr/local/lib
+DESTINC= /usr/local/include
+
+# what to build
+#
+SRC= hash_32.c hash_32a.c hash_64.c hash_64a.c \
+ fnv32.c fnv64.c \
+ have_ulong64.c test_fnv.c
+NO64BIT_SRC= no64bit_fnv64.c no64bit_hash_64.c \
+ no64bit_hash_64a.c no64bit_test_fnv.c
+HSRC= fnv.h \
+ longlong.h
+ALL= ${SRC} ${HSRC} \
+ README Makefile
+PROGS= fnv032 fnv064 fnv132 fnv164 fnv1a32 fnv1a64
+OBSOLETE_PROGS= fnv0_32 fnv0_64 fnv1_32 fnv1_64 fnv1a_32 fnv1a_64
+NO64BIT_PROGS= no64bit_fnv064 no64bit_fnv164 no64bit_fnv1a64
+LIBS= libfnv.a
+LIBOBJ= hash_32.o hash_64.o hash_32a.o hash_64a.o test_fnv.o
+NO64BIT_OBJ= no64bit_fnv64.o no64bit_hash_64.o \
+ no64bit_hash_64a.o no64bit_test_fnv.o
+OTHEROBJ= fnv32.o fnv64.o
+TARGETS= ${LIBOBJ} ${LIBS} ${PROGS}
+
+# default rule
+#
+all: ${TARGETS}
+
+# things to build
+#
+hash_32.o: hash_32.c longlong.h fnv.h
+ ${CC} ${CFLAGS} hash_32.c -c
+
+hash_64.o: hash_64.c longlong.h fnv.h
+ ${CC} ${CFLAGS} hash_64.c -c
+
+hash_32a.o: hash_32a.c longlong.h fnv.h
+ ${CC} ${CFLAGS} hash_32a.c -c
+
+hash_64a.o: hash_64a.c longlong.h fnv.h
+ ${CC} ${CFLAGS} hash_64a.c -c
+
+test_fnv.o: test_fnv.c longlong.h fnv.h
+ ${CC} ${CFLAGS} test_fnv.c -c
+
+fnv32.o: fnv32.c longlong.h fnv.h
+ ${CC} ${CFLAGS} fnv32.c -c
+
+fnv032: fnv32.o libfnv.a
+ ${CC} fnv32.o libfnv.a -o fnv032
+
+fnv64.o: fnv64.c longlong.h fnv.h
+ ${CC} ${CFLAGS} fnv64.c -c
+
+fnv064: fnv64.o libfnv.a
+ ${CC} fnv64.o libfnv.a -o fnv064
+
+libfnv.a: ${LIBOBJ}
+ rm -f $@
+ ${AR} rv $@ ${LIBOBJ}
+ ${RANLIB} $@
+
+fnv132: fnv032
+ -rm -f $@
+ -cp -f $? $@
+
+fnv1a32: fnv032
+ -rm -f $@
+ -cp -f $? $@
+
+fnv164: fnv064
+ -rm -f $@
+ -cp -f $? $@
+
+fnv1a64: fnv064
+ -rm -f $@
+ -cp -f $? $@
+
+longlong.h: have_ulong64.c Makefile
+ -@rm -f have_ulong64 have_ulong64.o ll_tmp longlong.h
+ @echo 'forming longlong.h'
+ @echo '/*' > longlong.h
+ @echo ' * DO NOT EDIT -- generated by the Makefile' >> longlong.h
+ @echo ' */' >> longlong.h
+ @echo '' >> longlong.h
+ @echo '#if !defined(__LONGLONG_H__)' >> longlong.h
+ @echo '#define __LONGLONG_H__' >> longlong.h
+ @echo '' >> longlong.h
+ @echo '/* do we have/want to use a long long type? */' >> longlong.h
+ -@rm -f have_ulong64.o have_ulong64
+ -@${CC} ${CFLAGS} have_ulong64.c -c 2>/dev/null; true
+ -@${CC} ${CFLAGS} have_ulong64.o -o have_ulong64 2>/dev/null; true
+ -@${SHELL} -c "./have_ulong64 > ll_tmp 2>/dev/null" \
+ >/dev/null 2>&1; true
+ -@if [ -s ll_tmp ]; then \
+ cat ll_tmp >> longlong.h; \
+ else \
+ echo '#undef HAVE_64BIT_LONG_LONG /* no */' >> longlong.h; \
+ fi
+ @echo '' >> longlong.h
+ @echo '/*' >> longlong.h
+ @echo ' * NO64BIT_LONG_LONG undef HAVE_64BIT_LONG_LONG' >> longlong.h
+ @echo ' */' >> longlong.h
+ @echo '#if defined(NO64BIT_LONG_LONG)' >> longlong.h
+ @echo '#undef HAVE_64BIT_LONG_LONG' >> longlong.h
+ @echo '#endif /* NO64BIT_LONG_LONG */' >> longlong.h
+ @echo '' >> longlong.h
+ @echo '#endif /* !__LONGLONG_H__ */' >> longlong.h
+ -@rm -f have_ulong64 have_ulong64.o ll_tmp
+ @echo 'longlong.h formed'
+
+# utilities
+#
+install: all
+ -@if [ -d "${DESTBIN}" ]; then \
+ echo " mkdir -p ${DESTBIN}"; \
+ mkdir -p ${DESTBIN}; \
+ fi
+ -@if [ -d "${DESTLIB}" ]; then \
+ echo " mkdir -p ${DESTLIB}"; \
+ mkdir -p ${DESTLIB}; \
+ fi
+ -@if [ -d "${DESTINC}" ]; then \
+ echo " mkdir -p ${DESTINC}"; \
+ mkdir -p ${DESTINC}; \
+ fi
+ ${INSTALL} -m 0755 ${PROGS} ${DESTBIN}
+ ${INSTALL} -m 0644 ${LIBS} ${DESTLIB}
+ ${RANLIB} ${DESTLIB}/libfnv.a
+ ${INSTALL} -m 0644 ${HSRC} ${DESTINC}
+ @# remove osolete programs
+ for i in ${OBSOLETE_PROGS}; do \
+ if [ -f "${DESTBIN}/$$i" ]; then \
+ echo "rm -f ${DESTBIN}/$$i"; \
+ rm -f "${DESTBIN}/$$i"; \
+ fi; \
+ done
+
+clean:
+ -rm -f have_ulong64 have_ulong64.o ll_tmp ll_tmp2 longlong.h
+ -rm -f ${LIBOBJ}
+ -rm -f ${OTHEROBJ}
+
+clobber: clean
+ -rm -f ${TARGETS}
+ -rm -f ${OBSOLETE_PROGS} lltmp lltmp2 ll_tmp
+ -rm -f ${NO64BIT_SRC}
+ -rm -f ${NO64BIT_OBJ}
+ -rm -f ${NO64BIT_PROGS}
+ -rm -f vector.c
+
+check: ${PROGS}
+ @echo -n "FNV-0 32 bit tests: "
+ @./fnv032 -t 1 -v
+ @echo -n "FNV-1 32 bit tests: "
+ @./fnv132 -t 1 -v
+ @echo -n "FNV-1a 32 bit tests: "
+ @./fnv1a32 -t 1 -v
+ @echo -n "FNV-0 64 bit tests: "
+ @./fnv064 -t 1 -v
+ @echo -n "FNV-1 64 bit tests: "
+ @./fnv164 -t 1 -v
+ @echo -n "FNV-1a 64 bit tests: "
+ @./fnv1a64 -t 1 -v
+
+###############################
+# generate test vector source #
+###############################
+
+no64bit_fnv64.c: fnv64.c
+ -rm -f $@
+ -cp -f $? $@
+
+no64bit_hash_64.c: hash_64.c
+ -rm -f $@
+ -cp -f $? $@
+
+no64bit_hash_64a.c: hash_64a.c
+ -rm -f $@
+ -cp -f $? $@
+
+no64bit_test_fnv.c: test_fnv.c
+ -rm -f $@
+ -cp -f $? $@
+
+no64bit_fnv64.o: no64bit_fnv64.c longlong.h fnv.h
+ ${CC} ${CFLAGS} -DNO64BIT_LONG_LONG no64bit_fnv64.c -c
+
+no64bit_hash_64.o: no64bit_hash_64.c longlong.h fnv.h
+ ${CC} ${CFLAGS} -DNO64BIT_LONG_LONG no64bit_hash_64.c -c
+
+no64bit_hash_64a.o: no64bit_hash_64a.c longlong.h fnv.h
+ ${CC} ${CFLAGS} -DNO64BIT_LONG_LONG no64bit_hash_64a.c -c
+
+no64bit_test_fnv.o: no64bit_test_fnv.c longlong.h fnv.h
+ ${CC} ${CFLAGS} -DNO64BIT_LONG_LONG no64bit_test_fnv.c -c
+
+no64bit_fnv064: no64bit_fnv64.o no64bit_hash_64.o \
+ no64bit_hash_64a.o no64bit_test_fnv.o
+ ${CC} ${CFLAGS} no64bit_fnv64.o no64bit_hash_64.o \
+ no64bit_hash_64a.o no64bit_test_fnv.o -o $@
+
+no64bit_fnv164: no64bit_fnv064
+ -rm -f $@
+ -cp -f $? $@
+
+no64bit_fnv1a64: no64bit_fnv064
+ -rm -f $@
+ -cp -f $? $@
+
+vector.c: ${PROGS} ${NO64BIT_PROGS}
+ -rm -f $@
+ echo '/* start of output generated by make $@ */' >> $@
+ echo '' >> $@
+ #@
+ echo '/* FNV-0 32 bit test vectors */' >> $@
+ ./fnv032 -t 0 >> $@
+ echo '' >> $@
+ #@
+ echo '/* FNV-1 32 bit test vectors */' >> $@
+ ./fnv132 -t 0 >> $@
+ echo '' >> $@
+ #@
+ echo '/* FNV-1a 32 bit test vectors */' >> $@
+ ./fnv1a32 -t 0 >> $@
+ echo '' >> $@
+ #@
+ echo '/* FNV-0 64 bit test vectors */' >> $@
+ echo '#if defined(HAVE_64BIT_LONG_LONG)' >> $@
+ ./fnv064 -t 0 >> $@
+ echo '#else /* HAVE_64BIT_LONG_LONG */' >> $@
+ ./no64bit_fnv064 -t 0 >> $@
+ echo '#endif /* HAVE_64BIT_LONG_LONG */' >> $@
+ echo '' >> $@
+ #@
+ echo '/* FNV-1 64 bit test vectors */' >> $@
+ echo '#if defined(HAVE_64BIT_LONG_LONG)' >> $@
+ ./fnv164 -t 0 >> $@
+ echo '#else /* HAVE_64BIT_LONG_LONG */' >> $@
+ ./no64bit_fnv164 -t 0 >> $@
+ echo '#endif /* HAVE_64BIT_LONG_LONG */' >> $@
+ echo '' >> $@
+ #@
+ echo '/* FNV-1a 64 bit test vectors */' >> $@
+ echo '#if defined(HAVE_64BIT_LONG_LONG)' >> $@
+ ./fnv1a64 -t 0 >> $@
+ echo '#else /* HAVE_64BIT_LONG_LONG */' >> $@
+ ./no64bit_fnv1a64 -t 0 >> $@
+ echo '#endif /* HAVE_64BIT_LONG_LONG */' >> $@
+ echo '' >> $@
+ #@
+ echo '/* end of output generated by make $@ */' >> $@
diff --git a/lib/fnv/README b/lib/fnv/README
new file mode 100644
index 0000000000..60aa9aaf61
--- /dev/null
+++ b/lib/fnv/README
@@ -0,0 +1,158 @@
+#=====================#
+# Fowler/Noll/Vo hash #
+#=====================#
+
+The basis of this hash algorithm was taken from an idea sent
+as reviewer comments to the IEEE POSIX P1003.2 committee by:
+
+ Phong Vo (http://www.research.att.com/info/kpv)
+ Glenn Fowler (http://www.research.att.com/~gsf/)
+
+In a subsequent ballot round:
+
+ Landon Curt Noll (http://www.isthe.com/chongo)
+
+improved on their algorithm. Some people tried this hash
+and found that it worked rather well. In an EMail message
+to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+
+FNV hashes are designed to be fast while maintaining a low
+collision rate. The FNV speed allows one to quickly hash lots
+of data while maintaining a reasonable collision rate. See:
+
+ http://www.isthe.com/chongo/tech/comp/fnv/index.html
+
+for more details as well as other forms of the FNV hash.
+Comments, questions, bug fixes and suggestions welcome at
+the address given in the above URL.
+
+
+#==================#
+# FNV hash utility #
+#==================#
+
+Two hash utilities (32 bit and 64 bit) are provided:
+
+ fnv032 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
+ fnv132 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
+ fnv1a32 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
+
+ fnv064 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
+ fnv164 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
+ fnv1a64 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
+
+ -b bcnt mask off all but the lower bcnt bits (default: 32)
+ -m multiple hashes, one per line for each arg
+ -s hash arg as a string (ignoring terminating NUL bytes)
+ -t code 0 ==> generate test vectors, 1 ==> test FNV hash
+ -v verbose mode, print arg after hash (implies -m)
+ arg string (if -s was given) or filename (default stdin)
+
+The fnv032, fnv064 implement the historic FNV-0 hash.
+The fnv132, fnv164 implement the recommended FNV-1 hash.
+The fnv1a32, fnv1a64 implement the recommended FNV-1a hash.
+
+This is the original historic FNV algorithm with a 0 offset basis.
+It is recommended that FNV-1, with a non-0 offset basis be used instead.
+
+To test FNV hashes, try:
+
+ fnv032 -t 1 -v
+ fnv132 -t 1 -v
+ fnv1a32 -t 1 -v
+
+ fnv064 -t 1 -v
+ fnv164 -t 1 -v
+ fnv1a64 -t 1 -v
+
+If you are compiling, try:
+
+ make check
+
+
+#==================#
+# FNV hash library #
+#==================#
+
+The libfnv.a library implements both a 32 bit and a 64 bit FNV hash
+on collections of bytes, a NUL terminated strings or on an open file
+descriptor.
+
+Here is the 32 bit FNV 1 hash:
+
+ Fnv32_t fnv_32_buf(void *buf, int len, Fnv32_t hval); /* byte buf */
+ Fnv32_t fnv_32_str(char *string, Fnv32_t hval); /* string */
+
+Here is the 32 bit FNV 1a hash:
+
+ Fnv32_t fnv_32a_buf(void *buf, int len, Fnv32_t hval); /* byte buf */
+ Fnv32_t fnv_32a_str(char *string, Fnv32_t hval); /* string */
+
+Here is the 64 bit FNV 1 hash:
+
+ Fnv64_t fnv_64_buf(void *buf, int len, Fnv64_t hval); /* byte buf */
+ Fnv64_t fnv_64_str(char *string, Fnv64_t hval); /* string */
+
+Here is the 64 bit FNV 1a hash:
+
+ Fnv64_t fnv_64a_buf(void *buf, int len, Fnv64_t hval); /* byte buf */
+ Fnv64_t fnv_64a_str(char *string, Fnv64_t hval); /* string */
+
+On the first call to a hash function, one must supply the initial basis
+that is appropriate for the hash in question:
+
+ FNV-0: (not recommended)
+
+ FNV0_32_INIT /* 32 bit FNV-0 initial basis */
+ FNV0_64_INIT /* 64 bit FNV-0 initial basis */
+
+ FNV-1:
+
+ FNV1_32_INIT /* 32 bit FNV-1 initial basis */
+ FNV1_64_INIT /* 64 bit FNV-1 initial basis */
+
+ FNV-1a:
+
+ FNV1A_32_INIT /* 32 bit FNV-1a initial basis */
+ FNV1A_64_INIT /* 64 bit FNV-1a initial basis */
+
+For example to perform a 64 bit FNV-1 hash:
+
+ #include "fnv.h"
+
+ Fnv64_t hash_val;
+
+ hash_val = fnv_64_str("a string", FNV1_64_INIT);
+ hash_val = fnv_64_str("more string", hash_val);
+
+produces the same final hash value as:
+
+ hash_val = fnv_64_str("a stringmore string", FNV1_64_INIT);
+
+NOTE: If one used 'FNV0_64_INIT' instead of 'FNV1_64_INIT' one would get the
+ historic FNV-0 hash instead recommended FNV-1 hash.
+
+To perform a 32 bit FNV-1 hash:
+
+ #include "fnv.h"
+
+ Fnv32_t hash_val;
+
+ hash_val = fnv_32_buf(buf, length_of_buf, FNV1_32_INIT);
+ hash_val = fnv_32_str("more data", hash_val);
+
+To perform a 64 bit FNV-1a hash:
+
+ #include "fnv.h"
+
+ Fnv64_t hash_val;
+
+ hash_val = fnv_64a_buf(buf, length_of_buf, FNV1_64_INIT);
+ hash_val = fnv_64a_str("more data", hash_val);
+
+=-=
+
+chongo <Landon Curt Noll> /\oo/\
+http://www.isthe.com/chongo
+
+Share and Enjoy!
diff --git a/lib/fnv/fnv.h b/lib/fnv/fnv.h
new file mode 100644
index 0000000000..2083a4aa23
--- /dev/null
+++ b/lib/fnv/fnv.h
@@ -0,0 +1,249 @@
+/*
+ * fnv - Fowler/Noll/Vo- hash code
+ *
+ * @(#) $Revision: 5.4 $
+ * @(#) $Id: fnv.h,v 5.4 2009/07/30 22:49:13 chongo Exp $
+ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/fnv.h,v $
+ *
+ ***
+ *
+ * Fowler/Noll/Vo- hash
+ *
+ * The basis of this hash algorithm was taken from an idea sent
+ * as reviewer comments to the IEEE POSIX P1003.2 committee by:
+ *
+ * Phong Vo (http://www.research.att.com/info/kpv/)
+ * Glenn Fowler (http://www.research.att.com/~gsf/)
+ *
+ * In a subsequent ballot round:
+ *
+ * Landon Curt Noll (http://www.isthe.com/chongo/)
+ *
+ * improved on their algorithm. Some people tried this hash
+ * and found that it worked rather well. In an EMail message
+ * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+ *
+ * FNV hashes are designed to be fast while maintaining a low
+ * collision rate. The FNV speed allows one to quickly hash lots
+ * of data while maintaining a reasonable collision rate. See:
+ *
+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ * for more details as well as other forms of the FNV hash.
+ *
+ ***
+ *
+ * NOTE: The FNV-0 historic hash is not recommended. One should use
+ * the FNV-1 hash instead.
+ *
+ * To use the 32 bit FNV-0 historic hash, pass FNV0_32_INIT as the
+ * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
+ *
+ * To use the 64 bit FNV-0 historic hash, pass FNV0_64_INIT as the
+ * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
+ *
+ * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the
+ * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
+ *
+ * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the
+ * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
+ *
+ * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
+ * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
+ *
+ * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the
+ * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str().
+ *
+ ***
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+#if !defined(__FNV_H__)
+#define __FNV_H__
+
+#include <sys/types.h>
+
+#define FNV_VERSION "5.0.2" /* @(#) FNV Version */
+
+
+/*
+ * 32 bit FNV-0 hash type
+ */
+typedef u_int32_t Fnv32_t;
+
+
+/*
+ * 32 bit FNV-0 zero initial basis
+ *
+ * This historic hash is not recommended. One should use
+ * the FNV-1 hash and initial basis instead.
+ */
+#define FNV0_32_INIT ((Fnv32_t)0)
+
+
+/*
+ * 32 bit FNV-1 and FNV-1a non-zero initial basis
+ *
+ * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets:
+ *
+ * chongo <Landon Curt Noll> /\../\
+ *
+ * NOTE: The \'s above are not back-slashing escape characters.
+ * They are literal ASCII backslash 0x5c characters.
+ *
+ * NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition.
+ */
+#define FNV1_32_INIT ((Fnv32_t)0x811c9dc5)
+#define FNV1_32A_INIT FNV1_32_INIT
+
+
+/*
+ * determine how 64 bit unsigned values are represented
+ */
+#include "longlong.h"
+
+
+/*
+ * 64 bit FNV-0 hash
+ */
+#if defined(HAVE_64BIT_LONG_LONG)
+typedef u_int64_t Fnv64_t;
+#else /* HAVE_64BIT_LONG_LONG */
+typedef struct {
+ u_int32_t w32[2]; /* w32[0] is low order, w32[1] is high order word */
+} Fnv64_t;
+#endif /* HAVE_64BIT_LONG_LONG */
+
+
+/*
+ * 64 bit FNV-0 zero initial basis
+ *
+ * This historic hash is not recommended. One should use
+ * the FNV-1 hash and initial basis instead.
+ */
+#if defined(HAVE_64BIT_LONG_LONG)
+#define FNV0_64_INIT ((Fnv64_t)0)
+#else /* HAVE_64BIT_LONG_LONG */
+extern const Fnv64_t fnv0_64_init;
+#define FNV0_64_INIT (fnv0_64_init)
+#endif /* HAVE_64BIT_LONG_LONG */
+
+
+/*
+ * 64 bit FNV-1 non-zero initial basis
+ *
+ * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets:
+ *
+ * chongo <Landon Curt Noll> /\../\
+ *
+ * NOTE: The \'s above are not back-slashing escape characters.
+ * They are literal ASCII backslash 0x5c characters.
+ *
+ * NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition.
+ */
+#if defined(HAVE_64BIT_LONG_LONG)
+#define FNV1_64_INIT ((Fnv64_t)0xcbf29ce484222325ULL)
+#define FNV1A_64_INIT FNV1_64_INIT
+#else /* HAVE_64BIT_LONG_LONG */
+extern const fnv1_64_init;
+extern const Fnv64_t fnv1a_64_init;
+#define FNV1_64_INIT (fnv1_64_init)
+#define FNV1A_64_INIT (fnv1a_64_init)
+#endif /* HAVE_64BIT_LONG_LONG */
+
+
+/*
+ * hash types
+ */
+enum fnv_type {
+ FNV_NONE = 0, /* invalid FNV hash type */
+ FNV0_32 = 1, /* FNV-0 32 bit hash */
+ FNV1_32 = 2, /* FNV-1 32 bit hash */
+ FNV1a_32 = 3, /* FNV-1a 32 bit hash */
+ FNV0_64 = 4, /* FNV-0 64 bit hash */
+ FNV1_64 = 5, /* FNV-1 64 bit hash */
+ FNV1a_64 = 6, /* FNV-1a 64 bit hash */
+};
+
+
+/*
+ * these test vectors are used as part o the FNV test suite
+ */
+struct test_vector {
+ void *buf; /* start of test vector buffer */
+ int len; /* length of test vector */
+};
+struct fnv0_32_test_vector {
+ struct test_vector *test; /* test vector buffer to hash */
+ Fnv32_t fnv0_32; /* expected FNV-0 32 bit hash value */
+};
+struct fnv1_32_test_vector {
+ struct test_vector *test; /* test vector buffer to hash */
+ Fnv32_t fnv1_32; /* expected FNV-1 32 bit hash value */
+};
+struct fnv1a_32_test_vector {
+ struct test_vector *test; /* test vector buffer to hash */
+ Fnv32_t fnv1a_32; /* expected FNV-1a 32 bit hash value */
+};
+struct fnv0_64_test_vector {
+ struct test_vector *test; /* test vector buffer to hash */
+ Fnv64_t fnv0_64; /* expected FNV-0 64 bit hash value */
+};
+struct fnv1_64_test_vector {
+ struct test_vector *test; /* test vector buffer to hash */
+ Fnv64_t fnv1_64; /* expected FNV-1 64 bit hash value */
+};
+struct fnv1a_64_test_vector {
+ struct test_vector *test; /* test vector buffer to hash */
+ Fnv64_t fnv1a_64; /* expected FNV-1a 64 bit hash value */
+};
+
+
+/*
+ * external functions
+ */
+/* hash_32.c */
+extern Fnv32_t fnv_32_buf(void *buf, size_t len, Fnv32_t hashval);
+extern Fnv32_t fnv_32_str(char *buf, Fnv32_t hashval);
+
+/* hash_32a.c */
+extern Fnv32_t fnv_32a_buf(void *buf, size_t len, Fnv32_t hashval);
+extern Fnv32_t fnv_32a_str(char *buf, Fnv32_t hashval);
+
+/* hash_64.c */
+extern Fnv64_t fnv_64_buf(void *buf, size_t len, Fnv64_t hashval);
+extern Fnv64_t fnv_64_str(char *buf, Fnv64_t hashval);
+
+/* hash_64a.c */
+extern Fnv64_t fnv_64a_buf(void *buf, size_t len, Fnv64_t hashval);
+extern Fnv64_t fnv_64a_str(char *buf, Fnv64_t hashval);
+
+/* test_fnv.c */
+extern struct test_vector fnv_test_str[];
+extern struct fnv0_32_test_vector fnv0_32_vector[];
+extern struct fnv1_32_test_vector fnv1_32_vector[];
+extern struct fnv1a_32_test_vector fnv1a_32_vector[];
+extern struct fnv0_64_test_vector fnv0_64_vector[];
+extern struct fnv1_64_test_vector fnv1_64_vector[];
+extern struct fnv1a_64_test_vector fnv1a_64_vector[];
+extern void unknown_hash_type(char *prog, enum fnv_type type, int code);
+extern void print_fnv32(Fnv32_t hval, Fnv32_t mask, int verbose, char *arg);
+extern void print_fnv64(Fnv64_t hval, Fnv64_t mask, int verbose, char *arg);
+
+
+#endif /* __FNV_H__ */
diff --git a/lib/fnv/fnv32.c b/lib/fnv/fnv32.c
new file mode 100644
index 0000000000..58c61f03fc
--- /dev/null
+++ b/lib/fnv/fnv32.c
@@ -0,0 +1,467 @@
+/*
+ * fnv32 - 32 bit Fowler/Noll/Vo hash of a buffer or string
+ *
+ * @(#) $Revision: 5.5 $
+ * @(#) $Id: fnv32.c,v 5.5 2012/03/21 01:38:12 chongo Exp $
+ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/fnv32.c,v $
+ *
+ ***
+ *
+ * Fowler/Noll/Vo hash
+ *
+ * The basis of this hash algorithm was taken from an idea sent
+ * as reviewer comments to the IEEE POSIX P1003.2 committee by:
+ *
+ * Phong Vo (http://www.research.att.com/info/kpv/)
+ * Glenn Fowler (http://www.research.att.com/~gsf/)
+ *
+ * In a subsequent ballot round:
+ *
+ * Landon Curt Noll (http://www.isthe.com/chongo/)
+ *
+ * improved on their algorithm. Some people tried this hash
+ * and found that it worked rather well. In an EMail message
+ * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+ *
+ * FNV hashes are designed to be fast while maintaining a low
+ * collision rate. The FNV speed allows one to quickly hash lots
+ * of data while maintaining a reasonable collision rate. See:
+ *
+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ * for more details as well as other forms of the FNV hash.
+ *
+ ***
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include "longlong.h"
+#include "fnv.h"
+
+#define WIDTH 32 /* bit width of hash */
+
+#define BUF_SIZE (32*1024) /* number of bytes to hash at a time */
+
+static char *usage =
+"usage: %s [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]\n"
+"\n"
+"\t-b bcnt\tmask off all but the lower bcnt bits (default 32)\n"
+"\t-m\tmultiple hashes, one per line for each arg\n"
+"\t-s\thash arg as a string (ignoring terminating NUL bytes)\n"
+"\t-t code\t test hash code: (0 ==> generate test vectors\n"
+"\t\t\t\t 1 ==> validate against FNV test vectors)\n"
+"\t-v\tverbose mode, print arg after hash (implies -m)\n"
+"\targ\tstring (if -s was given) or filename (default stdin)\n"
+"\n"
+"\tNOTE: Programs that begin with fnv0 implement the FNV-0 hash.\n"
+"\t The FNV-0 hash is historic FNV algorithm that is now deprecated.\n"
+"\n"
+"\tSee http://www.isthe.com/chongo/tech/comp/fnv/index.html for more info.\n"
+"\n"
+"\t@(#) FNV Version: %s\n";
+static char *program; /* our name */
+
+
+/*
+ * test_fnv32 - test the FNV32 hash
+ *
+ * given:
+ * hash_type type of FNV hash to test
+ * init_hval initial hash value
+ * mask lower bit mask
+ * v_flag 1 => print test failure info on stderr
+ * code 0 ==> generate FNV test vectors
+ * 1 ==> validate against FNV test vectors
+ *
+ * returns: 0 ==> OK, else test vector failure number
+ */
+static int
+test_fnv32(enum fnv_type hash_type, Fnv32_t init_hval,
+ Fnv32_t mask, int v_flag, int code)
+{
+ struct test_vector *t; /* FNV test vestor */
+ Fnv32_t hval; /* current hash value */
+ int tstnum; /* test vector that failed, starting at 1 */
+
+ /*
+ * print preamble if generating test vectors
+ */
+ if (code == 0) {
+ switch (hash_type) {
+ case FNV0_32:
+ printf("struct fnv0_32_test_vector fnv0_32_vector[] = {\n");
+ break;
+ case FNV1_32:
+ printf("struct fnv1_32_test_vector fnv1_32_vector[] = {\n");
+ break;
+ case FNV1a_32:
+ printf("struct fnv1a_32_test_vector fnv1a_32_vector[] = {\n");
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 12); /* exit(12) */
+ /*NOTREACHED*/
+ }
+ }
+
+ /*
+ * loop thru all test vectors
+ */
+ for (t = fnv_test_str, tstnum = 1; t->buf != NULL; ++t, ++tstnum) {
+
+ /*
+ * compute the FNV hash
+ */
+ hval = init_hval;
+ switch (hash_type) {
+ case FNV0_32:
+ case FNV1_32:
+ hval = fnv_32_buf(t->buf, t->len, hval);
+ break;
+ case FNV1a_32:
+ hval = fnv_32a_buf(t->buf, t->len, hval);
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 13); /* exit(13) */
+ /*NOTREACHED*/
+ }
+
+ /*
+ * print the vector
+ */
+ switch (code) {
+ case 0: /* generate the test vector */
+ printf(" { &fnv_test_str[%d], (Fnv32_t) 0x%08lxUL },\n",
+ tstnum-1, hval & mask);
+ break;
+ case 1: /* validate against test vector */
+ switch (hash_type) {
+ case FNV0_32:
+ if ((hval&mask) != (fnv0_32_vector[tstnum-1].fnv0_32 & mask)) {
+ if (v_flag) {
+ fprintf(stderr, "%s: failed fnv0_32 test # %d\n",
+ program, tstnum);
+ fprintf(stderr, "%s: test # 1 is 1st test\n", program);
+ fprintf(stderr,
+ "%s: expected 0x%08lx != generated: 0x%08lx\n",
+ program, (hval&mask),
+ (fnv0_32_vector[tstnum-1].fnv0_32 & mask));
+ }
+ return tstnum;
+ }
+ break;
+ case FNV1_32:
+ if ((hval&mask) != (fnv1_32_vector[tstnum-1].fnv1_32 & mask)) {
+ if (v_flag) {
+ fprintf(stderr, "%s: failed fnv1_32 test # %d\n",
+ program, tstnum);
+ fprintf(stderr, "%s: test # 1 is 1st test\n", program);
+ fprintf(stderr,
+ "%s: expected 0x%08lx != generated: 0x%08lx\n",
+ program, (hval&mask),
+ (fnv1_32_vector[tstnum-1].fnv1_32 & mask));
+ }
+ return tstnum;
+ }
+ break;
+ case FNV1a_32:
+ if ((hval&mask) != (fnv1a_32_vector[tstnum-1].fnv1a_32 &mask)) {
+ if (v_flag) {
+ fprintf(stderr, "%s: failed fnv1a_32 test # %d\n",
+ program, tstnum);
+ fprintf(stderr, "%s: test # 1 is 1st test\n", program);
+ fprintf(stderr,
+ "%s: expected 0x%08lx != generated: 0x%08lx\n",
+ program, (hval&mask),
+ (fnv1a_32_vector[tstnum-1].fnv1a_32 & mask));
+ }
+ return tstnum;
+ }
+ break;
+ }
+ break;
+ default:
+ fprintf(stderr, "%s: -m %d not implemented yet\n", program, code);
+ exit(14);
+ }
+ }
+
+ /*
+ * print completion if generating test vectors
+ */
+ if (code == 0) {
+ printf(" { NULL, 0 }\n");
+ printf("};\n");
+ }
+
+ /*
+ * no failures, return code 0 ==> all OK
+ */
+ return 0;
+}
+
+
+/*
+ * main - the main function
+ *
+ * See the above usage for details.
+ */
+int
+main(int argc, char *argv[])
+{
+ char buf[BUF_SIZE+1]; /* read buffer */
+ int readcnt; /* number of characters written */
+ Fnv32_t hval; /* current hash value */
+ int s_flag = 0; /* 1 => -s was given, hash args as strings */
+ int m_flag = 0; /* 1 => print multiple hashes, one per arg */
+ int v_flag = 0; /* 1 => verbose hash print */
+ int b_flag = WIDTH; /* -b flag value */
+ int t_flag = -1; /* FNV test vector code (0=>print, 1=>test) */
+ enum fnv_type hash_type = FNV_NONE; /* type of FNV hash to perform */
+ Fnv32_t bmask; /* mask to apply to output */
+ extern char *optarg; /* option argument */
+ extern int optind; /* argv index of the next arg */
+ int fd; /* open file to process */
+ char *p;
+ int i;
+
+ /*
+ * parse args
+ */
+ program = argv[0];
+ while ((i = getopt(argc, argv, "b:mst:v")) != -1) {
+ switch (i) {
+ case 'b': /* bcnt bit mask count */
+ b_flag = atoi(optarg);
+ break;
+ case 'm': /* print multiple hashes, one per arg */
+ m_flag = 1;
+ break;
+ case 's': /* hash args as strings */
+ s_flag = 1;
+ break;
+ case 't': /* FNV test vector code */
+ t_flag = atoi(optarg);
+ if (t_flag < 0 || t_flag > 1) {
+ fprintf(stderr, "%s: -t code must be 0 or 1\n", program);
+ fprintf(stderr, usage, program, FNV_VERSION);
+ exit(1);
+ }
+ m_flag = 1;
+ break;
+ case 'v': /* verbose hash print */
+ m_flag = 1;
+ v_flag = 1;
+ break;
+ default:
+ fprintf(stderr, usage, program, FNV_VERSION);
+ exit(1);
+ }
+ }
+ /* -t code incompatible with -b, -m and args */
+ if (t_flag >= 0) {
+ if (b_flag != WIDTH) {
+ fprintf(stderr, "%s: -t code incompatible with -b\n", program);
+ exit(2);
+ }
+ if (s_flag != 0) {
+ fprintf(stderr, "%s: -t code incompatible with -s\n", program);
+ exit(3);
+ }
+ if (optind < argc) {
+ fprintf(stderr, "%s: -t code incompatible args\n", program);
+ exit(4);
+ }
+ }
+ /* -s requires at least 1 arg */
+ if (s_flag && optind >= argc) {
+ fprintf(stderr, usage, program, FNV_VERSION);
+ exit(5);
+ }
+ /* limit -b values */
+ if (b_flag < 0 || b_flag > WIDTH) {
+ fprintf(stderr, "%s: -b bcnt: %d must be >= 0 and < %d\n",
+ program, b_flag, WIDTH);
+ exit(6);
+ }
+ if (b_flag == WIDTH) {
+ bmask = (Fnv32_t)0xffffffff;
+ } else {
+ bmask = (Fnv32_t)((1 << b_flag) - 1);
+ }
+
+ /*
+ * start with the initial basis depending on the hash type
+ */
+ p = strrchr(program, '/');
+ if (p == NULL) {
+ p = program;
+ } else {
+ ++p;
+ }
+ if (strcmp(p, "fnv032") == 0) {
+ /* using non-recommended FNV-0 and zero initial basis */
+ hval = FNV0_32_INIT;
+ hash_type = FNV0_32;
+ } else if (strcmp(p, "fnv132") == 0) {
+ /* using FNV-1 and non-zero initial basis */
+ hval = FNV1_32_INIT;
+ hash_type = FNV1_32;
+ } else if (strcmp(p, "fnv1a32") == 0) {
+ /* start with the FNV-1a initial basis */
+ hval = FNV1_32A_INIT;
+ hash_type = FNV1a_32;
+ } else {
+ fprintf(stderr, "%s: unknown program name, unknown hash type\n",
+ program);
+ exit(7);
+ }
+
+ /*
+ * FNV test vector processing, if needed
+ */
+ if (t_flag >= 0) {
+ int code; /* test vector that failed, starting at 1 */
+
+ /*
+ * perform all tests
+ */
+ code = test_fnv32(hash_type, hval, bmask, v_flag, t_flag);
+
+ /*
+ * evaluate the tests
+ */
+ if (code == 0) {
+ if (v_flag) {
+ printf("passed\n");
+ }
+ exit(0);
+ } else {
+ printf("failed vector (1 is 1st test): %d\n", code);
+ exit(8);
+ }
+ }
+
+ /*
+ * string hashing
+ */
+ if (s_flag) {
+
+ /* hash any other strings */
+ for (i=optind; i < argc; ++i) {
+ switch (hash_type) {
+ case FNV0_32:
+ case FNV1_32:
+ hval = fnv_32_str(argv[i], hval);
+ break;
+ case FNV1a_32:
+ hval = fnv_32a_str(argv[i], hval);
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 9); /* exit(9) */
+ /*NOTREACHED*/
+ }
+ if (m_flag) {
+ print_fnv32(hval, bmask, v_flag, argv[i]);
+ }
+ }
+
+
+ /*
+ * file hashing
+ */
+ } else {
+
+ /*
+ * case: process only stdin
+ */
+ if (optind >= argc) {
+
+ /* case: process only stdin */
+ while ((readcnt = read(0, buf, BUF_SIZE)) > 0) {
+ switch (hash_type) {
+ case FNV0_32:
+ case FNV1_32:
+ hval = fnv_32_buf(buf, readcnt, hval);
+ break;
+ case FNV1a_32:
+ hval = fnv_32a_buf(buf, readcnt, hval);
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 10); /* exit(10) */
+ /*NOTREACHED*/
+ }
+ }
+ if (m_flag) {
+ print_fnv32(hval, bmask, v_flag, "(stdin)");
+ }
+
+ } else {
+
+ /*
+ * process any other files
+ */
+ for (i=optind; i < argc; ++i) {
+
+ /* open the file */
+ fd = open(argv[i], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: unable to open file: %s\n",
+ program, argv[i]);
+ exit(4);
+ }
+
+ /* hash the file */
+ while ((readcnt = read(fd, buf, BUF_SIZE)) > 0) {
+ switch (hash_type) {
+ case FNV0_32:
+ case FNV1_32:
+ hval = fnv_32_buf(buf, readcnt, hval);
+ break;
+ case FNV1a_32:
+ hval = fnv_32a_buf(buf, readcnt, hval);
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 11);/* exit(11) */
+ /*NOTREACHED*/
+ }
+ }
+
+ /* finish processing the file */
+ if (m_flag) {
+ print_fnv32(hval, bmask, v_flag, argv[i]);
+ }
+ close(fd);
+ }
+ }
+ }
+
+ /*
+ * report hash and exit
+ */
+ if (!m_flag) {
+ print_fnv32(hval, bmask, v_flag, "");
+ }
+ return 0; /* exit(0); */
+}
diff --git a/lib/fnv/fnv64.c b/lib/fnv/fnv64.c
new file mode 100644
index 0000000000..0662d4d657
--- /dev/null
+++ b/lib/fnv/fnv64.c
@@ -0,0 +1,591 @@
+/*
+ * fnv_64 - 64 bit Fowler/Noll/Vo hash of a buffer or string
+ *
+ * @(#) $Revision: 5.5 $
+ * @(#) $Id: fnv64.c,v 5.5 2012/03/21 01:38:12 chongo Exp $
+ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/fnv64.c,v $
+ *
+ ***
+ *
+ * Fowler/Noll/Vo hash
+ *
+ * The basis of this hash algorithm was taken from an idea sent
+ * as reviewer comments to the IEEE POSIX P1003.2 committee by:
+ *
+ * Phong Vo (http://www.research.att.com/info/kpv/)
+ * Glenn Fowler (http://www.research.att.com/~gsf/)
+ *
+ * In a subsequent ballot round:
+ *
+ * Landon Curt Noll (http://www.isthe.com/chongo/)
+ *
+ * improved on their algorithm. Some people tried this hash
+ * and found that it worked rather well. In an EMail message
+ * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+ *
+ * FNV hashes are designed to be fast while maintaining a low
+ * collision rate. The FNV speed allows one to quickly hash lots
+ * of data while maintaining a reasonable collision rate. See:
+ *
+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ * for more details as well as other forms of the FNV hash.
+ *
+ ***
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include "longlong.h"
+#include "fnv.h"
+
+#define WIDTH 64 /* bit width of hash */
+
+#define BUF_SIZE (32*1024) /* number of bytes to hash at a time */
+
+static char *usage =
+"usage: %s [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]\n"
+"\n"
+"\t-b bcnt\tmask off all but the lower bcnt bits (default 64)\n"
+"\t-m\tmultiple hashes, one per line for each arg\n"
+"\t-s\thash arg as a string (ignoring terminating NUL bytes)\n"
+"\t-t code\t test hash code: (0 ==> generate test vectors\n"
+"\t\t\t\t 1 ==> validate against FNV test vectors)\n"
+"\t-v\tverbose mode, print arg after hash (implies -m)\n"
+"\targ\tstring (if -s was given) or filename (default stdin)\n"
+"\n"
+"\tNOTE: Programs that begin with fnv0 implement the FNV-0 hash.\n"
+"\t The FNV-0 hash is historic FNV algorithm that is now deprecated.\n"
+"\n"
+"\tSee http://www.isthe.com/chongo/tech/comp/fnv/index.html for more info.\n"
+"\n"
+"\t@(#) FNV Version: %s\n";
+static char *program; /* our name */
+
+
+/*
+ * test_fnv64 - test the FNV64 hash
+ *
+ * given:
+ * hash_type type of FNV hash to test
+ * init_hval initial hash value
+ * mask lower bit mask
+ * v_flag 1 => print test failure info on stderr
+ * code 0 ==> generate FNV test vectors
+ * 1 ==> validate against FNV test vectors
+ *
+ * returns: 0 ==> OK, else test vector failure number
+ */
+static int
+test_fnv64(enum fnv_type hash_type, Fnv64_t init_hval,
+ Fnv64_t mask, int v_flag, int code)
+{
+ struct test_vector *t; /* FNV test vestor */
+ Fnv64_t hval; /* current hash value */
+ int tstnum; /* test vector that failed, starting at 1 */
+
+ /*
+ * print preamble if generating test vectors
+ */
+ if (code == 0) {
+ switch (hash_type) {
+ case FNV0_64:
+ printf("struct fnv0_64_test_vector fnv0_64_vector[] = {\n");
+ break;
+ case FNV1_64:
+ printf("struct fnv1_64_test_vector fnv1_64_vector[] = {\n");
+ break;
+ case FNV1a_64:
+ printf("struct fnv1a_64_test_vector fnv1a_64_vector[] = {\n");
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 12); /* exit(12) */
+ /*NOTREACHED*/
+ }
+ }
+
+ /*
+ * loop thru all test vectors
+ */
+ for (t = fnv_test_str, tstnum = 1; t->buf != NULL; ++t, ++tstnum) {
+
+ /*
+ * compute the FNV hash
+ */
+ hval = init_hval;
+ switch (hash_type) {
+ case FNV0_64:
+ case FNV1_64:
+ hval = fnv_64_buf(t->buf, t->len, hval);
+ break;
+ case FNV1a_64:
+ hval = fnv_64a_buf(t->buf, t->len, hval);
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 13); /* exit(13) */
+ /*NOTREACHED*/
+ }
+
+ /*
+ * print the vector
+ */
+#if defined(HAVE_64BIT_LONG_LONG)
+ /*
+ * HAVE_64BIT_LONG_LONG testing
+ */
+ switch (code) {
+ case 0: /* generate the test vector */
+ printf(" { &fnv_test_str[%d], (Fnv64_t) 0x%016llxULL },\n",
+ tstnum-1, hval & mask);
+ break;
+
+ case 1: /* validate against test vector */
+ switch (hash_type) {
+ case FNV0_64:
+ if ((hval&mask) != (fnv0_64_vector[tstnum-1].fnv0_64 & mask)) {
+ if (v_flag) {
+ fprintf(stderr, "%s: failed fnv0_64 test # %d\n",
+ program, tstnum);
+ fprintf(stderr, "%s: test # 1 is 1st test\n", program);
+ fprintf(stderr,
+ "%s: expected 0x%016llx != generated: 0x%016llx\n",
+ program,
+ (hval&mask),
+ (fnv0_64_vector[tstnum-1].fnv0_64 & mask));
+ }
+ return tstnum;
+ }
+ break;
+ case FNV1_64:
+ if ((hval&mask) != (fnv1_64_vector[tstnum-1].fnv1_64 & mask)) {
+ if (v_flag) {
+ fprintf(stderr, "%s: failed fnv1_64 test # %d\n",
+ program, tstnum);
+ fprintf(stderr, "%s: test # 1 is 1st test\n", program);
+ fprintf(stderr,
+ "%s: expected 0x%016llx != generated: 0x%016llx\n",
+ program,
+ (hval&mask),
+ (fnv1_64_vector[tstnum-1].fnv1_64 & mask));
+ }
+ return tstnum;
+ }
+ break;
+ case FNV1a_64:
+ if ((hval&mask) != (fnv1a_64_vector[tstnum-1].fnv1a_64 &mask)) {
+ if (v_flag) {
+ fprintf(stderr, "%s: failed fnv1a_64 test # %d\n",
+ program, tstnum);
+ fprintf(stderr, "%s: test # 1 is 1st test\n", program);
+ fprintf(stderr,
+ "%s: expected 0x%016llx != generated: 0x%016llx\n",
+ program,
+ (hval&mask),
+ (fnv1a_64_vector[tstnum-1].fnv1a_64 & mask));
+ }
+ return tstnum;
+ }
+ break;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "%s: -m %d not implemented yet\n", program, code);
+ exit(14);
+ }
+#else /* HAVE_64BIT_LONG_LONG */
+ /*
+ * non HAVE_64BIT_LONG_LONG testing
+ */
+ switch (code) {
+ case 0: /* generate the test vector */
+ printf(" { &fnv_test_str[%d], "
+ "(Fnv64_t) {0x%08lxUL, 0x%08lxUL} },\n",
+ tstnum-1,
+ (hval.w32[0] & mask.w32[0]),
+ (hval.w32[1] & mask.w32[1]));
+ break;
+
+ case 1: /* validate against test vector */
+ switch (hash_type) {
+ case FNV0_64:
+ if (((hval.w32[0] & mask.w32[0]) !=
+ (fnv0_64_vector[tstnum-1].fnv0_64.w32[0] &
+ mask.w32[0])) &&
+ ((hval.w32[1] & mask.w32[1]) !=
+ (fnv0_64_vector[tstnum-1].fnv0_64.w32[1] &
+ mask.w32[1]))) {
+ if (v_flag) {
+ fprintf(stderr, "%s: failed fnv0_64 test # %d\n",
+ program, tstnum);
+ fprintf(stderr, "%s: test # 1 is 1st test\n", program);
+ fprintf(stderr,
+ "%s: expected 0x%08llx%08llx != "
+ "generated: 0x%08llx%08llx\n",
+ program,
+ (hval.w32[0] & mask.w32[0]),
+ (hval.w32[1] & mask.w32[1]),
+ ((fnv0_64_vector[tstnum-1].fnv0_64.w32[0] &
+ mask.w32[0])),
+ ((fnv0_64_vector[tstnum-1].fnv0_64.w32[1] &
+ mask.w32[1])));
+ }
+ return tstnum;
+ }
+ break;
+ case FNV1_64:
+ if (((hval.w32[0] & mask.w32[0]) !=
+ (fnv1_64_vector[tstnum-1].fnv1_64.w32[0] &
+ mask.w32[0])) &&
+ ((hval.w32[1] & mask.w32[1]) !=
+ (fnv1_64_vector[tstnum-1].fnv1_64.w32[1] &
+ mask.w32[1]))) {
+ if (v_flag) {
+ fprintf(stderr, "%s: failed fnv1_64 test # %d\n",
+ program, tstnum);
+ fprintf(stderr, "%s: test # 1 is 1st test\n", program);
+ fprintf(stderr,
+ "%s: expected 0x%08llx%08llx != "
+ "generated: 0x%08llx%08llx\n",
+ program,
+ (hval.w32[0] & mask.w32[0]),
+ (hval.w32[1] & mask.w32[1]),
+ ((fnv1_64_vector[tstnum-1].fnv1_64.w32[0] &
+ mask.w32[0])),
+ ((fnv1_64_vector[tstnum-1].fnv1_64.w32[1] &
+ mask.w32[1])));
+ }
+ return tstnum;
+ }
+ break;
+ case FNV1a_64:
+ if (((hval.w32[0] & mask.w32[0]) !=
+ (fnv1a_64_vector[tstnum-1].fnv1a_64.w32[0] &
+ mask.w32[0])) &&
+ ((hval.w32[1] & mask.w32[1]) !=
+ (fnv1a_64_vector[tstnum-1].fnv1a_64.w32[1] &
+ mask.w32[1]))) {
+ if (v_flag) {
+ fprintf(stderr, "%s: failed fnv1a_64 test # %d\n",
+ program, tstnum);
+ fprintf(stderr, "%s: test # 1 is 1st test\n", program);
+ fprintf(stderr,
+ "%s: expected 0x%08llx%08llx != "
+ "generated: 0x%08llx%08llx\n",
+ program,
+ (hval.w32[0] & mask.w32[0]),
+ (hval.w32[1] & mask.w32[1]),
+ ((fnv1a_64_vector[tstnum-1].fnv1a_64.w32[0] &
+ mask.w32[0])),
+ ((fnv1a_64_vector[tstnum-1].fnv1a_64.w32[1] &
+ mask.w32[1])));
+ }
+ return tstnum;
+ }
+ break;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "%s: -m %d not implemented yet\n", program, code);
+ exit(15);
+ }
+#endif /* HAVE_64BIT_LONG_LONG */
+ }
+
+ /*
+ * print completion if generating test vectors
+ */
+ if (code == 0) {
+#if defined(HAVE_64BIT_LONG_LONG)
+ printf(" { NULL, (Fnv64_t) 0 }\n");
+#else /* HAVE_64BIT_LONG_LONG */
+ printf(" { NULL, (Fnv64_t) {0,0} }\n");
+#endif /* HAVE_64BIT_LONG_LONG */
+ printf("};\n");
+ }
+
+ /*
+ * no failures, return code 0 ==> all OK
+ */
+ return 0;
+}
+
+
+/*
+ * main - the main function
+ *
+ * See the above usage for details.
+ */
+int
+main(int argc, char *argv[])
+{
+ char buf[BUF_SIZE+1]; /* read buffer */
+ int readcnt; /* number of characters written */
+ Fnv64_t hval; /* current hash value */
+ int s_flag = 0; /* 1 => -s was given, hash args as strings */
+ int m_flag = 0; /* 1 => print multiple hashes, one per arg */
+ int v_flag = 0; /* 1 => verbose hash print */
+ int b_flag = WIDTH; /* -b flag value */
+ int t_flag = -1; /* FNV test vector code (0=>print, 1=>test) */
+ enum fnv_type hash_type = FNV_NONE; /* type of FNV hash to perform */
+ Fnv64_t bmask; /* mask to apply to output */
+ extern char *optarg; /* option argument */
+ extern int optind; /* argv index of the next arg */
+ int fd; /* open file to process */
+ char *p;
+ int i;
+
+ /*
+ * parse args
+ */
+ program = argv[0];
+ while ((i = getopt(argc, argv, "b:mst:v")) != -1) {
+ switch (i) {
+ case 'b': /* bcnt bit mask count */
+ b_flag = atoi(optarg);
+ break;
+ case 'm': /* print multiple hashes, one per arg */
+ m_flag = 1;
+ break;
+ case 's': /* hash args as strings */
+ s_flag = 1;
+ break;
+ case 't': /* FNV test vector code */
+ t_flag = atoi(optarg);
+ if (t_flag < 0 || t_flag > 1) {
+ fprintf(stderr, "%s: -t code must be 0 or 1\n", program);
+ fprintf(stderr, usage, program, FNV_VERSION);
+ exit(1);
+ }
+ m_flag = 1;
+ break;
+ case 'v': /* verbose hash print */
+ m_flag = 1;
+ v_flag = 1;
+ break;
+ default:
+ fprintf(stderr, usage, program, FNV_VERSION);
+ exit(1);
+ }
+ }
+ /* -t code incompatible with -b, -m and args */
+ if (t_flag >= 0) {
+ if (b_flag != WIDTH) {
+ fprintf(stderr, "%s: -t code incompatible with -b\n", program);
+ exit(2);
+ }
+ if (s_flag != 0) {
+ fprintf(stderr, "%s: -t code incompatible with -s\n", program);
+ exit(3);
+ }
+ if (optind < argc) {
+ fprintf(stderr, "%s: -t code incompatible args\n", program);
+ exit(4);
+ }
+ }
+ /* -s requires at least 1 arg */
+ if (s_flag && optind >= argc) {
+ fprintf(stderr, usage, program, FNV_VERSION);
+ exit(5);
+ }
+ /* limit -b values */
+ if (b_flag < 0 || b_flag > WIDTH) {
+ fprintf(stderr, "%s: -b bcnt: %d must be >= 0 and < %d\n",
+ program, b_flag, WIDTH);
+ exit(6);
+ }
+#if defined(HAVE_64BIT_LONG_LONG)
+ if (b_flag == WIDTH) {
+ bmask = (Fnv64_t)0xffffffffffffffffULL;
+ } else {
+ bmask = (Fnv64_t)((1ULL << b_flag) - 1ULL);
+ }
+#else /* HAVE_64BIT_LONG_LONG */
+ if (b_flag == WIDTH) {
+ bmask.w32[0] = 0xffffffffUL;
+ bmask.w32[1] = 0xffffffffUL;
+ } else if (b_flag >= WIDTH/2) {
+ bmask.w32[0] = 0xffffffffUL;
+ bmask.w32[1] = ((1UL << (b_flag-(WIDTH/2))) - 1UL);
+ } else {
+ bmask.w32[0] = ((1UL << b_flag) - 1UL);
+ bmask.w32[1] = 0UL;
+ }
+#endif /* HAVE_64BIT_LONG_LONG */
+
+ /*
+ * start with the initial basis depending on the hash type
+ */
+ p = strrchr(program, '/');
+ if (p == NULL) {
+ p = program;
+ } else {
+ ++p;
+ }
+ if (strcmp(p, "fnv064") == 0 || strcmp(p, "no64bit_fnv064") == 0) {
+ /* using non-recommended FNV-0 and zero initial basis */
+ hval = FNV0_64_INIT;
+ hash_type = FNV0_64;
+ } else if (strcmp(p, "fnv164") == 0 || strcmp(p, "no64bit_fnv164") == 0) {
+ /* using FNV-1 and non-zero initial basis */
+ hval = FNV1_64_INIT;
+ hash_type = FNV1_64;
+ } else if (strcmp(p, "fnv1a64") == 0 || strcmp(p, "no64bit_fnv1a64") == 0) {
+ /* start with the FNV-1a initial basis */
+ hval = FNV1A_64_INIT;
+ hash_type = FNV1a_64;
+ } else {
+ fprintf(stderr, "%s: unknown program name, unknown hash type\n",
+ program);
+ exit(7);
+ }
+
+ /*
+ * FNV test vector processing, if needed
+ */
+ if (t_flag >= 0) {
+ int code; /* test vector that failed, starting at 1 */
+
+ /*
+ * perform all tests
+ */
+ code = test_fnv64(hash_type, hval, bmask, v_flag, t_flag);
+
+ /*
+ * evaluate the tests
+ */
+ if (code == 0) {
+ if (v_flag) {
+ printf("passed\n");
+ }
+ exit(0);
+ } else {
+ printf("failed vector (1 is 1st test): %d\n", code);
+ exit(8);
+ }
+ }
+
+ /*
+ * string hashing
+ */
+ if (s_flag) {
+
+ /* hash any other strings */
+ for (i=optind; i < argc; ++i) {
+ switch (hash_type) {
+ case FNV0_64:
+ case FNV1_64:
+ hval = fnv_64_str(argv[i], hval);
+ break;
+ case FNV1a_64:
+ hval = fnv_64a_str(argv[i], hval);
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 9); /* exit(9) */
+ /*NOTREACHED*/
+ }
+ if (m_flag) {
+ print_fnv64(hval, bmask, v_flag, argv[i]);
+ }
+ }
+
+
+ /*
+ * file hashing
+ */
+ } else {
+
+ /*
+ * case: process only stdin
+ */
+ if (optind >= argc) {
+
+ /* case: process only stdin */
+ while ((readcnt = read(0, buf, BUF_SIZE)) > 0) {
+ switch (hash_type) {
+ case FNV0_64:
+ case FNV1_64:
+ hval = fnv_64_buf(buf, readcnt, hval);
+ break;
+ case FNV1a_64:
+ hval = fnv_64a_buf(buf, readcnt, hval);
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 10); /* exit(10) */
+ /*NOTREACHED*/
+ }
+ }
+ if (m_flag) {
+ print_fnv64(hval, bmask, v_flag, "(stdin)");
+ }
+
+ } else {
+
+ /*
+ * process any other files
+ */
+ for (i=optind; i < argc; ++i) {
+
+ /* open the file */
+ fd = open(argv[i], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: unable to open file: %s\n",
+ program, argv[i]);
+ exit(4);
+ }
+
+ /* hash the file */
+ while ((readcnt = read(fd, buf, BUF_SIZE)) > 0) {
+ switch (hash_type) {
+ case FNV0_64:
+ case FNV1_64:
+ hval = fnv_64_buf(buf, readcnt, hval);
+ break;
+ case FNV1a_64:
+ hval = fnv_64a_buf(buf, readcnt, hval);
+ break;
+ default:
+ unknown_hash_type(program, hash_type, 11);/* exit(11) */
+ /*NOTREACHED*/
+ }
+ }
+
+ /* finish processing the file */
+ if (m_flag) {
+ print_fnv64(hval, bmask, v_flag, argv[i]);
+ }
+ close(fd);
+ }
+ }
+ }
+
+ /*
+ * report hash and exit
+ */
+ if (!m_flag) {
+ print_fnv64(hval, bmask, v_flag, "");
+ }
+ return 0; /* exit(0); */
+}
diff --git a/lib/fnv/hash_32.c b/lib/fnv/hash_32.c
new file mode 100644
index 0000000000..077170ff6d
--- /dev/null
+++ b/lib/fnv/hash_32.c
@@ -0,0 +1,156 @@
+/*
+ * hash_32 - 32 bit Fowler/Noll/Vo hash code
+ *
+ * @(#) $Revision: 5.1 $
+ * @(#) $Id: hash_32.c,v 5.1 2009/06/30 09:13:32 chongo Exp $
+ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_32.c,v $
+ *
+ ***
+ *
+ * Fowler/Noll/Vo hash
+ *
+ * The basis of this hash algorithm was taken from an idea sent
+ * as reviewer comments to the IEEE POSIX P1003.2 committee by:
+ *
+ * Phong Vo (http://www.research.att.com/info/kpv/)
+ * Glenn Fowler (http://www.research.att.com/~gsf/)
+ *
+ * In a subsequent ballot round:
+ *
+ * Landon Curt Noll (http://www.isthe.com/chongo/)
+ *
+ * improved on their algorithm. Some people tried this hash
+ * and found that it worked rather well. In an EMail message
+ * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+ *
+ * FNV hashes are designed to be fast while maintaining a low
+ * collision rate. The FNV speed allows one to quickly hash lots
+ * of data while maintaining a reasonable collision rate. See:
+ *
+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ * for more details as well as other forms of the FNV hash.
+ ***
+ *
+ * NOTE: The FNV-0 historic hash is not recommended. One should use
+ * the FNV-1 hash instead.
+ *
+ * To use the 32 bit FNV-0 historic hash, pass FNV0_32_INIT as the
+ * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
+ *
+ * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the
+ * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
+ *
+ ***
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+#include <stdlib.h>
+#include "fnv.h"
+
+
+/*
+ * 32 bit magic FNV-0 and FNV-1 prime
+ */
+#define FNV_32_PRIME ((Fnv32_t)0x01000193)
+
+
+/*
+ * fnv_32_buf - perform a 32 bit Fowler/Noll/Vo hash on a buffer
+ *
+ * input:
+ * buf - start of buffer to hash
+ * len - length of buffer in octets
+ * hval - previous hash value or 0 if first call
+ *
+ * returns:
+ * 32 bit hash as a static hash type
+ *
+ * NOTE: To use the 32 bit FNV-0 historic hash, use FNV0_32_INIT as the hval
+ * argument on the first call to either fnv_32_buf() or fnv_32_str().
+ *
+ * NOTE: To use the recommended 32 bit FNV-1 hash, use FNV1_32_INIT as the hval
+ * argument on the first call to either fnv_32_buf() or fnv_32_str().
+ */
+Fnv32_t
+fnv_32_buf(void *buf, size_t len, Fnv32_t hval)
+{
+ unsigned char *bp = (unsigned char *)buf; /* start of buffer */
+ unsigned char *be = bp + len; /* beyond end of buffer */
+
+ /*
+ * FNV-1 hash each octet in the buffer
+ */
+ while (bp < be) {
+
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_32_PRIME;
+#else
+ hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
+#endif
+
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv32_t)*bp++;
+ }
+
+ /* return our new hash value */
+ return hval;
+}
+
+
+/*
+ * fnv_32_str - perform a 32 bit Fowler/Noll/Vo hash on a string
+ *
+ * input:
+ * str - string to hash
+ * hval - previous hash value or 0 if first call
+ *
+ * returns:
+ * 32 bit hash as a static hash type
+ *
+ * NOTE: To use the 32 bit FNV-0 historic hash, use FNV0_32_INIT as the hval
+ * argument on the first call to either fnv_32_buf() or fnv_32_str().
+ *
+ * NOTE: To use the recommended 32 bit FNV-1 hash, use FNV1_32_INIT as the hval
+ * argument on the first call to either fnv_32_buf() or fnv_32_str().
+ */
+Fnv32_t
+fnv_32_str(char *str, Fnv32_t hval)
+{
+ unsigned char *s = (unsigned char *)str; /* unsigned string */
+
+ /*
+ * FNV-1 hash each octet in the buffer
+ */
+ while (*s) {
+
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_32_PRIME;
+#else
+ hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
+#endif
+
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv32_t)*s++;
+ }
+
+ /* return our new hash value */
+ return hval;
+}
diff --git a/lib/fnv/hash_32a.c b/lib/fnv/hash_32a.c
new file mode 100644
index 0000000000..8b10acf3e2
--- /dev/null
+++ b/lib/fnv/hash_32a.c
@@ -0,0 +1,144 @@
+/*
+ * hash_32 - 32 bit Fowler/Noll/Vo FNV-1a hash code
+ *
+ * @(#) $Revision: 5.1 $
+ * @(#) $Id: hash_32a.c,v 5.1 2009/06/30 09:13:32 chongo Exp $
+ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_32a.c,v $
+ *
+ ***
+ *
+ * Fowler/Noll/Vo hash
+ *
+ * The basis of this hash algorithm was taken from an idea sent
+ * as reviewer comments to the IEEE POSIX P1003.2 committee by:
+ *
+ * Phong Vo (http://www.research.att.com/info/kpv/)
+ * Glenn Fowler (http://www.research.att.com/~gsf/)
+ *
+ * In a subsequent ballot round:
+ *
+ * Landon Curt Noll (http://www.isthe.com/chongo/)
+ *
+ * improved on their algorithm. Some people tried this hash
+ * and found that it worked rather well. In an EMail message
+ * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+ *
+ * FNV hashes are designed to be fast while maintaining a low
+ * collision rate. The FNV speed allows one to quickly hash lots
+ * of data while maintaining a reasonable collision rate. See:
+ *
+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ * for more details as well as other forms of the FNV hash.
+ ***
+ *
+ * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
+ * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
+ *
+ ***
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+#include <stdlib.h>
+#include "fnv.h"
+
+
+/*
+ * 32 bit magic FNV-1a prime
+ */
+#define FNV_32_PRIME ((Fnv32_t)0x01000193)
+
+
+/*
+ * fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer
+ *
+ * input:
+ * buf - start of buffer to hash
+ * len - length of buffer in octets
+ * hval - previous hash value or 0 if first call
+ *
+ * returns:
+ * 32 bit hash as a static hash type
+ *
+ * NOTE: To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the
+ * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str().
+ */
+Fnv32_t
+fnv_32a_buf(void *buf, size_t len, Fnv32_t hval)
+{
+ unsigned char *bp = (unsigned char *)buf; /* start of buffer */
+ unsigned char *be = bp + len; /* beyond end of buffer */
+
+ /*
+ * FNV-1a hash each octet in the buffer
+ */
+ while (bp < be) {
+
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv32_t)*bp++;
+
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_32_PRIME;
+#else
+ hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
+#endif
+ }
+
+ /* return our new hash value */
+ return hval;
+}
+
+
+/*
+ * fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string
+ *
+ * input:
+ * str - string to hash
+ * hval - previous hash value or 0 if first call
+ *
+ * returns:
+ * 32 bit hash as a static hash type
+ *
+ * NOTE: To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the
+ * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str().
+ */
+Fnv32_t
+fnv_32a_str(char *str, Fnv32_t hval)
+{
+ unsigned char *s = (unsigned char *)str; /* unsigned string */
+
+ /*
+ * FNV-1a hash each octet in the buffer
+ */
+ while (*s) {
+
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv32_t)*s++;
+
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_32_PRIME;
+#else
+ hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
+#endif
+ }
+
+ /* return our new hash value */
+ return hval;
+}
diff --git a/lib/fnv/hash_64.c b/lib/fnv/hash_64.c
new file mode 100644
index 0000000000..4338605dca
--- /dev/null
+++ b/lib/fnv/hash_64.c
@@ -0,0 +1,312 @@
+/*
+ * hash_64 - 64 bit Fowler/Noll/Vo-0 hash code
+ *
+ * @(#) $Revision: 5.1 $
+ * @(#) $Id: hash_64.c,v 5.1 2009/06/30 09:01:38 chongo Exp $
+ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_64.c,v $
+ *
+ ***
+ *
+ * Fowler/Noll/Vo hash
+ *
+ * The basis of this hash algorithm was taken from an idea sent
+ * as reviewer comments to the IEEE POSIX P1003.2 committee by:
+ *
+ * Phong Vo (http://www.research.att.com/info/kpv/)
+ * Glenn Fowler (http://www.research.att.com/~gsf/)
+ *
+ * In a subsequent ballot round:
+ *
+ * Landon Curt Noll (http://www.isthe.com/chongo/)
+ *
+ * improved on their algorithm. Some people tried this hash
+ * and found that it worked rather well. In an EMail message
+ * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+ *
+ * FNV hashes are designed to be fast while maintaining a low
+ * collision rate. The FNV speed allows one to quickly hash lots
+ * of data while maintaining a reasonable collision rate. See:
+ *
+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ * for more details as well as other forms of the FNV hash.
+ *
+ ***
+ *
+ * NOTE: The FNV-0 historic hash is not recommended. One should use
+ * the FNV-1 hash instead.
+ *
+ * To use the 64 bit FNV-0 historic hash, pass FNV0_64_INIT as the
+ * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
+ *
+ * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the
+ * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
+ *
+ ***
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+#include <stdlib.h>
+#include "fnv.h"
+
+
+/*
+ * FNV-0 defines the initial basis to be zero
+ */
+#if !defined(HAVE_64BIT_LONG_LONG)
+const Fnv64_t fnv0_64_init = { 0UL, 0UL };
+#endif /* ! HAVE_64BIT_LONG_LONG */
+
+
+/*
+ * FNV-1 defines the initial basis to be non-zero
+ */
+#if !defined(HAVE_64BIT_LONG_LONG)
+const Fnv64_t fnv1_64_init = { 0x84222325UL, 0xcbf29ce4UL };
+#endif /* ! HAVE_64BIT_LONG_LONG */
+
+
+/*
+ * 64 bit magic FNV-0 and FNV-1 prime
+ */
+#if defined(HAVE_64BIT_LONG_LONG)
+#define FNV_64_PRIME ((Fnv64_t)0x100000001b3ULL)
+#else /* HAVE_64BIT_LONG_LONG */
+#define FNV_64_PRIME_LOW ((unsigned long)0x1b3) /* lower bits of FNV prime */
+#define FNV_64_PRIME_SHIFT (8) /* top FNV prime shift above 2^32 */
+#endif /* HAVE_64BIT_LONG_LONG */
+
+
+/*
+ * fnv_64_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer
+ *
+ * input:
+ * buf - start of buffer to hash
+ * len - length of buffer in octets
+ * hval - previous hash value or 0 if first call
+ *
+ * returns:
+ * 64 bit hash as a static hash type
+ *
+ * NOTE: To use the 64 bit FNV-0 historic hash, use FNV0_64_INIT as the hval
+ * argument on the first call to either fnv_64_buf() or fnv_64_str().
+ *
+ * NOTE: To use the recommended 64 bit FNV-1 hash, use FNV1_64_INIT as the hval
+ * argument on the first call to either fnv_64_buf() or fnv_64_str().
+ */
+Fnv64_t
+fnv_64_buf(void *buf, size_t len, Fnv64_t hval)
+{
+ unsigned char *bp = (unsigned char *)buf; /* start of buffer */
+ unsigned char *be = bp + len; /* beyond end of buffer */
+
+#if defined(HAVE_64BIT_LONG_LONG)
+
+ /*
+ * FNV-1 hash each octet of the buffer
+ */
+ while (bp < be) {
+
+ /* multiply by the 64 bit FNV magic prime mod 2^64 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_64_PRIME;
+#else /* NO_FNV_GCC_OPTIMIZATION */
+ hval += (hval << 1) + (hval << 4) + (hval << 5) +
+ (hval << 7) + (hval << 8) + (hval << 40);
+#endif /* NO_FNV_GCC_OPTIMIZATION */
+
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv64_t)*bp++;
+ }
+
+#else /* HAVE_64BIT_LONG_LONG */
+
+ unsigned long val[4]; /* hash value in base 2^16 */
+ unsigned long tmp[4]; /* tmp 64 bit value */
+
+ /*
+ * Convert Fnv64_t hval into a base 2^16 array
+ */
+ val[0] = hval.w32[0];
+ val[1] = (val[0] >> 16);
+ val[0] &= 0xffff;
+ val[2] = hval.w32[1];
+ val[3] = (val[2] >> 16);
+ val[2] &= 0xffff;
+
+ /*
+ * FNV-1 hash each octet of the buffer
+ */
+ while (bp < be) {
+
+ /*
+ * multiply by the 64 bit FNV magic prime mod 2^64
+ *
+ * Using 0x100000001b3 we have the following digits base 2^16:
+ *
+ * 0x0 0x100 0x0 0x1b3
+ *
+ * which is the same as:
+ *
+ * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
+ */
+ /* multiply by the lowest order digit base 2^16 */
+ tmp[0] = val[0] * FNV_64_PRIME_LOW;
+ tmp[1] = val[1] * FNV_64_PRIME_LOW;
+ tmp[2] = val[2] * FNV_64_PRIME_LOW;
+ tmp[3] = val[3] * FNV_64_PRIME_LOW;
+ /* multiply by the other non-zero digit */
+ tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
+ tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
+ /* propagate carries */
+ tmp[1] += (tmp[0] >> 16);
+ val[0] = tmp[0] & 0xffff;
+ tmp[2] += (tmp[1] >> 16);
+ val[1] = tmp[1] & 0xffff;
+ val[3] = tmp[3] + (tmp[2] >> 16);
+ val[2] = tmp[2] & 0xffff;
+ /*
+ * Doing a val[3] &= 0xffff; is not really needed since it simply
+ * removes multiples of 2^64. We can discard these excess bits
+ * outside of the loop when we convert to Fnv64_t.
+ */
+
+ /* xor the bottom with the current octet */
+ val[0] ^= (unsigned long)*bp++;
+ }
+
+ /*
+ * Convert base 2^16 array back into an Fnv64_t
+ */
+ hval.w32[1] = ((val[3]<<16) | val[2]);
+ hval.w32[0] = ((val[1]<<16) | val[0]);
+
+#endif /* HAVE_64BIT_LONG_LONG */
+
+ /* return our new hash value */
+ return hval;
+}
+
+
+/*
+ * fnv_64_str - perform a 64 bit Fowler/Noll/Vo hash on a buffer
+ *
+ * input:
+ * buf - start of buffer to hash
+ * hval - previous hash value or 0 if first call
+ *
+ * returns:
+ * 64 bit hash as a static hash type
+ *
+ * NOTE: To use the 64 bit FNV-0 historic hash, use FNV0_64_INIT as the hval
+ * argument on the first call to either fnv_64_buf() or fnv_64_str().
+ *
+ * NOTE: To use the recommended 64 bit FNV-1 hash, use FNV1_64_INIT as the hval
+ * argument on the first call to either fnv_64_buf() or fnv_64_str().
+ */
+Fnv64_t
+fnv_64_str(char *str, Fnv64_t hval)
+{
+ unsigned char *s = (unsigned char *)str; /* unsigned string */
+
+#if defined(HAVE_64BIT_LONG_LONG)
+
+ /*
+ * FNV-1 hash each octet of the string
+ */
+ while (*s) {
+
+ /* multiply by the 64 bit FNV magic prime mod 2^64 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_64_PRIME;
+#else /* NO_FNV_GCC_OPTIMIZATION */
+ hval += (hval << 1) + (hval << 4) + (hval << 5) +
+ (hval << 7) + (hval << 8) + (hval << 40);
+#endif /* NO_FNV_GCC_OPTIMIZATION */
+
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv64_t)*s++;
+ }
+
+#else /* !HAVE_64BIT_LONG_LONG */
+
+ unsigned long val[4]; /* hash value in base 2^16 */
+ unsigned long tmp[4]; /* tmp 64 bit value */
+
+ /*
+ * Convert Fnv64_t hval into a base 2^16 array
+ */
+ val[0] = hval.w32[0];
+ val[1] = (val[0] >> 16);
+ val[0] &= 0xffff;
+ val[2] = hval.w32[1];
+ val[3] = (val[2] >> 16);
+ val[2] &= 0xffff;
+
+ /*
+ * FNV-1 hash each octet of the string
+ */
+ while (*s) {
+
+ /*
+ * multiply by the 64 bit FNV magic prime mod 2^64
+ *
+ * Using 1099511628211, we have the following digits base 2^16:
+ *
+ * 0x0 0x100 0x0 0x1b3
+ *
+ * which is the same as:
+ *
+ * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
+ */
+ /* multiply by the lowest order digit base 2^16 */
+ tmp[0] = val[0] * FNV_64_PRIME_LOW;
+ tmp[1] = val[1] * FNV_64_PRIME_LOW;
+ tmp[2] = val[2] * FNV_64_PRIME_LOW;
+ tmp[3] = val[3] * FNV_64_PRIME_LOW;
+ /* multiply by the other non-zero digit */
+ tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
+ tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
+ /* propagate carries */
+ tmp[1] += (tmp[0] >> 16);
+ val[0] = tmp[0] & 0xffff;
+ tmp[2] += (tmp[1] >> 16);
+ val[1] = tmp[1] & 0xffff;
+ val[3] = tmp[3] + (tmp[2] >> 16);
+ val[2] = tmp[2] & 0xffff;
+ /*
+ * Doing a val[3] &= 0xffff; is not really needed since it simply
+ * removes multiples of 2^64. We can discard these excess bits
+ * outside of the loop when we convert to Fnv64_t.
+ */
+
+ /* xor the bottom with the current octet */
+ val[0] ^= (unsigned long)(*s++);
+ }
+
+ /*
+ * Convert base 2^16 array back into an Fnv64_t
+ */
+ hval.w32[1] = ((val[3]<<16) | val[2]);
+ hval.w32[0] = ((val[1]<<16) | val[0]);
+
+#endif /* !HAVE_64BIT_LONG_LONG */
+
+ /* return our new hash value */
+ return hval;
+}
diff --git a/lib/fnv/hash_64a.c b/lib/fnv/hash_64a.c
new file mode 100644
index 0000000000..6660f92ddf
--- /dev/null
+++ b/lib/fnv/hash_64a.c
@@ -0,0 +1,291 @@
+/*
+ * hash_64 - 64 bit Fowler/Noll/Vo-0 FNV-1a hash code
+ *
+ * @(#) $Revision: 5.1 $
+ * @(#) $Id: hash_64a.c,v 5.1 2009/06/30 09:01:38 chongo Exp $
+ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_64a.c,v $
+ *
+ ***
+ *
+ * Fowler/Noll/Vo hash
+ *
+ * The basis of this hash algorithm was taken from an idea sent
+ * as reviewer comments to the IEEE POSIX P1003.2 committee by:
+ *
+ * Phong Vo (http://www.research.att.com/info/kpv/)
+ * Glenn Fowler (http://www.research.att.com/~gsf/)
+ *
+ * In a subsequent ballot round:
+ *
+ * Landon Curt Noll (http://www.isthe.com/chongo/)
+ *
+ * improved on their algorithm. Some people tried this hash
+ * and found that it worked rather well. In an EMail message
+ * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+ *
+ * FNV hashes are designed to be fast while maintaining a low
+ * collision rate. The FNV speed allows one to quickly hash lots
+ * of data while maintaining a reasonable collision rate. See:
+ *
+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ * for more details as well as other forms of the FNV hash.
+ *
+ ***
+ *
+ * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the
+ * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str().
+ *
+ ***
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+#include <stdlib.h>
+#include "fnv.h"
+
+
+/*
+ * FNV-1a defines the initial basis to be non-zero
+ */
+#if !defined(HAVE_64BIT_LONG_LONG)
+const Fnv64_t fnv1a_64_init = { 0x84222325, 0xcbf29ce4 };
+#endif /* ! HAVE_64BIT_LONG_LONG */
+
+
+/*
+ * 64 bit magic FNV-1a prime
+ */
+#if defined(HAVE_64BIT_LONG_LONG)
+#define FNV_64_PRIME ((Fnv64_t)0x100000001b3ULL)
+#else /* HAVE_64BIT_LONG_LONG */
+#define FNV_64_PRIME_LOW ((unsigned long)0x1b3) /* lower bits of FNV prime */
+#define FNV_64_PRIME_SHIFT (8) /* top FNV prime shift above 2^32 */
+#endif /* HAVE_64BIT_LONG_LONG */
+
+
+/*
+ * fnv_64a_buf - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
+ *
+ * input:
+ * buf - start of buffer to hash
+ * len - length of buffer in octets
+ * hval - previous hash value or 0 if first call
+ *
+ * returns:
+ * 64 bit hash as a static hash type
+ *
+ * NOTE: To use the recommended 64 bit FNV-1a hash, use FNV1A_64_INIT as the
+ * hval arg on the first call to either fnv_64a_buf() or fnv_64a_str().
+ */
+Fnv64_t
+fnv_64a_buf(void *buf, size_t len, Fnv64_t hval)
+{
+ unsigned char *bp = (unsigned char *)buf; /* start of buffer */
+ unsigned char *be = bp + len; /* beyond end of buffer */
+
+#if defined(HAVE_64BIT_LONG_LONG)
+ /*
+ * FNV-1a hash each octet of the buffer
+ */
+ while (bp < be) {
+
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv64_t)*bp++;
+
+ /* multiply by the 64 bit FNV magic prime mod 2^64 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_64_PRIME;
+#else /* NO_FNV_GCC_OPTIMIZATION */
+ hval += (hval << 1) + (hval << 4) + (hval << 5) +
+ (hval << 7) + (hval << 8) + (hval << 40);
+#endif /* NO_FNV_GCC_OPTIMIZATION */
+ }
+
+#else /* HAVE_64BIT_LONG_LONG */
+
+ unsigned long val[4]; /* hash value in base 2^16 */
+ unsigned long tmp[4]; /* tmp 64 bit value */
+
+ /*
+ * Convert Fnv64_t hval into a base 2^16 array
+ */
+ val[0] = hval.w32[0];
+ val[1] = (val[0] >> 16);
+ val[0] &= 0xffff;
+ val[2] = hval.w32[1];
+ val[3] = (val[2] >> 16);
+ val[2] &= 0xffff;
+
+ /*
+ * FNV-1a hash each octet of the buffer
+ */
+ while (bp < be) {
+
+ /* xor the bottom with the current octet */
+ val[0] ^= (unsigned long)*bp++;
+
+ /*
+ * multiply by the 64 bit FNV magic prime mod 2^64
+ *
+ * Using 0x100000001b3 we have the following digits base 2^16:
+ *
+ * 0x0 0x100 0x0 0x1b3
+ *
+ * which is the same as:
+ *
+ * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
+ */
+ /* multiply by the lowest order digit base 2^16 */
+ tmp[0] = val[0] * FNV_64_PRIME_LOW;
+ tmp[1] = val[1] * FNV_64_PRIME_LOW;
+ tmp[2] = val[2] * FNV_64_PRIME_LOW;
+ tmp[3] = val[3] * FNV_64_PRIME_LOW;
+ /* multiply by the other non-zero digit */
+ tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
+ tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
+ /* propagate carries */
+ tmp[1] += (tmp[0] >> 16);
+ val[0] = tmp[0] & 0xffff;
+ tmp[2] += (tmp[1] >> 16);
+ val[1] = tmp[1] & 0xffff;
+ val[3] = tmp[3] + (tmp[2] >> 16);
+ val[2] = tmp[2] & 0xffff;
+ /*
+ * Doing a val[3] &= 0xffff; is not really needed since it simply
+ * removes multiples of 2^64. We can discard these excess bits
+ * outside of the loop when we convert to Fnv64_t.
+ */
+ }
+
+ /*
+ * Convert base 2^16 array back into an Fnv64_t
+ */
+ hval.w32[1] = ((val[3]<<16) | val[2]);
+ hval.w32[0] = ((val[1]<<16) | val[0]);
+
+#endif /* HAVE_64BIT_LONG_LONG */
+
+ /* return our new hash value */
+ return hval;
+}
+
+
+/*
+ * fnv_64a_str - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
+ *
+ * input:
+ * buf - start of buffer to hash
+ * hval - previous hash value or 0 if first call
+ *
+ * returns:
+ * 64 bit hash as a static hash type
+ *
+ * NOTE: To use the recommended 64 bit FNV-1a hash, use FNV1A_64_INIT as the
+ * hval arg on the first call to either fnv_64a_buf() or fnv_64a_str().
+ */
+Fnv64_t
+fnv_64a_str(char *str, Fnv64_t hval)
+{
+ unsigned char *s = (unsigned char *)str; /* unsigned string */
+
+#if defined(HAVE_64BIT_LONG_LONG)
+
+ /*
+ * FNV-1a hash each octet of the string
+ */
+ while (*s) {
+
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv64_t)*s++;
+
+ /* multiply by the 64 bit FNV magic prime mod 2^64 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_64_PRIME;
+#else /* NO_FNV_GCC_OPTIMIZATION */
+ hval += (hval << 1) + (hval << 4) + (hval << 5) +
+ (hval << 7) + (hval << 8) + (hval << 40);
+#endif /* NO_FNV_GCC_OPTIMIZATION */
+ }
+
+#else /* !HAVE_64BIT_LONG_LONG */
+
+ unsigned long val[4]; /* hash value in base 2^16 */
+ unsigned long tmp[4]; /* tmp 64 bit value */
+
+ /*
+ * Convert Fnv64_t hval into a base 2^16 array
+ */
+ val[0] = hval.w32[0];
+ val[1] = (val[0] >> 16);
+ val[0] &= 0xffff;
+ val[2] = hval.w32[1];
+ val[3] = (val[2] >> 16);
+ val[2] &= 0xffff;
+
+ /*
+ * FNV-1a hash each octet of the string
+ */
+ while (*s) {
+
+ /* xor the bottom with the current octet */
+
+ /*
+ * multiply by the 64 bit FNV magic prime mod 2^64
+ *
+ * Using 1099511628211, we have the following digits base 2^16:
+ *
+ * 0x0 0x100 0x0 0x1b3
+ *
+ * which is the same as:
+ *
+ * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
+ */
+ /* multiply by the lowest order digit base 2^16 */
+ tmp[0] = val[0] * FNV_64_PRIME_LOW;
+ tmp[1] = val[1] * FNV_64_PRIME_LOW;
+ tmp[2] = val[2] * FNV_64_PRIME_LOW;
+ tmp[3] = val[3] * FNV_64_PRIME_LOW;
+ /* multiply by the other non-zero digit */
+ tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
+ tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
+ /* propagate carries */
+ tmp[1] += (tmp[0] >> 16);
+ val[0] = tmp[0] & 0xffff;
+ tmp[2] += (tmp[1] >> 16);
+ val[1] = tmp[1] & 0xffff;
+ val[3] = tmp[3] + (tmp[2] >> 16);
+ val[2] = tmp[2] & 0xffff;
+ /*
+ * Doing a val[3] &= 0xffff; is not really needed since it simply
+ * removes multiples of 2^64. We can discard these excess bits
+ * outside of the loop when we convert to Fnv64_t.
+ */
+ val[0] ^= (unsigned long)(*s++);
+ }
+
+ /*
+ * Convert base 2^16 array back into an Fnv64_t
+ */
+ hval.w32[1] = ((val[3]<<16) | val[2]);
+ hval.w32[0] = ((val[1]<<16) | val[0]);
+
+#endif /* !HAVE_64BIT_LONG_LONG */
+
+ /* return our new hash value */
+ return hval;
+}
diff --git a/lib/fnv/have_ulong64.c b/lib/fnv/have_ulong64.c
new file mode 100644
index 0000000000..5c06262388
--- /dev/null
+++ b/lib/fnv/have_ulong64.c
@@ -0,0 +1,58 @@
+/*
+ * have_ulong64 - Determine if we have a 64 bit unsigned long long
+ *
+ * usage:
+ * have_ulong64 > longlong.h
+ *
+ * Not all systems have a 'long long type' so this may not compile on
+ * your system.
+ *
+ * This prog outputs the define:
+ *
+ * HAVE_64BIT_LONG_LONG
+ * defined ==> we have a 64 bit unsigned long long
+ * undefined ==> we must simulate a 64 bit unsigned long long
+ */
+/*
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+/*
+ * have the compiler try its hand with unsigned and signed long longs
+ */
+#if ! defined(NO64BIT_LONG_LONG)
+unsigned long long val = 1099511628211ULL;
+#endif /* NO64BIT_LONG_LONG */
+
+int
+main(void)
+{
+ /*
+ * ensure that the length of long long val is what we expect
+ */
+#if defined(NO64BIT_LONG_LONG)
+ printf("#undef HAVE_64BIT_LONG_LONG\t/* no */\n");
+#else /* NO64BIT_LONG_LONG */
+ if (val == 1099511628211ULL && sizeof(val) == 8) {
+ printf("#define HAVE_64BIT_LONG_LONG\t/* yes */\n");
+ }
+#endif /* NO64BIT_LONG_LONG */
+
+ /* exit(0); */
+ return 0;
+}
diff --git a/lib/fnv/longlong.h b/lib/fnv/longlong.h
new file mode 100644
index 0000000000..c8cfe48f29
--- /dev/null
+++ b/lib/fnv/longlong.h
@@ -0,0 +1,18 @@
+/*
+ * DO NOT EDIT -- generated by the Makefile
+ */
+
+#if !defined(__LONGLONG_H__)
+#define __LONGLONG_H__
+
+/* do we have/want to use a long long type? */
+#define HAVE_64BIT_LONG_LONG /* yes */
+
+/*
+ * NO64BIT_LONG_LONG undef HAVE_64BIT_LONG_LONG
+ */
+#if defined(NO64BIT_LONG_LONG)
+#undef HAVE_64BIT_LONG_LONG
+#endif /* NO64BIT_LONG_LONG */
+
+#endif /* !__LONGLONG_H__ */
diff --git a/lib/fnv/qmk_fnv_type_validation.c b/lib/fnv/qmk_fnv_type_validation.c
new file mode 100644
index 0000000000..e8576617ba
--- /dev/null
+++ b/lib/fnv/qmk_fnv_type_validation.c
@@ -0,0 +1,14 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "fnv.h"
+
+// This library was originally sourced from:
+// http://www.isthe.com/chongo/tech/comp/fnv/index.html
+//
+// Version at the time of retrieval on 2022-06-26: v5.0.3
+
+_Static_assert(sizeof(long long) == 8, "long long should be 64 bits");
+_Static_assert(sizeof(unsigned long long) == 8, "unsigned long long should be 64 bits");
+
+_Static_assert(sizeof(Fnv32_t) == 4, "Fnv32_t should be 32 bits");
+_Static_assert(sizeof(Fnv64_t) == 8, "Fnv64_t should be 64 bits");
diff --git a/lib/fnv/test_fnv.c b/lib/fnv/test_fnv.c
new file mode 100644
index 0000000000..efec3dec1d
--- /dev/null
+++ b/lib/fnv/test_fnv.c
@@ -0,0 +1,2237 @@
+/*
+ * test_fnv - FNV test suite
+ *
+ * @(#) $Revision: 5.3 $
+ * @(#) $Id: test_fnv.c,v 5.3 2009/06/30 11:50:41 chongo Exp $
+ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/test_fnv.c,v $
+ *
+ ***
+ *
+ * Fowler/Noll/Vo hash
+ *
+ * The basis of this hash algorithm was taken from an idea sent
+ * as reviewer comments to the IEEE POSIX P1003.2 committee by:
+ *
+ * Phong Vo (http://www.research.att.com/info/kpv/)
+ * Glenn Fowler (http://www.research.att.com/~gsf/)
+ *
+ * In a subsequent ballot round:
+ *
+ * Landon Curt Noll (http://www.isthe.com/chongo/)
+ *
+ * improved on their algorithm. Some people tried this hash
+ * and found that it worked rather well. In an EMail message
+ * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+ *
+ * FNV hashes are designed to be fast while maintaining a low
+ * collision rate. The FNV speed allows one to quickly hash lots
+ * of data while maintaining a reasonable collision rate. See:
+ *
+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ * for more details as well as other forms of the FNV hash.
+ *
+ ***
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+#include <stdio.h>
+#include "longlong.h"
+#include "fnv.h"
+
+#define LEN(x) (sizeof(x)-1)
+/* TEST macro does not include trailing NUL byte in the test vector */
+#define TEST(x) {x, LEN(x)}
+/* TEST0 macro includes the trailing NUL byte in the test vector */
+#define TEST0(x) {x, sizeof(x)}
+/* REPEAT500 - repeat a string 500 times */
+#define R500(x) R100(x)R100(x)R100(x)R100(x)R100(x)
+#define R100(x) R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)
+#define R10(x) x x x x x x x x x x
+
+/*
+ * FNV test vectors
+ *
+ * NOTE: A NULL pointer marks beyond the end of the test vectors.
+ *
+ * NOTE: The order of the fnv_test_str[] test vectors is 1-to-1 with:
+ *
+ * struct fnv0_32_test_vector fnv0_32_vector[];
+ * struct fnv1_32_test_vector fnv1_32_vector[];
+ * struct fnv1a_32_test_vector fnv1a_32_vector[];
+ * struct fnv0_64_test_vector fnv0_64_vector[];
+ * struct fnv1_64_test_vector fnv1_64_vector[];
+ * struct fnv1a_64_test_vector fnv1a_64_vector[];
+ *
+ * IMPORTANT NOTE:
+ *
+ * If you change the fnv_test_str[] array, you need
+ * to also change ALL of the above fnv*_vector arrays!!!
+ *
+ * To rebuild, try:
+ *
+ * make vector.c
+ *
+ * and then fold the results into the source file.
+ * Of course, you better make sure that the vaules
+ * produced by the above command are valid, otherwise
+ * you will be testing against invalid vectors!
+ */
+struct test_vector fnv_test_str[] = {
+ TEST(""),
+ TEST("a"),
+ TEST("b"),
+ TEST("c"),
+ TEST("d"),
+ TEST("e"),
+ TEST("f"),
+ TEST("fo"),
+ TEST("foo"),
+ TEST("foob"),
+ TEST("fooba"),
+ TEST("foobar"),
+ TEST0(""),
+ TEST0("a"),
+ TEST0("b"),
+ TEST0("c"),
+ TEST0("d"),
+ TEST0("e"),
+ TEST0("f"),
+ TEST0("fo"),
+ TEST0("foo"),
+ TEST0("foob"),
+ TEST0("fooba"),
+ TEST0("foobar"),
+ TEST("ch"),
+ TEST("cho"),
+ TEST("chon"),
+ TEST("chong"),
+ TEST("chongo"),
+ TEST("chongo "),
+ TEST("chongo w"),
+ TEST("chongo wa"),
+ TEST("chongo was"),
+ TEST("chongo was "),
+ TEST("chongo was h"),
+ TEST("chongo was he"),
+ TEST("chongo was her"),
+ TEST("chongo was here"),
+ TEST("chongo was here!"),
+ TEST("chongo was here!\n"),
+ TEST0("ch"),
+ TEST0("cho"),
+ TEST0("chon"),
+ TEST0("chong"),
+ TEST0("chongo"),
+ TEST0("chongo "),
+ TEST0("chongo w"),
+ TEST0("chongo wa"),
+ TEST0("chongo was"),
+ TEST0("chongo was "),
+ TEST0("chongo was h"),
+ TEST0("chongo was he"),
+ TEST0("chongo was her"),
+ TEST0("chongo was here"),
+ TEST0("chongo was here!"),
+ TEST0("chongo was here!\n"),
+ TEST("cu"),
+ TEST("cur"),
+ TEST("curd"),
+ TEST("curds"),
+ TEST("curds "),
+ TEST("curds a"),
+ TEST("curds an"),
+ TEST("curds and"),
+ TEST("curds and "),
+ TEST("curds and w"),
+ TEST("curds and wh"),
+ TEST("curds and whe"),
+ TEST("curds and whey"),
+ TEST("curds and whey\n"),
+ TEST0("cu"),
+ TEST0("cur"),
+ TEST0("curd"),
+ TEST0("curds"),
+ TEST0("curds "),
+ TEST0("curds a"),
+ TEST0("curds an"),
+ TEST0("curds and"),
+ TEST0("curds and "),
+ TEST0("curds and w"),
+ TEST0("curds and wh"),
+ TEST0("curds and whe"),
+ TEST0("curds and whey"),
+ TEST0("curds and whey\n"),
+ TEST("hi"), TEST0("hi"),
+ TEST("hello"), TEST0("hello"),
+ TEST("\xff\x00\x00\x01"), TEST("\x01\x00\x00\xff"),
+ TEST("\xff\x00\x00\x02"), TEST("\x02\x00\x00\xff"),
+ TEST("\xff\x00\x00\x03"), TEST("\x03\x00\x00\xff"),
+ TEST("\xff\x00\x00\x04"), TEST("\x04\x00\x00\xff"),
+ TEST("\x40\x51\x4e\x44"), TEST("\x44\x4e\x51\x40"),
+ TEST("\x40\x51\x4e\x4a"), TEST("\x4a\x4e\x51\x40"),
+ TEST("\x40\x51\x4e\x54"), TEST("\x54\x4e\x51\x40"),
+ TEST("127.0.0.1"), TEST0("127.0.0.1"),
+ TEST("127.0.0.2"), TEST0("127.0.0.2"),
+ TEST("127.0.0.3"), TEST0("127.0.0.3"),
+ TEST("64.81.78.68"), TEST0("64.81.78.68"),
+ TEST("64.81.78.74"), TEST0("64.81.78.74"),
+ TEST("64.81.78.84"), TEST0("64.81.78.84"),
+ TEST("feedface"), TEST0("feedface"),
+ TEST("feedfacedaffdeed"), TEST0("feedfacedaffdeed"),
+ TEST("feedfacedeadbeef"), TEST0("feedfacedeadbeef"),
+ TEST("line 1\nline 2\nline 3"),
+ TEST("chongo <Landon Curt Noll> /\\../\\"),
+ TEST0("chongo <Landon Curt Noll> /\\../\\"),
+ TEST("chongo (Landon Curt Noll) /\\../\\"),
+ TEST0("chongo (Landon Curt Noll) /\\../\\"),
+ TEST("http://antwrp.gsfc.nasa.gov/apod/astropix.html"),
+ TEST("http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash"),
+ TEST("http://epod.usra.edu/"),
+ TEST("http://exoplanet.eu/"),
+ TEST("http://hvo.wr.usgs.gov/cam3/"),
+ TEST("http://hvo.wr.usgs.gov/cams/HMcam/"),
+ TEST("http://hvo.wr.usgs.gov/kilauea/update/deformation.html"),
+ TEST("http://hvo.wr.usgs.gov/kilauea/update/images.html"),
+ TEST("http://hvo.wr.usgs.gov/kilauea/update/maps.html"),
+ TEST("http://hvo.wr.usgs.gov/volcanowatch/current_issue.html"),
+ TEST("http://neo.jpl.nasa.gov/risk/"),
+ TEST("http://norvig.com/21-days.html"),
+ TEST("http://primes.utm.edu/curios/home.php"),
+ TEST("http://slashdot.org/"),
+ TEST("http://tux.wr.usgs.gov/Maps/155.25-19.5.html"),
+ TEST("http://volcano.wr.usgs.gov/kilaueastatus.php"),
+ TEST("http://www.avo.alaska.edu/activity/Redoubt.php"),
+ TEST("http://www.dilbert.com/fast/"),
+ TEST("http://www.fourmilab.ch/gravitation/orbits/"),
+ TEST("http://www.fpoa.net/"),
+ TEST("http://www.ioccc.org/index.html"),
+ TEST("http://www.isthe.com/cgi-bin/number.cgi"),
+ TEST("http://www.isthe.com/chongo/bio.html"),
+ TEST("http://www.isthe.com/chongo/index.html"),
+ TEST("http://www.isthe.com/chongo/src/calc/lucas-calc"),
+ TEST("http://www.isthe.com/chongo/tech/astro/venus2004.html"),
+ TEST("http://www.isthe.com/chongo/tech/astro/vita.html"),
+ TEST("http://www.isthe.com/chongo/tech/comp/c/expert.html"),
+ TEST("http://www.isthe.com/chongo/tech/comp/calc/index.html"),
+ TEST("http://www.isthe.com/chongo/tech/comp/fnv/index.html"),
+ TEST("http://www.isthe.com/chongo/tech/math/number/howhigh.html"),
+ TEST("http://www.isthe.com/chongo/tech/math/number/number.html"),
+ TEST("http://www.isthe.com/chongo/tech/math/prime/mersenne.html"),
+ TEST("http://www.isthe.com/chongo/tech/math/prime/mersenne.html#largest"),
+ TEST("http://www.lavarnd.org/cgi-bin/corpspeak.cgi"),
+ TEST("http://www.lavarnd.org/cgi-bin/haiku.cgi"),
+ TEST("http://www.lavarnd.org/cgi-bin/rand-none.cgi"),
+ TEST("http://www.lavarnd.org/cgi-bin/randdist.cgi"),
+ TEST("http://www.lavarnd.org/index.html"),
+ TEST("http://www.lavarnd.org/what/nist-test.html"),
+ TEST("http://www.macosxhints.com/"),
+ TEST("http://www.mellis.com/"),
+ TEST("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/havoalert.cfm"),
+ TEST("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/timelines_24.cfm"),
+ TEST("http://www.paulnoll.com/"),
+ TEST("http://www.pepysdiary.com/"),
+ TEST("http://www.sciencenews.org/index/home/activity/view"),
+ TEST("http://www.skyandtelescope.com/"),
+ TEST("http://www.sput.nl/~rob/sirius.html"),
+ TEST("http://www.systemexperts.com/"),
+ TEST("http://www.tq-international.com/phpBB3/index.php"),
+ TEST("http://www.travelquesttours.com/index.htm"),
+ TEST("http://www.wunderground.com/global/stations/89606.html"),
+ TEST(R10("21701")),
+ TEST(R10("M21701")),
+ TEST(R10("2^21701-1")),
+ TEST(R10("\x54\xc5")),
+ TEST(R10("\xc5\x54")),
+ TEST(R10("23209")),
+ TEST(R10("M23209")),
+ TEST(R10("2^23209-1")),
+ TEST(R10("\x5a\xa9")),
+ TEST(R10("\xa9\x5a")),
+ TEST(R10("391581216093")),
+ TEST(R10("391581*2^216093-1")),
+ TEST(R10("\x05\xf9\x9d\x03\x4c\x81")),
+ TEST(R10("FEDCBA9876543210")),
+ TEST(R10("\xfe\xdc\xba\x98\x76\x54\x32\x10")),
+ TEST(R10("EFCDAB8967452301")),
+ TEST(R10("\xef\xcd\xab\x89\x67\x45\x23\x01")),
+ TEST(R10("0123456789ABCDEF")),
+ TEST(R10("\x01\x23\x45\x67\x89\xab\xcd\xef")),
+ TEST(R10("1032547698BADCFE")),
+ TEST(R10("\x10\x32\x54\x76\x98\xba\xdc\xfe")),
+ TEST(R500("\x00")),
+ TEST(R500("\x07")),
+ TEST(R500("~")),
+ TEST(R500("\x7f")),
+ {NULL, 0} /* MUST BE LAST */
+};
+
+
+/*
+ * insert the contents of vector.c below
+ *
+ * make vector.c
+ * :r vector.c
+ */
+/* start of output generated by make vector.c */
+
+/* FNV-0 32 bit test vectors */
+struct fnv0_32_test_vector fnv0_32_vector[] = {
+ { &fnv_test_str[0], (Fnv32_t) 0x00000000UL },
+ { &fnv_test_str[1], (Fnv32_t) 0x00000061UL },
+ { &fnv_test_str[2], (Fnv32_t) 0x00000062UL },
+ { &fnv_test_str[3], (Fnv32_t) 0x00000063UL },
+ { &fnv_test_str[4], (Fnv32_t) 0x00000064UL },
+ { &fnv_test_str[5], (Fnv32_t) 0x00000065UL },
+ { &fnv_test_str[6], (Fnv32_t) 0x00000066UL },
+ { &fnv_test_str[7], (Fnv32_t) 0x6600a0fdUL },
+ { &fnv_test_str[8], (Fnv32_t) 0x8ffd6e28UL },
+ { &fnv_test_str[9], (Fnv32_t) 0xd3f4689aUL },
+ { &fnv_test_str[10], (Fnv32_t) 0x43c0aa0fUL },
+ { &fnv_test_str[11], (Fnv32_t) 0xb74bb5efUL },
+ { &fnv_test_str[12], (Fnv32_t) 0x00000000UL },
+ { &fnv_test_str[13], (Fnv32_t) 0x610098b3UL },
+ { &fnv_test_str[14], (Fnv32_t) 0x62009a46UL },
+ { &fnv_test_str[15], (Fnv32_t) 0x63009bd9UL },
+ { &fnv_test_str[16], (Fnv32_t) 0x64009d6cUL },
+ { &fnv_test_str[17], (Fnv32_t) 0x65009effUL },
+ { &fnv_test_str[18], (Fnv32_t) 0x6600a092UL },
+ { &fnv_test_str[19], (Fnv32_t) 0x8ffd6e47UL },
+ { &fnv_test_str[20], (Fnv32_t) 0xd3f468f8UL },
+ { &fnv_test_str[21], (Fnv32_t) 0x43c0aa6eUL },
+ { &fnv_test_str[22], (Fnv32_t) 0xb74bb59dUL },
+ { &fnv_test_str[23], (Fnv32_t) 0x7b2f673dUL },
+ { &fnv_test_str[24], (Fnv32_t) 0x63009bb1UL },
+ { &fnv_test_str[25], (Fnv32_t) 0x8af517ccUL },
+ { &fnv_test_str[26], (Fnv32_t) 0x8bd4764aUL },
+ { &fnv_test_str[27], (Fnv32_t) 0x69763619UL },
+ { &fnv_test_str[28], (Fnv32_t) 0x1e172934UL },
+ { &fnv_test_str[29], (Fnv32_t) 0x9275dcfcUL },
+ { &fnv_test_str[30], (Fnv32_t) 0x8b8ae0c3UL },
+ { &fnv_test_str[31], (Fnv32_t) 0x6e9fd298UL },
+ { &fnv_test_str[32], (Fnv32_t) 0xbd98853bUL },
+ { &fnv_test_str[33], (Fnv32_t) 0xb219bbc1UL },
+ { &fnv_test_str[34], (Fnv32_t) 0x1f8290bbUL },
+ { &fnv_test_str[35], (Fnv32_t) 0x5589d604UL },
+ { &fnv_test_str[36], (Fnv32_t) 0xabfbe83eUL },
+ { &fnv_test_str[37], (Fnv32_t) 0xfb8e99ffUL },
+ { &fnv_test_str[38], (Fnv32_t) 0x007c6c4cUL },
+ { &fnv_test_str[39], (Fnv32_t) 0x0fde7baeUL },
+ { &fnv_test_str[40], (Fnv32_t) 0x8af517a3UL },
+ { &fnv_test_str[41], (Fnv32_t) 0x8bd47624UL },
+ { &fnv_test_str[42], (Fnv32_t) 0x6976367eUL },
+ { &fnv_test_str[43], (Fnv32_t) 0x1e17295bUL },
+ { &fnv_test_str[44], (Fnv32_t) 0x9275dcdcUL },
+ { &fnv_test_str[45], (Fnv32_t) 0x8b8ae0b4UL },
+ { &fnv_test_str[46], (Fnv32_t) 0x6e9fd2f9UL },
+ { &fnv_test_str[47], (Fnv32_t) 0xbd988548UL },
+ { &fnv_test_str[48], (Fnv32_t) 0xb219bbe1UL },
+ { &fnv_test_str[49], (Fnv32_t) 0x1f8290d3UL },
+ { &fnv_test_str[50], (Fnv32_t) 0x5589d661UL },
+ { &fnv_test_str[51], (Fnv32_t) 0xabfbe84cUL },
+ { &fnv_test_str[52], (Fnv32_t) 0xfb8e999aUL },
+ { &fnv_test_str[53], (Fnv32_t) 0x007c6c6dUL },
+ { &fnv_test_str[54], (Fnv32_t) 0x0fde7ba4UL },
+ { &fnv_test_str[55], (Fnv32_t) 0xa93cb2eaUL },
+ { &fnv_test_str[56], (Fnv32_t) 0x63009bacUL },
+ { &fnv_test_str[57], (Fnv32_t) 0x85f50fb6UL },
+ { &fnv_test_str[58], (Fnv32_t) 0x96c7bbe6UL },
+ { &fnv_test_str[59], (Fnv32_t) 0x426ccb61UL },
+ { &fnv_test_str[60], (Fnv32_t) 0xf2442993UL },
+ { &fnv_test_str[61], (Fnv32_t) 0xf44d7208UL },
+ { &fnv_test_str[62], (Fnv32_t) 0x9dea82f6UL },
+ { &fnv_test_str[63], (Fnv32_t) 0x8e2c2926UL },
+ { &fnv_test_str[64], (Fnv32_t) 0xf584c6f2UL },
+ { &fnv_test_str[65], (Fnv32_t) 0x72052e81UL },
+ { &fnv_test_str[66], (Fnv32_t) 0xff28357bUL },
+ { &fnv_test_str[67], (Fnv32_t) 0x274c30c4UL },
+ { &fnv_test_str[68], (Fnv32_t) 0xa0f0c4f5UL },
+ { &fnv_test_str[69], (Fnv32_t) 0x50060da5UL },
+ { &fnv_test_str[70], (Fnv32_t) 0x85f50fc4UL },
+ { &fnv_test_str[71], (Fnv32_t) 0x96c7bb82UL },
+ { &fnv_test_str[72], (Fnv32_t) 0x426ccb12UL },
+ { &fnv_test_str[73], (Fnv32_t) 0xf24429b3UL },
+ { &fnv_test_str[74], (Fnv32_t) 0xf44d7269UL },
+ { &fnv_test_str[75], (Fnv32_t) 0x9dea8298UL },
+ { &fnv_test_str[76], (Fnv32_t) 0x8e2c2942UL },
+ { &fnv_test_str[77], (Fnv32_t) 0xf584c6d2UL },
+ { &fnv_test_str[78], (Fnv32_t) 0x72052ef6UL },
+ { &fnv_test_str[79], (Fnv32_t) 0xff283513UL },
+ { &fnv_test_str[80], (Fnv32_t) 0x274c30a1UL },
+ { &fnv_test_str[81], (Fnv32_t) 0xa0f0c48cUL },
+ { &fnv_test_str[82], (Fnv32_t) 0x50060dafUL },
+ { &fnv_test_str[83], (Fnv32_t) 0x9e877abfUL },
+ { &fnv_test_str[84], (Fnv32_t) 0x6800a3d1UL },
+ { &fnv_test_str[85], (Fnv32_t) 0x8a01e203UL },
+ { &fnv_test_str[86], (Fnv32_t) 0xec6d6be8UL },
+ { &fnv_test_str[87], (Fnv32_t) 0x1840de38UL },
+ { &fnv_test_str[88], (Fnv32_t) 0xa7cc97b4UL },
+ { &fnv_test_str[89], (Fnv32_t) 0x3ee6b3b4UL },
+ { &fnv_test_str[90], (Fnv32_t) 0xa7cc97b7UL },
+ { &fnv_test_str[91], (Fnv32_t) 0x7dcd6669UL },
+ { &fnv_test_str[92], (Fnv32_t) 0xa7cc97b6UL },
+ { &fnv_test_str[93], (Fnv32_t) 0xbcb4191eUL },
+ { &fnv_test_str[94], (Fnv32_t) 0xa7cc97b1UL },
+ { &fnv_test_str[95], (Fnv32_t) 0xfb9acdd3UL },
+ { &fnv_test_str[96], (Fnv32_t) 0x89380433UL },
+ { &fnv_test_str[97], (Fnv32_t) 0x8acd2855UL },
+ { &fnv_test_str[98], (Fnv32_t) 0x8938043dUL },
+ { &fnv_test_str[99], (Fnv32_t) 0xcaeed493UL },
+ { &fnv_test_str[100], (Fnv32_t) 0x89380423UL },
+ { &fnv_test_str[101], (Fnv32_t) 0x59382a25UL },
+ { &fnv_test_str[102], (Fnv32_t) 0x567f75d7UL },
+ { &fnv_test_str[103], (Fnv32_t) 0x01a68175UL },
+ { &fnv_test_str[104], (Fnv32_t) 0x567f75d4UL },
+ { &fnv_test_str[105], (Fnv32_t) 0xfea67cbcUL },
+ { &fnv_test_str[106], (Fnv32_t) 0x567f75d5UL },
+ { &fnv_test_str[107], (Fnv32_t) 0xffa67e4fUL },
+ { &fnv_test_str[108], (Fnv32_t) 0xd131b668UL },
+ { &fnv_test_str[109], (Fnv32_t) 0xb94225b8UL },
+ { &fnv_test_str[110], (Fnv32_t) 0xd231b7d7UL },
+ { &fnv_test_str[111], (Fnv32_t) 0xbb446775UL },
+ { &fnv_test_str[112], (Fnv32_t) 0xdf31cc6eUL },
+ { &fnv_test_str[113], (Fnv32_t) 0xc964d12aUL },
+ { &fnv_test_str[114], (Fnv32_t) 0x23af8f9fUL },
+ { &fnv_test_str[115], (Fnv32_t) 0xcc5f174dUL },
+ { &fnv_test_str[116], (Fnv32_t) 0x96b29b8cUL },
+ { &fnv_test_str[117], (Fnv32_t) 0xc72add64UL },
+ { &fnv_test_str[118], (Fnv32_t) 0x528fb7efUL },
+ { &fnv_test_str[119], (Fnv32_t) 0xe73e8d3dUL },
+ { &fnv_test_str[120], (Fnv32_t) 0x876386feUL },
+ { &fnv_test_str[121], (Fnv32_t) 0x811c9dc5UL },
+ { &fnv_test_str[122], (Fnv32_t) 0x050c5d1fUL },
+ { &fnv_test_str[123], (Fnv32_t) 0x14bf7238UL },
+ { &fnv_test_str[124], (Fnv32_t) 0xe160ce28UL },
+ { &fnv_test_str[125], (Fnv32_t) 0x89dc5a75UL },
+ { &fnv_test_str[126], (Fnv32_t) 0xd89b69a0UL },
+ { &fnv_test_str[127], (Fnv32_t) 0x94471a88UL },
+ { &fnv_test_str[128], (Fnv32_t) 0xe78db65fUL },
+ { &fnv_test_str[129], (Fnv32_t) 0x0c3009a2UL },
+ { &fnv_test_str[130], (Fnv32_t) 0x122dff03UL },
+ { &fnv_test_str[131], (Fnv32_t) 0xb4cd8875UL },
+ { &fnv_test_str[132], (Fnv32_t) 0xf4dba725UL },
+ { &fnv_test_str[133], (Fnv32_t) 0x41a16560UL },
+ { &fnv_test_str[134], (Fnv32_t) 0x9c0f941fUL },
+ { &fnv_test_str[135], (Fnv32_t) 0x451a5348UL },
+ { &fnv_test_str[136], (Fnv32_t) 0x3f1d1d89UL },
+ { &fnv_test_str[137], (Fnv32_t) 0x1b91b57aUL },
+ { &fnv_test_str[138], (Fnv32_t) 0x3e99b577UL },
+ { &fnv_test_str[139], (Fnv32_t) 0x4c9de07aUL },
+ { &fnv_test_str[140], (Fnv32_t) 0x1ddf7572UL },
+ { &fnv_test_str[141], (Fnv32_t) 0x64e81976UL },
+ { &fnv_test_str[142], (Fnv32_t) 0x1106a888UL },
+ { &fnv_test_str[143], (Fnv32_t) 0xa498d8e5UL },
+ { &fnv_test_str[144], (Fnv32_t) 0x3c03d2e3UL },
+ { &fnv_test_str[145], (Fnv32_t) 0x26568b28UL },
+ { &fnv_test_str[146], (Fnv32_t) 0x70d7fb42UL },
+ { &fnv_test_str[147], (Fnv32_t) 0xd3ae1d22UL },
+ { &fnv_test_str[148], (Fnv32_t) 0xac8ea5f4UL },
+ { &fnv_test_str[149], (Fnv32_t) 0x4d0abd60UL },
+ { &fnv_test_str[150], (Fnv32_t) 0x48f5e086UL },
+ { &fnv_test_str[151], (Fnv32_t) 0xa8f6241bUL },
+ { &fnv_test_str[152], (Fnv32_t) 0x572f864fUL },
+ { &fnv_test_str[153], (Fnv32_t) 0xa5340803UL },
+ { &fnv_test_str[154], (Fnv32_t) 0x22881aa8UL },
+ { &fnv_test_str[155], (Fnv32_t) 0xc2e2f5a2UL },
+ { &fnv_test_str[156], (Fnv32_t) 0xebf5aec7UL },
+ { &fnv_test_str[157], (Fnv32_t) 0x3cdbfb85UL },
+ { &fnv_test_str[158], (Fnv32_t) 0xbb859704UL },
+ { &fnv_test_str[159], (Fnv32_t) 0xc956fe11UL },
+ { &fnv_test_str[160], (Fnv32_t) 0x8f11a7c9UL },
+ { &fnv_test_str[161], (Fnv32_t) 0x36c48ecfUL },
+ { &fnv_test_str[162], (Fnv32_t) 0x24bfa27eUL },
+ { &fnv_test_str[163], (Fnv32_t) 0xf2596ad1UL },
+ { &fnv_test_str[164], (Fnv32_t) 0xf14a9b45UL },
+ { &fnv_test_str[165], (Fnv32_t) 0x7d45835aUL },
+ { &fnv_test_str[166], (Fnv32_t) 0x6e49334dUL },
+ { &fnv_test_str[167], (Fnv32_t) 0x71767337UL },
+ { &fnv_test_str[168], (Fnv32_t) 0x858a1a8aUL },
+ { &fnv_test_str[169], (Fnv32_t) 0x16e75ac2UL },
+ { &fnv_test_str[170], (Fnv32_t) 0x409f99dfUL },
+ { &fnv_test_str[171], (Fnv32_t) 0x6d6652ddUL },
+ { &fnv_test_str[172], (Fnv32_t) 0x2761a9ffUL },
+ { &fnv_test_str[173], (Fnv32_t) 0x41f0d616UL },
+ { &fnv_test_str[174], (Fnv32_t) 0x0e2d0d0fUL },
+ { &fnv_test_str[175], (Fnv32_t) 0x06adc8fdUL },
+ { &fnv_test_str[176], (Fnv32_t) 0x60e0d4b9UL },
+ { &fnv_test_str[177], (Fnv32_t) 0x5ddc79d3UL },
+ { &fnv_test_str[178], (Fnv32_t) 0x1e6d0b46UL },
+ { &fnv_test_str[179], (Fnv32_t) 0x1d1514d8UL },
+ { &fnv_test_str[180], (Fnv32_t) 0xb1903a4eUL },
+ { &fnv_test_str[181], (Fnv32_t) 0x8200c318UL },
+ { &fnv_test_str[182], (Fnv32_t) 0x15e22888UL },
+ { &fnv_test_str[183], (Fnv32_t) 0x57591760UL },
+ { &fnv_test_str[184], (Fnv32_t) 0x02462efcUL },
+ { &fnv_test_str[185], (Fnv32_t) 0x7651ec44UL },
+ { &fnv_test_str[186], (Fnv32_t) 0x7c24e9d4UL },
+ { &fnv_test_str[187], (Fnv32_t) 0x1952a034UL },
+ { &fnv_test_str[188], (Fnv32_t) 0xd4c46864UL },
+ { &fnv_test_str[189], (Fnv32_t) 0xcb57cde0UL },
+ { &fnv_test_str[190], (Fnv32_t) 0x71136a70UL },
+ { &fnv_test_str[191], (Fnv32_t) 0x0618fb40UL },
+ { &fnv_test_str[192], (Fnv32_t) 0x69a24fc0UL },
+ { &fnv_test_str[193], (Fnv32_t) 0x6a9be510UL },
+ { &fnv_test_str[194], (Fnv32_t) 0xe0477040UL },
+ { &fnv_test_str[195], (Fnv32_t) 0x85aa94b0UL },
+ { &fnv_test_str[196], (Fnv32_t) 0xc6d76240UL },
+ { &fnv_test_str[197], (Fnv32_t) 0xa9f09e40UL },
+ { &fnv_test_str[198], (Fnv32_t) 0xa0291540UL },
+ { &fnv_test_str[199], (Fnv32_t) 0x00000000UL },
+ { &fnv_test_str[200], (Fnv32_t) 0x2e672aa4UL },
+ { &fnv_test_str[201], (Fnv32_t) 0x84b1aa48UL },
+ { &fnv_test_str[202], (Fnv32_t) 0xfc24ba24UL },
+ { NULL, 0 }
+};
+
+/* FNV-1 32 bit test vectors */
+struct fnv1_32_test_vector fnv1_32_vector[] = {
+ { &fnv_test_str[0], (Fnv32_t) 0x811c9dc5UL },
+ { &fnv_test_str[1], (Fnv32_t) 0x050c5d7eUL },
+ { &fnv_test_str[2], (Fnv32_t) 0x050c5d7dUL },
+ { &fnv_test_str[3], (Fnv32_t) 0x050c5d7cUL },
+ { &fnv_test_str[4], (Fnv32_t) 0x050c5d7bUL },
+ { &fnv_test_str[5], (Fnv32_t) 0x050c5d7aUL },
+ { &fnv_test_str[6], (Fnv32_t) 0x050c5d79UL },
+ { &fnv_test_str[7], (Fnv32_t) 0x6b772514UL },
+ { &fnv_test_str[8], (Fnv32_t) 0x408f5e13UL },
+ { &fnv_test_str[9], (Fnv32_t) 0xb4b1178bUL },
+ { &fnv_test_str[10], (Fnv32_t) 0xfdc80fb0UL },
+ { &fnv_test_str[11], (Fnv32_t) 0x31f0b262UL },
+ { &fnv_test_str[12], (Fnv32_t) 0x050c5d1fUL },
+ { &fnv_test_str[13], (Fnv32_t) 0x70772d5aUL },
+ { &fnv_test_str[14], (Fnv32_t) 0x6f772bc7UL },
+ { &fnv_test_str[15], (Fnv32_t) 0x6e772a34UL },
+ { &fnv_test_str[16], (Fnv32_t) 0x6d7728a1UL },
+ { &fnv_test_str[17], (Fnv32_t) 0x6c77270eUL },
+ { &fnv_test_str[18], (Fnv32_t) 0x6b77257bUL },
+ { &fnv_test_str[19], (Fnv32_t) 0x408f5e7cUL },
+ { &fnv_test_str[20], (Fnv32_t) 0xb4b117e9UL },
+ { &fnv_test_str[21], (Fnv32_t) 0xfdc80fd1UL },
+ { &fnv_test_str[22], (Fnv32_t) 0x31f0b210UL },
+ { &fnv_test_str[23], (Fnv32_t) 0xffe8d046UL },
+ { &fnv_test_str[24], (Fnv32_t) 0x6e772a5cUL },
+ { &fnv_test_str[25], (Fnv32_t) 0x4197aebbUL },
+ { &fnv_test_str[26], (Fnv32_t) 0xfcc8100fUL },
+ { &fnv_test_str[27], (Fnv32_t) 0xfdf147faUL },
+ { &fnv_test_str[28], (Fnv32_t) 0xbcd44ee1UL },
+ { &fnv_test_str[29], (Fnv32_t) 0x23382c13UL },
+ { &fnv_test_str[30], (Fnv32_t) 0x846d619eUL },
+ { &fnv_test_str[31], (Fnv32_t) 0x1630abdbUL },
+ { &fnv_test_str[32], (Fnv32_t) 0xc99e89b2UL },
+ { &fnv_test_str[33], (Fnv32_t) 0x1692c316UL },
+ { &fnv_test_str[34], (Fnv32_t) 0x9f091bcaUL },
+ { &fnv_test_str[35], (Fnv32_t) 0x2556be9bUL },
+ { &fnv_test_str[36], (Fnv32_t) 0x628e0e73UL },
+ { &fnv_test_str[37], (Fnv32_t) 0x98a0bf6cUL },
+ { &fnv_test_str[38], (Fnv32_t) 0xb10d5725UL },
+ { &fnv_test_str[39], (Fnv32_t) 0xdd002f35UL },
+ { &fnv_test_str[40], (Fnv32_t) 0x4197aed4UL },
+ { &fnv_test_str[41], (Fnv32_t) 0xfcc81061UL },
+ { &fnv_test_str[42], (Fnv32_t) 0xfdf1479dUL },
+ { &fnv_test_str[43], (Fnv32_t) 0xbcd44e8eUL },
+ { &fnv_test_str[44], (Fnv32_t) 0x23382c33UL },
+ { &fnv_test_str[45], (Fnv32_t) 0x846d61e9UL },
+ { &fnv_test_str[46], (Fnv32_t) 0x1630abbaUL },
+ { &fnv_test_str[47], (Fnv32_t) 0xc99e89c1UL },
+ { &fnv_test_str[48], (Fnv32_t) 0x1692c336UL },
+ { &fnv_test_str[49], (Fnv32_t) 0x9f091ba2UL },
+ { &fnv_test_str[50], (Fnv32_t) 0x2556befeUL },
+ { &fnv_test_str[51], (Fnv32_t) 0x628e0e01UL },
+ { &fnv_test_str[52], (Fnv32_t) 0x98a0bf09UL },
+ { &fnv_test_str[53], (Fnv32_t) 0xb10d5704UL },
+ { &fnv_test_str[54], (Fnv32_t) 0xdd002f3fUL },
+ { &fnv_test_str[55], (Fnv32_t) 0x1c4a506fUL },
+ { &fnv_test_str[56], (Fnv32_t) 0x6e772a41UL },
+ { &fnv_test_str[57], (Fnv32_t) 0x26978421UL },
+ { &fnv_test_str[58], (Fnv32_t) 0xe184ff97UL },
+ { &fnv_test_str[59], (Fnv32_t) 0x9b5e5ac6UL },
+ { &fnv_test_str[60], (Fnv32_t) 0x5b88e592UL },
+ { &fnv_test_str[61], (Fnv32_t) 0xaa8164b7UL },
+ { &fnv_test_str[62], (Fnv32_t) 0x20b18c7bUL },
+ { &fnv_test_str[63], (Fnv32_t) 0xf28025c5UL },
+ { &fnv_test_str[64], (Fnv32_t) 0x84bb753fUL },
+ { &fnv_test_str[65], (Fnv32_t) 0x3219925aUL },
+ { &fnv_test_str[66], (Fnv32_t) 0x384163c6UL },
+ { &fnv_test_str[67], (Fnv32_t) 0x54f010d7UL },
+ { &fnv_test_str[68], (Fnv32_t) 0x8cea820cUL },
+ { &fnv_test_str[69], (Fnv32_t) 0xe12ab8eeUL },
+ { &fnv_test_str[70], (Fnv32_t) 0x26978453UL },
+ { &fnv_test_str[71], (Fnv32_t) 0xe184fff3UL },
+ { &fnv_test_str[72], (Fnv32_t) 0x9b5e5ab5UL },
+ { &fnv_test_str[73], (Fnv32_t) 0x5b88e5b2UL },
+ { &fnv_test_str[74], (Fnv32_t) 0xaa8164d6UL },
+ { &fnv_test_str[75], (Fnv32_t) 0x20b18c15UL },
+ { &fnv_test_str[76], (Fnv32_t) 0xf28025a1UL },
+ { &fnv_test_str[77], (Fnv32_t) 0x84bb751fUL },
+ { &fnv_test_str[78], (Fnv32_t) 0x3219922dUL },
+ { &fnv_test_str[79], (Fnv32_t) 0x384163aeUL },
+ { &fnv_test_str[80], (Fnv32_t) 0x54f010b2UL },
+ { &fnv_test_str[81], (Fnv32_t) 0x8cea8275UL },
+ { &fnv_test_str[82], (Fnv32_t) 0xe12ab8e4UL },
+ { &fnv_test_str[83], (Fnv32_t) 0x64411eaaUL },
+ { &fnv_test_str[84], (Fnv32_t) 0x6977223cUL },
+ { &fnv_test_str[85], (Fnv32_t) 0x428ae474UL },
+ { &fnv_test_str[86], (Fnv32_t) 0xb6fa7167UL },
+ { &fnv_test_str[87], (Fnv32_t) 0x73408525UL },
+ { &fnv_test_str[88], (Fnv32_t) 0xb78320a1UL },
+ { &fnv_test_str[89], (Fnv32_t) 0x0caf4135UL },
+ { &fnv_test_str[90], (Fnv32_t) 0xb78320a2UL },
+ { &fnv_test_str[91], (Fnv32_t) 0xcdc88e80UL },
+ { &fnv_test_str[92], (Fnv32_t) 0xb78320a3UL },
+ { &fnv_test_str[93], (Fnv32_t) 0x8ee1dbcbUL },
+ { &fnv_test_str[94], (Fnv32_t) 0xb78320a4UL },
+ { &fnv_test_str[95], (Fnv32_t) 0x4ffb2716UL },
+ { &fnv_test_str[96], (Fnv32_t) 0x860632aaUL },
+ { &fnv_test_str[97], (Fnv32_t) 0xcc2c5c64UL },
+ { &fnv_test_str[98], (Fnv32_t) 0x860632a4UL },
+ { &fnv_test_str[99], (Fnv32_t) 0x2a7ec4a6UL },
+ { &fnv_test_str[100], (Fnv32_t) 0x860632baUL },
+ { &fnv_test_str[101], (Fnv32_t) 0xfefe8e14UL },
+ { &fnv_test_str[102], (Fnv32_t) 0x0a3cffd8UL },
+ { &fnv_test_str[103], (Fnv32_t) 0xf606c108UL },
+ { &fnv_test_str[104], (Fnv32_t) 0x0a3cffdbUL },
+ { &fnv_test_str[105], (Fnv32_t) 0xf906c5c1UL },
+ { &fnv_test_str[106], (Fnv32_t) 0x0a3cffdaUL },
+ { &fnv_test_str[107], (Fnv32_t) 0xf806c42eUL },
+ { &fnv_test_str[108], (Fnv32_t) 0xc07167d7UL },
+ { &fnv_test_str[109], (Fnv32_t) 0xc9867775UL },
+ { &fnv_test_str[110], (Fnv32_t) 0xbf716668UL },
+ { &fnv_test_str[111], (Fnv32_t) 0xc78435b8UL },
+ { &fnv_test_str[112], (Fnv32_t) 0xc6717155UL },
+ { &fnv_test_str[113], (Fnv32_t) 0xb99568cfUL },
+ { &fnv_test_str[114], (Fnv32_t) 0x7662e0d6UL },
+ { &fnv_test_str[115], (Fnv32_t) 0x33a7f0e2UL },
+ { &fnv_test_str[116], (Fnv32_t) 0xc2732f95UL },
+ { &fnv_test_str[117], (Fnv32_t) 0xb053e78fUL },
+ { &fnv_test_str[118], (Fnv32_t) 0x3a19c02aUL },
+ { &fnv_test_str[119], (Fnv32_t) 0xa089821eUL },
+ { &fnv_test_str[120], (Fnv32_t) 0x31ae8f83UL },
+ { &fnv_test_str[121], (Fnv32_t) 0x995fa9c4UL },
+ { &fnv_test_str[122], (Fnv32_t) 0x35983f8cUL },
+ { &fnv_test_str[123], (Fnv32_t) 0x5036a251UL },
+ { &fnv_test_str[124], (Fnv32_t) 0x97018583UL },
+ { &fnv_test_str[125], (Fnv32_t) 0xb4448d60UL },
+ { &fnv_test_str[126], (Fnv32_t) 0x025dfe59UL },
+ { &fnv_test_str[127], (Fnv32_t) 0xc5eab3afUL },
+ { &fnv_test_str[128], (Fnv32_t) 0x7d21ba1eUL },
+ { &fnv_test_str[129], (Fnv32_t) 0x7704cddbUL },
+ { &fnv_test_str[130], (Fnv32_t) 0xd0071bfeUL },
+ { &fnv_test_str[131], (Fnv32_t) 0x0ff3774cUL },
+ { &fnv_test_str[132], (Fnv32_t) 0xb0fea0eaUL },
+ { &fnv_test_str[133], (Fnv32_t) 0x58177303UL },
+ { &fnv_test_str[134], (Fnv32_t) 0x4f599cdaUL },
+ { &fnv_test_str[135], (Fnv32_t) 0x3e590a47UL },
+ { &fnv_test_str[136], (Fnv32_t) 0x965595f8UL },
+ { &fnv_test_str[137], (Fnv32_t) 0xc37f178dUL },
+ { &fnv_test_str[138], (Fnv32_t) 0x9711dd26UL },
+ { &fnv_test_str[139], (Fnv32_t) 0x23c99b7fUL },
+ { &fnv_test_str[140], (Fnv32_t) 0x6e568b17UL },
+ { &fnv_test_str[141], (Fnv32_t) 0x43f0245bUL },
+ { &fnv_test_str[142], (Fnv32_t) 0xbcb7a001UL },
+ { &fnv_test_str[143], (Fnv32_t) 0x12e6dffeUL },
+ { &fnv_test_str[144], (Fnv32_t) 0x0792f2d6UL },
+ { &fnv_test_str[145], (Fnv32_t) 0xb966936bUL },
+ { &fnv_test_str[146], (Fnv32_t) 0x46439ac5UL },
+ { &fnv_test_str[147], (Fnv32_t) 0x728d49afUL },
+ { &fnv_test_str[148], (Fnv32_t) 0xd33745c9UL },
+ { &fnv_test_str[149], (Fnv32_t) 0xbc382a57UL },
+ { &fnv_test_str[150], (Fnv32_t) 0x4bda1d31UL },
+ { &fnv_test_str[151], (Fnv32_t) 0xce35ccaeUL },
+ { &fnv_test_str[152], (Fnv32_t) 0x3b6eed94UL },
+ { &fnv_test_str[153], (Fnv32_t) 0x445c9c58UL },
+ { &fnv_test_str[154], (Fnv32_t) 0x3db8bf9dUL },
+ { &fnv_test_str[155], (Fnv32_t) 0x2dee116dUL },
+ { &fnv_test_str[156], (Fnv32_t) 0xc18738daUL },
+ { &fnv_test_str[157], (Fnv32_t) 0x5b156176UL },
+ { &fnv_test_str[158], (Fnv32_t) 0x2aa7d593UL },
+ { &fnv_test_str[159], (Fnv32_t) 0xb2409658UL },
+ { &fnv_test_str[160], (Fnv32_t) 0xe1489528UL },
+ { &fnv_test_str[161], (Fnv32_t) 0xfe1ee07eUL },
+ { &fnv_test_str[162], (Fnv32_t) 0xe8842315UL },
+ { &fnv_test_str[163], (Fnv32_t) 0x3a6a63a2UL },
+ { &fnv_test_str[164], (Fnv32_t) 0x06d2c18cUL },
+ { &fnv_test_str[165], (Fnv32_t) 0xf8ef7225UL },
+ { &fnv_test_str[166], (Fnv32_t) 0x843d3300UL },
+ { &fnv_test_str[167], (Fnv32_t) 0xbb24f7aeUL },
+ { &fnv_test_str[168], (Fnv32_t) 0x878c0ec9UL },
+ { &fnv_test_str[169], (Fnv32_t) 0xb557810fUL },
+ { &fnv_test_str[170], (Fnv32_t) 0x57423246UL },
+ { &fnv_test_str[171], (Fnv32_t) 0x87f7505eUL },
+ { &fnv_test_str[172], (Fnv32_t) 0xbb809f20UL },
+ { &fnv_test_str[173], (Fnv32_t) 0x8932abb5UL },
+ { &fnv_test_str[174], (Fnv32_t) 0x0a9b3aa0UL },
+ { &fnv_test_str[175], (Fnv32_t) 0xb8682a24UL },
+ { &fnv_test_str[176], (Fnv32_t) 0xa7ac1c56UL },
+ { &fnv_test_str[177], (Fnv32_t) 0x11409252UL },
+ { &fnv_test_str[178], (Fnv32_t) 0xa987f517UL },
+ { &fnv_test_str[179], (Fnv32_t) 0xf309e7edUL },
+ { &fnv_test_str[180], (Fnv32_t) 0xc9e8f417UL },
+ { &fnv_test_str[181], (Fnv32_t) 0x7f447bddUL },
+ { &fnv_test_str[182], (Fnv32_t) 0xb929adc5UL },
+ { &fnv_test_str[183], (Fnv32_t) 0x57022879UL },
+ { &fnv_test_str[184], (Fnv32_t) 0xdcfd2c49UL },
+ { &fnv_test_str[185], (Fnv32_t) 0x6edafff5UL },
+ { &fnv_test_str[186], (Fnv32_t) 0xf04fb1f1UL },
+ { &fnv_test_str[187], (Fnv32_t) 0xfb7de8b9UL },
+ { &fnv_test_str[188], (Fnv32_t) 0xc5f1d7e9UL },
+ { &fnv_test_str[189], (Fnv32_t) 0x32c1f439UL },
+ { &fnv_test_str[190], (Fnv32_t) 0x7fd3eb7dUL },
+ { &fnv_test_str[191], (Fnv32_t) 0x81597da5UL },
+ { &fnv_test_str[192], (Fnv32_t) 0x05eb7a25UL },
+ { &fnv_test_str[193], (Fnv32_t) 0x9c0fa1b5UL },
+ { &fnv_test_str[194], (Fnv32_t) 0x53ccb1c5UL },
+ { &fnv_test_str[195], (Fnv32_t) 0xfabece15UL },
+ { &fnv_test_str[196], (Fnv32_t) 0x4ad745a5UL },
+ { &fnv_test_str[197], (Fnv32_t) 0xe5bdc495UL },
+ { &fnv_test_str[198], (Fnv32_t) 0x23b3c0a5UL },
+ { &fnv_test_str[199], (Fnv32_t) 0xfa823dd5UL },
+ { &fnv_test_str[200], (Fnv32_t) 0x0c6c58b9UL },
+ { &fnv_test_str[201], (Fnv32_t) 0xe2dbccd5UL },
+ { &fnv_test_str[202], (Fnv32_t) 0xdb7f50f9UL },
+ { NULL, 0 }
+};
+
+/* FNV-1a 32 bit test vectors */
+struct fnv1a_32_test_vector fnv1a_32_vector[] = {
+ { &fnv_test_str[0], (Fnv32_t) 0x811c9dc5UL },
+ { &fnv_test_str[1], (Fnv32_t) 0xe40c292cUL },
+ { &fnv_test_str[2], (Fnv32_t) 0xe70c2de5UL },
+ { &fnv_test_str[3], (Fnv32_t) 0xe60c2c52UL },
+ { &fnv_test_str[4], (Fnv32_t) 0xe10c2473UL },
+ { &fnv_test_str[5], (Fnv32_t) 0xe00c22e0UL },
+ { &fnv_test_str[6], (Fnv32_t) 0xe30c2799UL },
+ { &fnv_test_str[7], (Fnv32_t) 0x6222e842UL },
+ { &fnv_test_str[8], (Fnv32_t) 0xa9f37ed7UL },
+ { &fnv_test_str[9], (Fnv32_t) 0x3f5076efUL },
+ { &fnv_test_str[10], (Fnv32_t) 0x39aaa18aUL },
+ { &fnv_test_str[11], (Fnv32_t) 0xbf9cf968UL },
+ { &fnv_test_str[12], (Fnv32_t) 0x050c5d1fUL },
+ { &fnv_test_str[13], (Fnv32_t) 0x2b24d044UL },
+ { &fnv_test_str[14], (Fnv32_t) 0x9d2c3f7fUL },
+ { &fnv_test_str[15], (Fnv32_t) 0x7729c516UL },
+ { &fnv_test_str[16], (Fnv32_t) 0xb91d6109UL },
+ { &fnv_test_str[17], (Fnv32_t) 0x931ae6a0UL },
+ { &fnv_test_str[18], (Fnv32_t) 0x052255dbUL },
+ { &fnv_test_str[19], (Fnv32_t) 0xbef39fe6UL },
+ { &fnv_test_str[20], (Fnv32_t) 0x6150ac75UL },
+ { &fnv_test_str[21], (Fnv32_t) 0x9aab3a3dUL },
+ { &fnv_test_str[22], (Fnv32_t) 0x519c4c3eUL },
+ { &fnv_test_str[23], (Fnv32_t) 0x0c1c9eb8UL },
+ { &fnv_test_str[24], (Fnv32_t) 0x5f299f4eUL },
+ { &fnv_test_str[25], (Fnv32_t) 0xef8580f3UL },
+ { &fnv_test_str[26], (Fnv32_t) 0xac297727UL },
+ { &fnv_test_str[27], (Fnv32_t) 0x4546b9c0UL },
+ { &fnv_test_str[28], (Fnv32_t) 0xbd564e7dUL },
+ { &fnv_test_str[29], (Fnv32_t) 0x6bdd5c67UL },
+ { &fnv_test_str[30], (Fnv32_t) 0xdd77ed30UL },
+ { &fnv_test_str[31], (Fnv32_t) 0xf4ca9683UL },
+ { &fnv_test_str[32], (Fnv32_t) 0x4aeb9bd0UL },
+ { &fnv_test_str[33], (Fnv32_t) 0xe0e67ad0UL },
+ { &fnv_test_str[34], (Fnv32_t) 0xc2d32fa8UL },
+ { &fnv_test_str[35], (Fnv32_t) 0x7f743fb7UL },
+ { &fnv_test_str[36], (Fnv32_t) 0x6900631fUL },
+ { &fnv_test_str[37], (Fnv32_t) 0xc59c990eUL },
+ { &fnv_test_str[38], (Fnv32_t) 0x448524fdUL },
+ { &fnv_test_str[39], (Fnv32_t) 0xd49930d5UL },
+ { &fnv_test_str[40], (Fnv32_t) 0x1c85c7caUL },
+ { &fnv_test_str[41], (Fnv32_t) 0x0229fe89UL },
+ { &fnv_test_str[42], (Fnv32_t) 0x2c469265UL },
+ { &fnv_test_str[43], (Fnv32_t) 0xce566940UL },
+ { &fnv_test_str[44], (Fnv32_t) 0x8bdd8ec7UL },
+ { &fnv_test_str[45], (Fnv32_t) 0x34787625UL },
+ { &fnv_test_str[46], (Fnv32_t) 0xd3ca6290UL },
+ { &fnv_test_str[47], (Fnv32_t) 0xddeaf039UL },
+ { &fnv_test_str[48], (Fnv32_t) 0xc0e64870UL },
+ { &fnv_test_str[49], (Fnv32_t) 0xdad35570UL },
+ { &fnv_test_str[50], (Fnv32_t) 0x5a740578UL },
+ { &fnv_test_str[51], (Fnv32_t) 0x5b004d15UL },
+ { &fnv_test_str[52], (Fnv32_t) 0x6a9c09cdUL },
+ { &fnv_test_str[53], (Fnv32_t) 0x2384f10aUL },
+ { &fnv_test_str[54], (Fnv32_t) 0xda993a47UL },
+ { &fnv_test_str[55], (Fnv32_t) 0x8227df4fUL },
+ { &fnv_test_str[56], (Fnv32_t) 0x4c298165UL },
+ { &fnv_test_str[57], (Fnv32_t) 0xfc563735UL },
+ { &fnv_test_str[58], (Fnv32_t) 0x8cb91483UL },
+ { &fnv_test_str[59], (Fnv32_t) 0x775bf5d0UL },
+ { &fnv_test_str[60], (Fnv32_t) 0xd5c428d0UL },
+ { &fnv_test_str[61], (Fnv32_t) 0x34cc0ea3UL },
+ { &fnv_test_str[62], (Fnv32_t) 0xea3b4cb7UL },
+ { &fnv_test_str[63], (Fnv32_t) 0x8e59f029UL },
+ { &fnv_test_str[64], (Fnv32_t) 0x2094de2bUL },
+ { &fnv_test_str[65], (Fnv32_t) 0xa65a0ad4UL },
+ { &fnv_test_str[66], (Fnv32_t) 0x9bbee5f4UL },
+ { &fnv_test_str[67], (Fnv32_t) 0xbe836343UL },
+ { &fnv_test_str[68], (Fnv32_t) 0x22d5344eUL },
+ { &fnv_test_str[69], (Fnv32_t) 0x19a1470cUL },
+ { &fnv_test_str[70], (Fnv32_t) 0x4a56b1ffUL },
+ { &fnv_test_str[71], (Fnv32_t) 0x70b8e86fUL },
+ { &fnv_test_str[72], (Fnv32_t) 0x0a5b4a39UL },
+ { &fnv_test_str[73], (Fnv32_t) 0xb5c3f670UL },
+ { &fnv_test_str[74], (Fnv32_t) 0x53cc3f70UL },
+ { &fnv_test_str[75], (Fnv32_t) 0xc03b0a99UL },
+ { &fnv_test_str[76], (Fnv32_t) 0x7259c415UL },
+ { &fnv_test_str[77], (Fnv32_t) 0x4095108bUL },
+ { &fnv_test_str[78], (Fnv32_t) 0x7559bdb1UL },
+ { &fnv_test_str[79], (Fnv32_t) 0xb3bf0bbcUL },
+ { &fnv_test_str[80], (Fnv32_t) 0x2183ff1cUL },
+ { &fnv_test_str[81], (Fnv32_t) 0x2bd54279UL },
+ { &fnv_test_str[82], (Fnv32_t) 0x23a156caUL },
+ { &fnv_test_str[83], (Fnv32_t) 0x64e2d7e4UL },
+ { &fnv_test_str[84], (Fnv32_t) 0x683af69aUL },
+ { &fnv_test_str[85], (Fnv32_t) 0xaed2346eUL },
+ { &fnv_test_str[86], (Fnv32_t) 0x4f9f2cabUL },
+ { &fnv_test_str[87], (Fnv32_t) 0x02935131UL },
+ { &fnv_test_str[88], (Fnv32_t) 0xc48fb86dUL },
+ { &fnv_test_str[89], (Fnv32_t) 0x2269f369UL },
+ { &fnv_test_str[90], (Fnv32_t) 0xc18fb3b4UL },
+ { &fnv_test_str[91], (Fnv32_t) 0x50ef1236UL },
+ { &fnv_test_str[92], (Fnv32_t) 0xc28fb547UL },
+ { &fnv_test_str[93], (Fnv32_t) 0x96c3bf47UL },
+ { &fnv_test_str[94], (Fnv32_t) 0xbf8fb08eUL },
+ { &fnv_test_str[95], (Fnv32_t) 0xf3e4d49cUL },
+ { &fnv_test_str[96], (Fnv32_t) 0x32179058UL },
+ { &fnv_test_str[97], (Fnv32_t) 0x280bfee6UL },
+ { &fnv_test_str[98], (Fnv32_t) 0x30178d32UL },
+ { &fnv_test_str[99], (Fnv32_t) 0x21addaf8UL },
+ { &fnv_test_str[100], (Fnv32_t) 0x4217a988UL },
+ { &fnv_test_str[101], (Fnv32_t) 0x772633d6UL },
+ { &fnv_test_str[102], (Fnv32_t) 0x08a3d11eUL },
+ { &fnv_test_str[103], (Fnv32_t) 0xb7e2323aUL },
+ { &fnv_test_str[104], (Fnv32_t) 0x07a3cf8bUL },
+ { &fnv_test_str[105], (Fnv32_t) 0x91dfb7d1UL },
+ { &fnv_test_str[106], (Fnv32_t) 0x06a3cdf8UL },
+ { &fnv_test_str[107], (Fnv32_t) 0x6bdd3d68UL },
+ { &fnv_test_str[108], (Fnv32_t) 0x1d5636a7UL },
+ { &fnv_test_str[109], (Fnv32_t) 0xd5b808e5UL },
+ { &fnv_test_str[110], (Fnv32_t) 0x1353e852UL },
+ { &fnv_test_str[111], (Fnv32_t) 0xbf16b916UL },
+ { &fnv_test_str[112], (Fnv32_t) 0xa55b89edUL },
+ { &fnv_test_str[113], (Fnv32_t) 0x3c1a2017UL },
+ { &fnv_test_str[114], (Fnv32_t) 0x0588b13cUL },
+ { &fnv_test_str[115], (Fnv32_t) 0xf22f0174UL },
+ { &fnv_test_str[116], (Fnv32_t) 0xe83641e1UL },
+ { &fnv_test_str[117], (Fnv32_t) 0x6e69b533UL },
+ { &fnv_test_str[118], (Fnv32_t) 0xf1760448UL },
+ { &fnv_test_str[119], (Fnv32_t) 0x64c8bd58UL },
+ { &fnv_test_str[120], (Fnv32_t) 0x97b4ea23UL },
+ { &fnv_test_str[121], (Fnv32_t) 0x9a4e92e6UL },
+ { &fnv_test_str[122], (Fnv32_t) 0xcfb14012UL },
+ { &fnv_test_str[123], (Fnv32_t) 0xf01b2511UL },
+ { &fnv_test_str[124], (Fnv32_t) 0x0bbb59c3UL },
+ { &fnv_test_str[125], (Fnv32_t) 0xce524afaUL },
+ { &fnv_test_str[126], (Fnv32_t) 0xdd16ef45UL },
+ { &fnv_test_str[127], (Fnv32_t) 0x60648bb3UL },
+ { &fnv_test_str[128], (Fnv32_t) 0x7fa4bcfcUL },
+ { &fnv_test_str[129], (Fnv32_t) 0x5053ae17UL },
+ { &fnv_test_str[130], (Fnv32_t) 0xc9302890UL },
+ { &fnv_test_str[131], (Fnv32_t) 0x956ded32UL },
+ { &fnv_test_str[132], (Fnv32_t) 0x9136db84UL },
+ { &fnv_test_str[133], (Fnv32_t) 0xdf9d3323UL },
+ { &fnv_test_str[134], (Fnv32_t) 0x32bb6cd0UL },
+ { &fnv_test_str[135], (Fnv32_t) 0xc8f8385bUL },
+ { &fnv_test_str[136], (Fnv32_t) 0xeb08bfbaUL },
+ { &fnv_test_str[137], (Fnv32_t) 0x62cc8e3dUL },
+ { &fnv_test_str[138], (Fnv32_t) 0xc3e20f5cUL },
+ { &fnv_test_str[139], (Fnv32_t) 0x39e97f17UL },
+ { &fnv_test_str[140], (Fnv32_t) 0x7837b203UL },
+ { &fnv_test_str[141], (Fnv32_t) 0x319e877bUL },
+ { &fnv_test_str[142], (Fnv32_t) 0xd3e63f89UL },
+ { &fnv_test_str[143], (Fnv32_t) 0x29b50b38UL },
+ { &fnv_test_str[144], (Fnv32_t) 0x5ed678b8UL },
+ { &fnv_test_str[145], (Fnv32_t) 0xb0d5b793UL },
+ { &fnv_test_str[146], (Fnv32_t) 0x52450be5UL },
+ { &fnv_test_str[147], (Fnv32_t) 0xfa72d767UL },
+ { &fnv_test_str[148], (Fnv32_t) 0x95066709UL },
+ { &fnv_test_str[149], (Fnv32_t) 0x7f52e123UL },
+ { &fnv_test_str[150], (Fnv32_t) 0x76966481UL },
+ { &fnv_test_str[151], (Fnv32_t) 0x063258b0UL },
+ { &fnv_test_str[152], (Fnv32_t) 0x2ded6e8aUL },
+ { &fnv_test_str[153], (Fnv32_t) 0xb07d7c52UL },
+ { &fnv_test_str[154], (Fnv32_t) 0xd0c71b71UL },
+ { &fnv_test_str[155], (Fnv32_t) 0xf684f1bdUL },
+ { &fnv_test_str[156], (Fnv32_t) 0x868ecfa8UL },
+ { &fnv_test_str[157], (Fnv32_t) 0xf794f684UL },
+ { &fnv_test_str[158], (Fnv32_t) 0xd19701c3UL },
+ { &fnv_test_str[159], (Fnv32_t) 0x346e171eUL },
+ { &fnv_test_str[160], (Fnv32_t) 0x91f8f676UL },
+ { &fnv_test_str[161], (Fnv32_t) 0x0bf58848UL },
+ { &fnv_test_str[162], (Fnv32_t) 0x6317b6d1UL },
+ { &fnv_test_str[163], (Fnv32_t) 0xafad4c54UL },
+ { &fnv_test_str[164], (Fnv32_t) 0x0f25681eUL },
+ { &fnv_test_str[165], (Fnv32_t) 0x91b18d49UL },
+ { &fnv_test_str[166], (Fnv32_t) 0x7d61c12eUL },
+ { &fnv_test_str[167], (Fnv32_t) 0x5147d25cUL },
+ { &fnv_test_str[168], (Fnv32_t) 0x9a8b6805UL },
+ { &fnv_test_str[169], (Fnv32_t) 0x4cd2a447UL },
+ { &fnv_test_str[170], (Fnv32_t) 0x1e549b14UL },
+ { &fnv_test_str[171], (Fnv32_t) 0x2fe1b574UL },
+ { &fnv_test_str[172], (Fnv32_t) 0xcf0cd31eUL },
+ { &fnv_test_str[173], (Fnv32_t) 0x6c471669UL },
+ { &fnv_test_str[174], (Fnv32_t) 0x0e5eef1eUL },
+ { &fnv_test_str[175], (Fnv32_t) 0x2bed3602UL },
+ { &fnv_test_str[176], (Fnv32_t) 0xb26249e0UL },
+ { &fnv_test_str[177], (Fnv32_t) 0x2c9b86a4UL },
+ { &fnv_test_str[178], (Fnv32_t) 0xe415e2bbUL },
+ { &fnv_test_str[179], (Fnv32_t) 0x18a98d1dUL },
+ { &fnv_test_str[180], (Fnv32_t) 0xb7df8b7bUL },
+ { &fnv_test_str[181], (Fnv32_t) 0x241e9075UL },
+ { &fnv_test_str[182], (Fnv32_t) 0x063f70ddUL },
+ { &fnv_test_str[183], (Fnv32_t) 0x0295aed9UL },
+ { &fnv_test_str[184], (Fnv32_t) 0x56a7f781UL },
+ { &fnv_test_str[185], (Fnv32_t) 0x253bc645UL },
+ { &fnv_test_str[186], (Fnv32_t) 0x46610921UL },
+ { &fnv_test_str[187], (Fnv32_t) 0x7c1577f9UL },
+ { &fnv_test_str[188], (Fnv32_t) 0x512b2851UL },
+ { &fnv_test_str[189], (Fnv32_t) 0x76823999UL },
+ { &fnv_test_str[190], (Fnv32_t) 0xc0586935UL },
+ { &fnv_test_str[191], (Fnv32_t) 0xf3415c85UL },
+ { &fnv_test_str[192], (Fnv32_t) 0x0ae4ff65UL },
+ { &fnv_test_str[193], (Fnv32_t) 0x58b79725UL },
+ { &fnv_test_str[194], (Fnv32_t) 0xdea43aa5UL },
+ { &fnv_test_str[195], (Fnv32_t) 0x2bb3be35UL },
+ { &fnv_test_str[196], (Fnv32_t) 0xea777a45UL },
+ { &fnv_test_str[197], (Fnv32_t) 0x8f21c305UL },
+ { &fnv_test_str[198], (Fnv32_t) 0x5c9d0865UL },
+ { &fnv_test_str[199], (Fnv32_t) 0xfa823dd5UL },
+ { &fnv_test_str[200], (Fnv32_t) 0x21a27271UL },
+ { &fnv_test_str[201], (Fnv32_t) 0x83c5c6d5UL },
+ { &fnv_test_str[202], (Fnv32_t) 0x813b0881UL },
+ { NULL, 0 }
+};
+
+/* FNV-0 64 bit test vectors */
+#if defined(HAVE_64BIT_LONG_LONG)
+struct fnv0_64_test_vector fnv0_64_vector[] = {
+ { &fnv_test_str[0], (Fnv64_t) 0x0000000000000000ULL },
+ { &fnv_test_str[1], (Fnv64_t) 0x0000000000000061ULL },
+ { &fnv_test_str[2], (Fnv64_t) 0x0000000000000062ULL },
+ { &fnv_test_str[3], (Fnv64_t) 0x0000000000000063ULL },
+ { &fnv_test_str[4], (Fnv64_t) 0x0000000000000064ULL },
+ { &fnv_test_str[5], (Fnv64_t) 0x0000000000000065ULL },
+ { &fnv_test_str[6], (Fnv64_t) 0x0000000000000066ULL },
+ { &fnv_test_str[7], (Fnv64_t) 0x000066000000ad3dULL },
+ { &fnv_test_str[8], (Fnv64_t) 0x015a8f0001265ec8ULL },
+ { &fnv_test_str[9], (Fnv64_t) 0x733fc501f4330dbaULL },
+ { &fnv_test_str[10], (Fnv64_t) 0x08697c51f2c0536fULL },
+ { &fnv_test_str[11], (Fnv64_t) 0x0b91ae3f7ccdc5efULL },
+ { &fnv_test_str[12], (Fnv64_t) 0x0000000000000000ULL },
+ { &fnv_test_str[13], (Fnv64_t) 0x000061000000a4d3ULL },
+ { &fnv_test_str[14], (Fnv64_t) 0x000062000000a686ULL },
+ { &fnv_test_str[15], (Fnv64_t) 0x000063000000a839ULL },
+ { &fnv_test_str[16], (Fnv64_t) 0x000064000000a9ecULL },
+ { &fnv_test_str[17], (Fnv64_t) 0x000065000000ab9fULL },
+ { &fnv_test_str[18], (Fnv64_t) 0x000066000000ad52ULL },
+ { &fnv_test_str[19], (Fnv64_t) 0x015a8f0001265ea7ULL },
+ { &fnv_test_str[20], (Fnv64_t) 0x733fc501f4330dd8ULL },
+ { &fnv_test_str[21], (Fnv64_t) 0x08697c51f2c0530eULL },
+ { &fnv_test_str[22], (Fnv64_t) 0x0b91ae3f7ccdc59dULL },
+ { &fnv_test_str[23], (Fnv64_t) 0x765104e111a7551dULL },
+ { &fnv_test_str[24], (Fnv64_t) 0x000063000000a851ULL },
+ { &fnv_test_str[25], (Fnv64_t) 0x01508a00011e01ccULL },
+ { &fnv_test_str[26], (Fnv64_t) 0x59dc4a01e5fd0dcaULL },
+ { &fnv_test_str[27], (Fnv64_t) 0xae5f8b39ccfe6e59ULL },
+ { &fnv_test_str[28], (Fnv64_t) 0x4ac7ec3754558154ULL },
+ { &fnv_test_str[29], (Fnv64_t) 0x6737b6044d4ac19cULL },
+ { &fnv_test_str[30], (Fnv64_t) 0xae6be54f5606fc63ULL },
+ { &fnv_test_str[31], (Fnv64_t) 0x685308cf2ddedc58ULL },
+ { &fnv_test_str[32], (Fnv64_t) 0x23f4500af1b069fbULL },
+ { &fnv_test_str[33], (Fnv64_t) 0xc88dfd98aec415a1ULL },
+ { &fnv_test_str[34], (Fnv64_t) 0x8d5b8b70f730c0fbULL },
+ { &fnv_test_str[35], (Fnv64_t) 0x634eebf407d7eae4ULL },
+ { &fnv_test_str[36], (Fnv64_t) 0x9705d3a953e4211eULL },
+ { &fnv_test_str[37], (Fnv64_t) 0x8307c6b98ca4459fULL },
+ { &fnv_test_str[38], (Fnv64_t) 0x4a7c4c49fb224d0cULL },
+ { &fnv_test_str[39], (Fnv64_t) 0xb382adb5bb48eb6eULL },
+ { &fnv_test_str[40], (Fnv64_t) 0x01508a00011e01a3ULL },
+ { &fnv_test_str[41], (Fnv64_t) 0x59dc4a01e5fd0da4ULL },
+ { &fnv_test_str[42], (Fnv64_t) 0xae5f8b39ccfe6e3eULL },
+ { &fnv_test_str[43], (Fnv64_t) 0x4ac7ec375455813bULL },
+ { &fnv_test_str[44], (Fnv64_t) 0x6737b6044d4ac1bcULL },
+ { &fnv_test_str[45], (Fnv64_t) 0xae6be54f5606fc14ULL },
+ { &fnv_test_str[46], (Fnv64_t) 0x685308cf2ddedc39ULL },
+ { &fnv_test_str[47], (Fnv64_t) 0x23f4500af1b06988ULL },
+ { &fnv_test_str[48], (Fnv64_t) 0xc88dfd98aec41581ULL },
+ { &fnv_test_str[49], (Fnv64_t) 0x8d5b8b70f730c093ULL },
+ { &fnv_test_str[50], (Fnv64_t) 0x634eebf407d7ea81ULL },
+ { &fnv_test_str[51], (Fnv64_t) 0x9705d3a953e4216cULL },
+ { &fnv_test_str[52], (Fnv64_t) 0x8307c6b98ca445faULL },
+ { &fnv_test_str[53], (Fnv64_t) 0x4a7c4c49fb224d2dULL },
+ { &fnv_test_str[54], (Fnv64_t) 0xb382adb5bb48eb64ULL },
+ { &fnv_test_str[55], (Fnv64_t) 0x4ff899cd3ce80beaULL },
+ { &fnv_test_str[56], (Fnv64_t) 0x000063000000a84cULL },
+ { &fnv_test_str[57], (Fnv64_t) 0x01508500011df956ULL },
+ { &fnv_test_str[58], (Fnv64_t) 0x59cb5501e5eead46ULL },
+ { &fnv_test_str[59], (Fnv64_t) 0x832eb839b4906d81ULL },
+ { &fnv_test_str[60], (Fnv64_t) 0x78d08b0dd16a1213ULL },
+ { &fnv_test_str[61], (Fnv64_t) 0xb46e5b7ad73cb628ULL },
+ { &fnv_test_str[62], (Fnv64_t) 0xd43b99bbbc298596ULL },
+ { &fnv_test_str[63], (Fnv64_t) 0xcacbd000ba8dfd86ULL },
+ { &fnv_test_str[64], (Fnv64_t) 0x264ff73cff45ca92ULL },
+ { &fnv_test_str[65], (Fnv64_t) 0x5fabaea5c3973661ULL },
+ { &fnv_test_str[66], (Fnv64_t) 0x27f024ab59f166bbULL },
+ { &fnv_test_str[67], (Fnv64_t) 0xce750a29d5318fa4ULL },
+ { &fnv_test_str[68], (Fnv64_t) 0x026fe915433713d5ULL },
+ { &fnv_test_str[69], (Fnv64_t) 0x5b3ce4213696b2e5ULL },
+ { &fnv_test_str[70], (Fnv64_t) 0x01508500011df924ULL },
+ { &fnv_test_str[71], (Fnv64_t) 0x59cb5501e5eead22ULL },
+ { &fnv_test_str[72], (Fnv64_t) 0x832eb839b4906df2ULL },
+ { &fnv_test_str[73], (Fnv64_t) 0x78d08b0dd16a1233ULL },
+ { &fnv_test_str[74], (Fnv64_t) 0xb46e5b7ad73cb649ULL },
+ { &fnv_test_str[75], (Fnv64_t) 0xd43b99bbbc2985f8ULL },
+ { &fnv_test_str[76], (Fnv64_t) 0xcacbd000ba8dfde2ULL },
+ { &fnv_test_str[77], (Fnv64_t) 0x264ff73cff45cab2ULL },
+ { &fnv_test_str[78], (Fnv64_t) 0x5fabaea5c3973616ULL },
+ { &fnv_test_str[79], (Fnv64_t) 0x27f024ab59f166d3ULL },
+ { &fnv_test_str[80], (Fnv64_t) 0xce750a29d5318fc1ULL },
+ { &fnv_test_str[81], (Fnv64_t) 0x026fe915433713acULL },
+ { &fnv_test_str[82], (Fnv64_t) 0x5b3ce4213696b2efULL },
+ { &fnv_test_str[83], (Fnv64_t) 0x9f2a896fc211fb1fULL },
+ { &fnv_test_str[84], (Fnv64_t) 0x000068000000b0d1ULL },
+ { &fnv_test_str[85], (Fnv64_t) 0x01618900012c7323ULL },
+ { &fnv_test_str[86], (Fnv64_t) 0x3fa86e63bc7d03c8ULL },
+ { &fnv_test_str[87], (Fnv64_t) 0xa8375b79486d6cd8ULL },
+ { &fnv_test_str[88], (Fnv64_t) 0xa0d18504e316ac54ULL },
+ { &fnv_test_str[89], (Fnv64_t) 0x08a97b0004e7fe54ULL },
+ { &fnv_test_str[90], (Fnv64_t) 0xa0d18504e316ac57ULL },
+ { &fnv_test_str[91], (Fnv64_t) 0x1152f60009cffda9ULL },
+ { &fnv_test_str[92], (Fnv64_t) 0xa0d18504e316ac56ULL },
+ { &fnv_test_str[93], (Fnv64_t) 0x19fc71000eb7fcfeULL },
+ { &fnv_test_str[94], (Fnv64_t) 0xa0d18504e316ac51ULL },
+ { &fnv_test_str[95], (Fnv64_t) 0x22a5ec00139ffa53ULL },
+ { &fnv_test_str[96], (Fnv64_t) 0x29bed00139779a33ULL },
+ { &fnv_test_str[97], (Fnv64_t) 0x4dbc81014e3c19f5ULL },
+ { &fnv_test_str[98], (Fnv64_t) 0x29bed00139779a3dULL },
+ { &fnv_test_str[99], (Fnv64_t) 0x81a72b016b9f7573ULL },
+ { &fnv_test_str[100], (Fnv64_t) 0x29bed00139779a23ULL },
+ { &fnv_test_str[101], (Fnv64_t) 0xd85411019cbbce45ULL },
+ { &fnv_test_str[102], (Fnv64_t) 0xf548616b8621d657ULL },
+ { &fnv_test_str[103], (Fnv64_t) 0xebd3e0b4eb7f35d5ULL },
+ { &fnv_test_str[104], (Fnv64_t) 0xf548616b8621d654ULL },
+ { &fnv_test_str[105], (Fnv64_t) 0xebd3ddb4eb7f30bcULL },
+ { &fnv_test_str[106], (Fnv64_t) 0xf548616b8621d655ULL },
+ { &fnv_test_str[107], (Fnv64_t) 0xebd3deb4eb7f326fULL },
+ { &fnv_test_str[108], (Fnv64_t) 0x581cb60340ab0968ULL },
+ { &fnv_test_str[109], (Fnv64_t) 0x63d2af86e2a0fbb8ULL },
+ { &fnv_test_str[110], (Fnv64_t) 0x581cb70340ab0b37ULL },
+ { &fnv_test_str[111], (Fnv64_t) 0x63d63186e2a40e75ULL },
+ { &fnv_test_str[112], (Fnv64_t) 0x581cc40340ab212eULL },
+ { &fnv_test_str[113], (Fnv64_t) 0x64023f86e2c9612aULL },
+ { &fnv_test_str[114], (Fnv64_t) 0xdbda6a26c33c909fULL },
+ { &fnv_test_str[115], (Fnv64_t) 0xd0b2feddbfe9be2dULL },
+ { &fnv_test_str[116], (Fnv64_t) 0x9c9eae3f5d037decULL },
+ { &fnv_test_str[117], (Fnv64_t) 0x252001ab0ceef804ULL },
+ { &fnv_test_str[118], (Fnv64_t) 0x4456a56f9e05cfefULL },
+ { &fnv_test_str[119], (Fnv64_t) 0x250b0ba983e0531dULL },
+ { &fnv_test_str[120], (Fnv64_t) 0x52b007213b27b33eULL },
+ { &fnv_test_str[121], (Fnv64_t) 0xcbf29ce484222325ULL },
+ { &fnv_test_str[122], (Fnv64_t) 0xaf63bd4c8601b7dfULL },
+ { &fnv_test_str[123], (Fnv64_t) 0x128599ccddae09f8ULL },
+ { &fnv_test_str[124], (Fnv64_t) 0x270e4f1caebaf068ULL },
+ { &fnv_test_str[125], (Fnv64_t) 0x01517d497446a395ULL },
+ { &fnv_test_str[126], (Fnv64_t) 0x9af5a29a89450b40ULL },
+ { &fnv_test_str[127], (Fnv64_t) 0xb502f6c063ba72e8ULL },
+ { &fnv_test_str[128], (Fnv64_t) 0xacf41561498ca7dfULL },
+ { &fnv_test_str[129], (Fnv64_t) 0x6be8c2423a351542ULL },
+ { &fnv_test_str[130], (Fnv64_t) 0xd04f1f6da96ce4a3ULL },
+ { &fnv_test_str[131], (Fnv64_t) 0x69eb9a8f282c7235ULL },
+ { &fnv_test_str[132], (Fnv64_t) 0x6a7e5a418f77cfc5ULL },
+ { &fnv_test_str[133], (Fnv64_t) 0xbcaf568ddc2ecba0ULL },
+ { &fnv_test_str[134], (Fnv64_t) 0xb03b5cc4c38f8b1fULL },
+ { &fnv_test_str[135], (Fnv64_t) 0xf89a9f51432db828ULL },
+ { &fnv_test_str[136], (Fnv64_t) 0x549e856be6103429ULL },
+ { &fnv_test_str[137], (Fnv64_t) 0x3cf50d224d29377aULL },
+ { &fnv_test_str[138], (Fnv64_t) 0xdb762df418c10c37ULL },
+ { &fnv_test_str[139], (Fnv64_t) 0xfeeb4226b0e9a6baULL },
+ { &fnv_test_str[140], (Fnv64_t) 0x7004a4cd9310c052ULL },
+ { &fnv_test_str[141], (Fnv64_t) 0xd1c727d7f5329276ULL },
+ { &fnv_test_str[142], (Fnv64_t) 0xbe313796596ce908ULL },
+ { &fnv_test_str[143], (Fnv64_t) 0x768f67ede090fcc5ULL },
+ { &fnv_test_str[144], (Fnv64_t) 0xa81563cc9db9bfc3ULL },
+ { &fnv_test_str[145], (Fnv64_t) 0x47194043c55197a8ULL },
+ { &fnv_test_str[146], (Fnv64_t) 0xc99d81864aebab02ULL },
+ { &fnv_test_str[147], (Fnv64_t) 0xcc1f161b235ea4a2ULL },
+ { &fnv_test_str[148], (Fnv64_t) 0xaadab0c420ecd434ULL },
+ { &fnv_test_str[149], (Fnv64_t) 0x6b3c034d6f44d740ULL },
+ { &fnv_test_str[150], (Fnv64_t) 0x73a45e850602cbc6ULL },
+ { &fnv_test_str[151], (Fnv64_t) 0x72360f04f0cd227bULL },
+ { &fnv_test_str[152], (Fnv64_t) 0xa9ca80be384a778fULL },
+ { &fnv_test_str[153], (Fnv64_t) 0xd4085e66906889e3ULL },
+ { &fnv_test_str[154], (Fnv64_t) 0x93aa8b2748efdbc8ULL },
+ { &fnv_test_str[155], (Fnv64_t) 0x6f8cd678407436a2ULL },
+ { &fnv_test_str[156], (Fnv64_t) 0xf39a43d4dc8be4c7ULL },
+ { &fnv_test_str[157], (Fnv64_t) 0xd7f5cec91125d245ULL },
+ { &fnv_test_str[158], (Fnv64_t) 0x691d7b73be18adc4ULL },
+ { &fnv_test_str[159], (Fnv64_t) 0xf4361e01caf6b691ULL },
+ { &fnv_test_str[160], (Fnv64_t) 0xde7d8264f64be089ULL },
+ { &fnv_test_str[161], (Fnv64_t) 0xa34ff43e5545c06fULL },
+ { &fnv_test_str[162], (Fnv64_t) 0x181f0b8e908a2bdeULL },
+ { &fnv_test_str[163], (Fnv64_t) 0x28a965b78ddbc071ULL },
+ { &fnv_test_str[164], (Fnv64_t) 0xead9cea0e3cc6ae5ULL },
+ { &fnv_test_str[165], (Fnv64_t) 0x0b6743153b43ebbaULL },
+ { &fnv_test_str[166], (Fnv64_t) 0xa7aa3f012c74528dULL },
+ { &fnv_test_str[167], (Fnv64_t) 0x2d5d8ad7f9dffeb7ULL },
+ { &fnv_test_str[168], (Fnv64_t) 0x00750fb6e19624eaULL },
+ { &fnv_test_str[169], (Fnv64_t) 0x01c125a4e6c76c82ULL },
+ { &fnv_test_str[170], (Fnv64_t) 0x3fde3afac0722f1fULL },
+ { &fnv_test_str[171], (Fnv64_t) 0xd7c3eaf4abaa379dULL },
+ { &fnv_test_str[172], (Fnv64_t) 0xd2217e1c923c9f3fULL },
+ { &fnv_test_str[173], (Fnv64_t) 0x82d0a2e3b725caf6ULL },
+ { &fnv_test_str[174], (Fnv64_t) 0x0a10bee8eeb72e4fULL },
+ { &fnv_test_str[175], (Fnv64_t) 0xc530e8723e72c6fdULL },
+ { &fnv_test_str[176], (Fnv64_t) 0xd8d34dcd2e7bad99ULL },
+ { &fnv_test_str[177], (Fnv64_t) 0xecf77466e9a2baf3ULL },
+ { &fnv_test_str[178], (Fnv64_t) 0xde3d2ddb043b9666ULL },
+ { &fnv_test_str[179], (Fnv64_t) 0xd1cc824e1a8157d8ULL },
+ { &fnv_test_str[180], (Fnv64_t) 0x7d5c68ecbc90512eULL },
+ { &fnv_test_str[181], (Fnv64_t) 0x2f7c691b1d7c76d8ULL },
+ { &fnv_test_str[182], (Fnv64_t) 0x5d88c2bad3a46bc8ULL },
+ { &fnv_test_str[183], (Fnv64_t) 0xdf107320276647a0ULL },
+ { &fnv_test_str[184], (Fnv64_t) 0x0f78f22e7e70e9bcULL },
+ { &fnv_test_str[185], (Fnv64_t) 0x8c67be5c80f67d04ULL },
+ { &fnv_test_str[186], (Fnv64_t) 0x07c1adfa4d019194ULL },
+ { &fnv_test_str[187], (Fnv64_t) 0xce1312420c5b1af4ULL },
+ { &fnv_test_str[188], (Fnv64_t) 0x043a41b2dc53ab24ULL },
+ { &fnv_test_str[189], (Fnv64_t) 0x0b038eebf7340860ULL },
+ { &fnv_test_str[190], (Fnv64_t) 0x1bcd837353fb69b0ULL },
+ { &fnv_test_str[191], (Fnv64_t) 0x46f992fc59eff180ULL },
+ { &fnv_test_str[192], (Fnv64_t) 0x497678ee29ae79c0ULL },
+ { &fnv_test_str[193], (Fnv64_t) 0xb10a62280ddd4450ULL },
+ { &fnv_test_str[194], (Fnv64_t) 0x35eb228db4d68140ULL },
+ { &fnv_test_str[195], (Fnv64_t) 0x8b350e86d9470870ULL },
+ { &fnv_test_str[196], (Fnv64_t) 0x4e1fbdb2812e9540ULL },
+ { &fnv_test_str[197], (Fnv64_t) 0x051e080df69a0600ULL },
+ { &fnv_test_str[198], (Fnv64_t) 0x45e1e8ae54dadb40ULL },
+ { &fnv_test_str[199], (Fnv64_t) 0x0000000000000000ULL },
+ { &fnv_test_str[200], (Fnv64_t) 0xcd73806290557064ULL },
+ { &fnv_test_str[201], (Fnv64_t) 0x2613a37bbe0317c8ULL },
+ { &fnv_test_str[202], (Fnv64_t) 0x1480e21fcf2ae5e4ULL },
+ { NULL, (Fnv64_t) 0 }
+};
+#else /* HAVE_64BIT_LONG_LONG */
+struct fnv0_64_test_vector fnv0_64_vector[] = {
+ { &fnv_test_str[0], (Fnv64_t) {0x00000000UL, 0x00000000UL} },
+ { &fnv_test_str[1], (Fnv64_t) {0x00000061UL, 0x00000000UL} },
+ { &fnv_test_str[2], (Fnv64_t) {0x00000062UL, 0x00000000UL} },
+ { &fnv_test_str[3], (Fnv64_t) {0x00000063UL, 0x00000000UL} },
+ { &fnv_test_str[4], (Fnv64_t) {0x00000064UL, 0x00000000UL} },
+ { &fnv_test_str[5], (Fnv64_t) {0x00000065UL, 0x00000000UL} },
+ { &fnv_test_str[6], (Fnv64_t) {0x00000066UL, 0x00000000UL} },
+ { &fnv_test_str[7], (Fnv64_t) {0x0000ad3dUL, 0x00006600UL} },
+ { &fnv_test_str[8], (Fnv64_t) {0x01265ec8UL, 0x015a8f00UL} },
+ { &fnv_test_str[9], (Fnv64_t) {0xf4330dbaUL, 0x733fc501UL} },
+ { &fnv_test_str[10], (Fnv64_t) {0xf2c0536fUL, 0x08697c51UL} },
+ { &fnv_test_str[11], (Fnv64_t) {0x7ccdc5efUL, 0x0b91ae3fUL} },
+ { &fnv_test_str[12], (Fnv64_t) {0x00000000UL, 0x00000000UL} },
+ { &fnv_test_str[13], (Fnv64_t) {0x0000a4d3UL, 0x00006100UL} },
+ { &fnv_test_str[14], (Fnv64_t) {0x0000a686UL, 0x00006200UL} },
+ { &fnv_test_str[15], (Fnv64_t) {0x0000a839UL, 0x00006300UL} },
+ { &fnv_test_str[16], (Fnv64_t) {0x0000a9ecUL, 0x00006400UL} },
+ { &fnv_test_str[17], (Fnv64_t) {0x0000ab9fUL, 0x00006500UL} },
+ { &fnv_test_str[18], (Fnv64_t) {0x0000ad52UL, 0x00006600UL} },
+ { &fnv_test_str[19], (Fnv64_t) {0x01265ea7UL, 0x015a8f00UL} },
+ { &fnv_test_str[20], (Fnv64_t) {0xf4330dd8UL, 0x733fc501UL} },
+ { &fnv_test_str[21], (Fnv64_t) {0xf2c0530eUL, 0x08697c51UL} },
+ { &fnv_test_str[22], (Fnv64_t) {0x7ccdc59dUL, 0x0b91ae3fUL} },
+ { &fnv_test_str[23], (Fnv64_t) {0x11a7551dUL, 0x765104e1UL} },
+ { &fnv_test_str[24], (Fnv64_t) {0x0000a851UL, 0x00006300UL} },
+ { &fnv_test_str[25], (Fnv64_t) {0x011e01ccUL, 0x01508a00UL} },
+ { &fnv_test_str[26], (Fnv64_t) {0xe5fd0dcaUL, 0x59dc4a01UL} },
+ { &fnv_test_str[27], (Fnv64_t) {0xccfe6e59UL, 0xae5f8b39UL} },
+ { &fnv_test_str[28], (Fnv64_t) {0x54558154UL, 0x4ac7ec37UL} },
+ { &fnv_test_str[29], (Fnv64_t) {0x4d4ac19cUL, 0x6737b604UL} },
+ { &fnv_test_str[30], (Fnv64_t) {0x5606fc63UL, 0xae6be54fUL} },
+ { &fnv_test_str[31], (Fnv64_t) {0x2ddedc58UL, 0x685308cfUL} },
+ { &fnv_test_str[32], (Fnv64_t) {0xf1b069fbUL, 0x23f4500aUL} },
+ { &fnv_test_str[33], (Fnv64_t) {0xaec415a1UL, 0xc88dfd98UL} },
+ { &fnv_test_str[34], (Fnv64_t) {0xf730c0fbUL, 0x8d5b8b70UL} },
+ { &fnv_test_str[35], (Fnv64_t) {0x07d7eae4UL, 0x634eebf4UL} },
+ { &fnv_test_str[36], (Fnv64_t) {0x53e4211eUL, 0x9705d3a9UL} },
+ { &fnv_test_str[37], (Fnv64_t) {0x8ca4459fUL, 0x8307c6b9UL} },
+ { &fnv_test_str[38], (Fnv64_t) {0xfb224d0cUL, 0x4a7c4c49UL} },
+ { &fnv_test_str[39], (Fnv64_t) {0xbb48eb6eUL, 0xb382adb5UL} },
+ { &fnv_test_str[40], (Fnv64_t) {0x011e01a3UL, 0x01508a00UL} },
+ { &fnv_test_str[41], (Fnv64_t) {0xe5fd0da4UL, 0x59dc4a01UL} },
+ { &fnv_test_str[42], (Fnv64_t) {0xccfe6e3eUL, 0xae5f8b39UL} },
+ { &fnv_test_str[43], (Fnv64_t) {0x5455813bUL, 0x4ac7ec37UL} },
+ { &fnv_test_str[44], (Fnv64_t) {0x4d4ac1bcUL, 0x6737b604UL} },
+ { &fnv_test_str[45], (Fnv64_t) {0x5606fc14UL, 0xae6be54fUL} },
+ { &fnv_test_str[46], (Fnv64_t) {0x2ddedc39UL, 0x685308cfUL} },
+ { &fnv_test_str[47], (Fnv64_t) {0xf1b06988UL, 0x23f4500aUL} },
+ { &fnv_test_str[48], (Fnv64_t) {0xaec41581UL, 0xc88dfd98UL} },
+ { &fnv_test_str[49], (Fnv64_t) {0xf730c093UL, 0x8d5b8b70UL} },
+ { &fnv_test_str[50], (Fnv64_t) {0x07d7ea81UL, 0x634eebf4UL} },
+ { &fnv_test_str[51], (Fnv64_t) {0x53e4216cUL, 0x9705d3a9UL} },
+ { &fnv_test_str[52], (Fnv64_t) {0x8ca445faUL, 0x8307c6b9UL} },
+ { &fnv_test_str[53], (Fnv64_t) {0xfb224d2dUL, 0x4a7c4c49UL} },
+ { &fnv_test_str[54], (Fnv64_t) {0xbb48eb64UL, 0xb382adb5UL} },
+ { &fnv_test_str[55], (Fnv64_t) {0x3ce80beaUL, 0x4ff899cdUL} },
+ { &fnv_test_str[56], (Fnv64_t) {0x0000a84cUL, 0x00006300UL} },
+ { &fnv_test_str[57], (Fnv64_t) {0x011df956UL, 0x01508500UL} },
+ { &fnv_test_str[58], (Fnv64_t) {0xe5eead46UL, 0x59cb5501UL} },
+ { &fnv_test_str[59], (Fnv64_t) {0xb4906d81UL, 0x832eb839UL} },
+ { &fnv_test_str[60], (Fnv64_t) {0xd16a1213UL, 0x78d08b0dUL} },
+ { &fnv_test_str[61], (Fnv64_t) {0xd73cb628UL, 0xb46e5b7aUL} },
+ { &fnv_test_str[62], (Fnv64_t) {0xbc298596UL, 0xd43b99bbUL} },
+ { &fnv_test_str[63], (Fnv64_t) {0xba8dfd86UL, 0xcacbd000UL} },
+ { &fnv_test_str[64], (Fnv64_t) {0xff45ca92UL, 0x264ff73cUL} },
+ { &fnv_test_str[65], (Fnv64_t) {0xc3973661UL, 0x5fabaea5UL} },
+ { &fnv_test_str[66], (Fnv64_t) {0x59f166bbUL, 0x27f024abUL} },
+ { &fnv_test_str[67], (Fnv64_t) {0xd5318fa4UL, 0xce750a29UL} },
+ { &fnv_test_str[68], (Fnv64_t) {0x433713d5UL, 0x026fe915UL} },
+ { &fnv_test_str[69], (Fnv64_t) {0x3696b2e5UL, 0x5b3ce421UL} },
+ { &fnv_test_str[70], (Fnv64_t) {0x011df924UL, 0x01508500UL} },
+ { &fnv_test_str[71], (Fnv64_t) {0xe5eead22UL, 0x59cb5501UL} },
+ { &fnv_test_str[72], (Fnv64_t) {0xb4906df2UL, 0x832eb839UL} },
+ { &fnv_test_str[73], (Fnv64_t) {0xd16a1233UL, 0x78d08b0dUL} },
+ { &fnv_test_str[74], (Fnv64_t) {0xd73cb649UL, 0xb46e5b7aUL} },
+ { &fnv_test_str[75], (Fnv64_t) {0xbc2985f8UL, 0xd43b99bbUL} },
+ { &fnv_test_str[76], (Fnv64_t) {0xba8dfde2UL, 0xcacbd000UL} },
+ { &fnv_test_str[77], (Fnv64_t) {0xff45cab2UL, 0x264ff73cUL} },
+ { &fnv_test_str[78], (Fnv64_t) {0xc3973616UL, 0x5fabaea5UL} },
+ { &fnv_test_str[79], (Fnv64_t) {0x59f166d3UL, 0x27f024abUL} },
+ { &fnv_test_str[80], (Fnv64_t) {0xd5318fc1UL, 0xce750a29UL} },
+ { &fnv_test_str[81], (Fnv64_t) {0x433713acUL, 0x026fe915UL} },
+ { &fnv_test_str[82], (Fnv64_t) {0x3696b2efUL, 0x5b3ce421UL} },
+ { &fnv_test_str[83], (Fnv64_t) {0xc211fb1fUL, 0x9f2a896fUL} },
+ { &fnv_test_str[84], (Fnv64_t) {0x0000b0d1UL, 0x00006800UL} },
+ { &fnv_test_str[85], (Fnv64_t) {0x012c7323UL, 0x01618900UL} },
+ { &fnv_test_str[86], (Fnv64_t) {0xbc7d03c8UL, 0x3fa86e63UL} },
+ { &fnv_test_str[87], (Fnv64_t) {0x486d6cd8UL, 0xa8375b79UL} },
+ { &fnv_test_str[88], (Fnv64_t) {0xe316ac54UL, 0xa0d18504UL} },
+ { &fnv_test_str[89], (Fnv64_t) {0x04e7fe54UL, 0x08a97b00UL} },
+ { &fnv_test_str[90], (Fnv64_t) {0xe316ac57UL, 0xa0d18504UL} },
+ { &fnv_test_str[91], (Fnv64_t) {0x09cffda9UL, 0x1152f600UL} },
+ { &fnv_test_str[92], (Fnv64_t) {0xe316ac56UL, 0xa0d18504UL} },
+ { &fnv_test_str[93], (Fnv64_t) {0x0eb7fcfeUL, 0x19fc7100UL} },
+ { &fnv_test_str[94], (Fnv64_t) {0xe316ac51UL, 0xa0d18504UL} },
+ { &fnv_test_str[95], (Fnv64_t) {0x139ffa53UL, 0x22a5ec00UL} },
+ { &fnv_test_str[96], (Fnv64_t) {0x39779a33UL, 0x29bed001UL} },
+ { &fnv_test_str[97], (Fnv64_t) {0x4e3c19f5UL, 0x4dbc8101UL} },
+ { &fnv_test_str[98], (Fnv64_t) {0x39779a3dUL, 0x29bed001UL} },
+ { &fnv_test_str[99], (Fnv64_t) {0x6b9f7573UL, 0x81a72b01UL} },
+ { &fnv_test_str[100], (Fnv64_t) {0x39779a23UL, 0x29bed001UL} },
+ { &fnv_test_str[101], (Fnv64_t) {0x9cbbce45UL, 0xd8541101UL} },
+ { &fnv_test_str[102], (Fnv64_t) {0x8621d657UL, 0xf548616bUL} },
+ { &fnv_test_str[103], (Fnv64_t) {0xeb7f35d5UL, 0xebd3e0b4UL} },
+ { &fnv_test_str[104], (Fnv64_t) {0x8621d654UL, 0xf548616bUL} },
+ { &fnv_test_str[105], (Fnv64_t) {0xeb7f30bcUL, 0xebd3ddb4UL} },
+ { &fnv_test_str[106], (Fnv64_t) {0x8621d655UL, 0xf548616bUL} },
+ { &fnv_test_str[107], (Fnv64_t) {0xeb7f326fUL, 0xebd3deb4UL} },
+ { &fnv_test_str[108], (Fnv64_t) {0x40ab0968UL, 0x581cb603UL} },
+ { &fnv_test_str[109], (Fnv64_t) {0xe2a0fbb8UL, 0x63d2af86UL} },
+ { &fnv_test_str[110], (Fnv64_t) {0x40ab0b37UL, 0x581cb703UL} },
+ { &fnv_test_str[111], (Fnv64_t) {0xe2a40e75UL, 0x63d63186UL} },
+ { &fnv_test_str[112], (Fnv64_t) {0x40ab212eUL, 0x581cc403UL} },
+ { &fnv_test_str[113], (Fnv64_t) {0xe2c9612aUL, 0x64023f86UL} },
+ { &fnv_test_str[114], (Fnv64_t) {0xc33c909fUL, 0xdbda6a26UL} },
+ { &fnv_test_str[115], (Fnv64_t) {0xbfe9be2dUL, 0xd0b2feddUL} },
+ { &fnv_test_str[116], (Fnv64_t) {0x5d037decUL, 0x9c9eae3fUL} },
+ { &fnv_test_str[117], (Fnv64_t) {0x0ceef804UL, 0x252001abUL} },
+ { &fnv_test_str[118], (Fnv64_t) {0x9e05cfefUL, 0x4456a56fUL} },
+ { &fnv_test_str[119], (Fnv64_t) {0x83e0531dUL, 0x250b0ba9UL} },
+ { &fnv_test_str[120], (Fnv64_t) {0x3b27b33eUL, 0x52b00721UL} },
+ { &fnv_test_str[121], (Fnv64_t) {0x84222325UL, 0xcbf29ce4UL} },
+ { &fnv_test_str[122], (Fnv64_t) {0x8601b7dfUL, 0xaf63bd4cUL} },
+ { &fnv_test_str[123], (Fnv64_t) {0xddae09f8UL, 0x128599ccUL} },
+ { &fnv_test_str[124], (Fnv64_t) {0xaebaf068UL, 0x270e4f1cUL} },
+ { &fnv_test_str[125], (Fnv64_t) {0x7446a395UL, 0x01517d49UL} },
+ { &fnv_test_str[126], (Fnv64_t) {0x89450b40UL, 0x9af5a29aUL} },
+ { &fnv_test_str[127], (Fnv64_t) {0x63ba72e8UL, 0xb502f6c0UL} },
+ { &fnv_test_str[128], (Fnv64_t) {0x498ca7dfUL, 0xacf41561UL} },
+ { &fnv_test_str[129], (Fnv64_t) {0x3a351542UL, 0x6be8c242UL} },
+ { &fnv_test_str[130], (Fnv64_t) {0xa96ce4a3UL, 0xd04f1f6dUL} },
+ { &fnv_test_str[131], (Fnv64_t) {0x282c7235UL, 0x69eb9a8fUL} },
+ { &fnv_test_str[132], (Fnv64_t) {0x8f77cfc5UL, 0x6a7e5a41UL} },
+ { &fnv_test_str[133], (Fnv64_t) {0xdc2ecba0UL, 0xbcaf568dUL} },
+ { &fnv_test_str[134], (Fnv64_t) {0xc38f8b1fUL, 0xb03b5cc4UL} },
+ { &fnv_test_str[135], (Fnv64_t) {0x432db828UL, 0xf89a9f51UL} },
+ { &fnv_test_str[136], (Fnv64_t) {0xe6103429UL, 0x549e856bUL} },
+ { &fnv_test_str[137], (Fnv64_t) {0x4d29377aUL, 0x3cf50d22UL} },
+ { &fnv_test_str[138], (Fnv64_t) {0x18c10c37UL, 0xdb762df4UL} },
+ { &fnv_test_str[139], (Fnv64_t) {0xb0e9a6baUL, 0xfeeb4226UL} },
+ { &fnv_test_str[140], (Fnv64_t) {0x9310c052UL, 0x7004a4cdUL} },
+ { &fnv_test_str[141], (Fnv64_t) {0xf5329276UL, 0xd1c727d7UL} },
+ { &fnv_test_str[142], (Fnv64_t) {0x596ce908UL, 0xbe313796UL} },
+ { &fnv_test_str[143], (Fnv64_t) {0xe090fcc5UL, 0x768f67edUL} },
+ { &fnv_test_str[144], (Fnv64_t) {0x9db9bfc3UL, 0xa81563ccUL} },
+ { &fnv_test_str[145], (Fnv64_t) {0xc55197a8UL, 0x47194043UL} },
+ { &fnv_test_str[146], (Fnv64_t) {0x4aebab02UL, 0xc99d8186UL} },
+ { &fnv_test_str[147], (Fnv64_t) {0x235ea4a2UL, 0xcc1f161bUL} },
+ { &fnv_test_str[148], (Fnv64_t) {0x20ecd434UL, 0xaadab0c4UL} },
+ { &fnv_test_str[149], (Fnv64_t) {0x6f44d740UL, 0x6b3c034dUL} },
+ { &fnv_test_str[150], (Fnv64_t) {0x0602cbc6UL, 0x73a45e85UL} },
+ { &fnv_test_str[151], (Fnv64_t) {0xf0cd227bUL, 0x72360f04UL} },
+ { &fnv_test_str[152], (Fnv64_t) {0x384a778fUL, 0xa9ca80beUL} },
+ { &fnv_test_str[153], (Fnv64_t) {0x906889e3UL, 0xd4085e66UL} },
+ { &fnv_test_str[154], (Fnv64_t) {0x48efdbc8UL, 0x93aa8b27UL} },
+ { &fnv_test_str[155], (Fnv64_t) {0x407436a2UL, 0x6f8cd678UL} },
+ { &fnv_test_str[156], (Fnv64_t) {0xdc8be4c7UL, 0xf39a43d4UL} },
+ { &fnv_test_str[157], (Fnv64_t) {0x1125d245UL, 0xd7f5cec9UL} },
+ { &fnv_test_str[158], (Fnv64_t) {0xbe18adc4UL, 0x691d7b73UL} },
+ { &fnv_test_str[159], (Fnv64_t) {0xcaf6b691UL, 0xf4361e01UL} },
+ { &fnv_test_str[160], (Fnv64_t) {0xf64be089UL, 0xde7d8264UL} },
+ { &fnv_test_str[161], (Fnv64_t) {0x5545c06fUL, 0xa34ff43eUL} },
+ { &fnv_test_str[162], (Fnv64_t) {0x908a2bdeUL, 0x181f0b8eUL} },
+ { &fnv_test_str[163], (Fnv64_t) {0x8ddbc071UL, 0x28a965b7UL} },
+ { &fnv_test_str[164], (Fnv64_t) {0xe3cc6ae5UL, 0xead9cea0UL} },
+ { &fnv_test_str[165], (Fnv64_t) {0x3b43ebbaUL, 0x0b674315UL} },
+ { &fnv_test_str[166], (Fnv64_t) {0x2c74528dUL, 0xa7aa3f01UL} },
+ { &fnv_test_str[167], (Fnv64_t) {0xf9dffeb7UL, 0x2d5d8ad7UL} },
+ { &fnv_test_str[168], (Fnv64_t) {0xe19624eaUL, 0x00750fb6UL} },
+ { &fnv_test_str[169], (Fnv64_t) {0xe6c76c82UL, 0x01c125a4UL} },
+ { &fnv_test_str[170], (Fnv64_t) {0xc0722f1fUL, 0x3fde3afaUL} },
+ { &fnv_test_str[171], (Fnv64_t) {0xabaa379dUL, 0xd7c3eaf4UL} },
+ { &fnv_test_str[172], (Fnv64_t) {0x923c9f3fUL, 0xd2217e1cUL} },
+ { &fnv_test_str[173], (Fnv64_t) {0xb725caf6UL, 0x82d0a2e3UL} },
+ { &fnv_test_str[174], (Fnv64_t) {0xeeb72e4fUL, 0x0a10bee8UL} },
+ { &fnv_test_str[175], (Fnv64_t) {0x3e72c6fdUL, 0xc530e872UL} },
+ { &fnv_test_str[176], (Fnv64_t) {0x2e7bad99UL, 0xd8d34dcdUL} },
+ { &fnv_test_str[177], (Fnv64_t) {0xe9a2baf3UL, 0xecf77466UL} },
+ { &fnv_test_str[178], (Fnv64_t) {0x043b9666UL, 0xde3d2ddbUL} },
+ { &fnv_test_str[179], (Fnv64_t) {0x1a8157d8UL, 0xd1cc824eUL} },
+ { &fnv_test_str[180], (Fnv64_t) {0xbc90512eUL, 0x7d5c68ecUL} },
+ { &fnv_test_str[181], (Fnv64_t) {0x1d7c76d8UL, 0x2f7c691bUL} },
+ { &fnv_test_str[182], (Fnv64_t) {0xd3a46bc8UL, 0x5d88c2baUL} },
+ { &fnv_test_str[183], (Fnv64_t) {0x276647a0UL, 0xdf107320UL} },
+ { &fnv_test_str[184], (Fnv64_t) {0x7e70e9bcUL, 0x0f78f22eUL} },
+ { &fnv_test_str[185], (Fnv64_t) {0x80f67d04UL, 0x8c67be5cUL} },
+ { &fnv_test_str[186], (Fnv64_t) {0x4d019194UL, 0x07c1adfaUL} },
+ { &fnv_test_str[187], (Fnv64_t) {0x0c5b1af4UL, 0xce131242UL} },
+ { &fnv_test_str[188], (Fnv64_t) {0xdc53ab24UL, 0x043a41b2UL} },
+ { &fnv_test_str[189], (Fnv64_t) {0xf7340860UL, 0x0b038eebUL} },
+ { &fnv_test_str[190], (Fnv64_t) {0x53fb69b0UL, 0x1bcd8373UL} },
+ { &fnv_test_str[191], (Fnv64_t) {0x59eff180UL, 0x46f992fcUL} },
+ { &fnv_test_str[192], (Fnv64_t) {0x29ae79c0UL, 0x497678eeUL} },
+ { &fnv_test_str[193], (Fnv64_t) {0x0ddd4450UL, 0xb10a6228UL} },
+ { &fnv_test_str[194], (Fnv64_t) {0xb4d68140UL, 0x35eb228dUL} },
+ { &fnv_test_str[195], (Fnv64_t) {0xd9470870UL, 0x8b350e86UL} },
+ { &fnv_test_str[196], (Fnv64_t) {0x812e9540UL, 0x4e1fbdb2UL} },
+ { &fnv_test_str[197], (Fnv64_t) {0xf69a0600UL, 0x051e080dUL} },
+ { &fnv_test_str[198], (Fnv64_t) {0x54dadb40UL, 0x45e1e8aeUL} },
+ { &fnv_test_str[199], (Fnv64_t) {0x00000000UL, 0x00000000UL} },
+ { &fnv_test_str[200], (Fnv64_t) {0x90557064UL, 0xcd738062UL} },
+ { &fnv_test_str[201], (Fnv64_t) {0xbe0317c8UL, 0x2613a37bUL} },
+ { &fnv_test_str[202], (Fnv64_t) {0xcf2ae5e4UL, 0x1480e21fUL} },
+ { NULL, (Fnv64_t) {0,0} }
+};
+#endif /* HAVE_64BIT_LONG_LONG */
+
+/* FNV-1 64 bit test vectors */
+#if defined(HAVE_64BIT_LONG_LONG)
+struct fnv1_64_test_vector fnv1_64_vector[] = {
+ { &fnv_test_str[0], (Fnv64_t) 0xcbf29ce484222325ULL },
+ { &fnv_test_str[1], (Fnv64_t) 0xaf63bd4c8601b7beULL },
+ { &fnv_test_str[2], (Fnv64_t) 0xaf63bd4c8601b7bdULL },
+ { &fnv_test_str[3], (Fnv64_t) 0xaf63bd4c8601b7bcULL },
+ { &fnv_test_str[4], (Fnv64_t) 0xaf63bd4c8601b7bbULL },
+ { &fnv_test_str[5], (Fnv64_t) 0xaf63bd4c8601b7baULL },
+ { &fnv_test_str[6], (Fnv64_t) 0xaf63bd4c8601b7b9ULL },
+ { &fnv_test_str[7], (Fnv64_t) 0x08326207b4eb2f34ULL },
+ { &fnv_test_str[8], (Fnv64_t) 0xd8cbc7186ba13533ULL },
+ { &fnv_test_str[9], (Fnv64_t) 0x0378817ee2ed65cbULL },
+ { &fnv_test_str[10], (Fnv64_t) 0xd329d59b9963f790ULL },
+ { &fnv_test_str[11], (Fnv64_t) 0x340d8765a4dda9c2ULL },
+ { &fnv_test_str[12], (Fnv64_t) 0xaf63bd4c8601b7dfULL },
+ { &fnv_test_str[13], (Fnv64_t) 0x08326707b4eb37daULL },
+ { &fnv_test_str[14], (Fnv64_t) 0x08326607b4eb3627ULL },
+ { &fnv_test_str[15], (Fnv64_t) 0x08326507b4eb3474ULL },
+ { &fnv_test_str[16], (Fnv64_t) 0x08326407b4eb32c1ULL },
+ { &fnv_test_str[17], (Fnv64_t) 0x08326307b4eb310eULL },
+ { &fnv_test_str[18], (Fnv64_t) 0x08326207b4eb2f5bULL },
+ { &fnv_test_str[19], (Fnv64_t) 0xd8cbc7186ba1355cULL },
+ { &fnv_test_str[20], (Fnv64_t) 0x0378817ee2ed65a9ULL },
+ { &fnv_test_str[21], (Fnv64_t) 0xd329d59b9963f7f1ULL },
+ { &fnv_test_str[22], (Fnv64_t) 0x340d8765a4dda9b0ULL },
+ { &fnv_test_str[23], (Fnv64_t) 0x50a6d3b724a774a6ULL },
+ { &fnv_test_str[24], (Fnv64_t) 0x08326507b4eb341cULL },
+ { &fnv_test_str[25], (Fnv64_t) 0xd8d5c8186ba98bfbULL },
+ { &fnv_test_str[26], (Fnv64_t) 0x1ccefc7ef118dbefULL },
+ { &fnv_test_str[27], (Fnv64_t) 0x0c92fab3ad3db77aULL },
+ { &fnv_test_str[28], (Fnv64_t) 0x9b77794f5fdec421ULL },
+ { &fnv_test_str[29], (Fnv64_t) 0x0ac742dfe7874433ULL },
+ { &fnv_test_str[30], (Fnv64_t) 0xd7dad5766ad8e2deULL },
+ { &fnv_test_str[31], (Fnv64_t) 0xa1bb96378e897f5bULL },
+ { &fnv_test_str[32], (Fnv64_t) 0x5b3f9b6733a367d2ULL },
+ { &fnv_test_str[33], (Fnv64_t) 0xb07ce25cbea969f6ULL },
+ { &fnv_test_str[34], (Fnv64_t) 0x8d9e9997f9df0d6aULL },
+ { &fnv_test_str[35], (Fnv64_t) 0x838c673d9603cb7bULL },
+ { &fnv_test_str[36], (Fnv64_t) 0x8b5ee8a5e872c273ULL },
+ { &fnv_test_str[37], (Fnv64_t) 0x4507c4e9fb00690cULL },
+ { &fnv_test_str[38], (Fnv64_t) 0x4c9ca59581b27f45ULL },
+ { &fnv_test_str[39], (Fnv64_t) 0xe0aca20b624e4235ULL },
+ { &fnv_test_str[40], (Fnv64_t) 0xd8d5c8186ba98b94ULL },
+ { &fnv_test_str[41], (Fnv64_t) 0x1ccefc7ef118db81ULL },
+ { &fnv_test_str[42], (Fnv64_t) 0x0c92fab3ad3db71dULL },
+ { &fnv_test_str[43], (Fnv64_t) 0x9b77794f5fdec44eULL },
+ { &fnv_test_str[44], (Fnv64_t) 0x0ac742dfe7874413ULL },
+ { &fnv_test_str[45], (Fnv64_t) 0xd7dad5766ad8e2a9ULL },
+ { &fnv_test_str[46], (Fnv64_t) 0xa1bb96378e897f3aULL },
+ { &fnv_test_str[47], (Fnv64_t) 0x5b3f9b6733a367a1ULL },
+ { &fnv_test_str[48], (Fnv64_t) 0xb07ce25cbea969d6ULL },
+ { &fnv_test_str[49], (Fnv64_t) 0x8d9e9997f9df0d02ULL },
+ { &fnv_test_str[50], (Fnv64_t) 0x838c673d9603cb1eULL },
+ { &fnv_test_str[51], (Fnv64_t) 0x8b5ee8a5e872c201ULL },
+ { &fnv_test_str[52], (Fnv64_t) 0x4507c4e9fb006969ULL },
+ { &fnv_test_str[53], (Fnv64_t) 0x4c9ca59581b27f64ULL },
+ { &fnv_test_str[54], (Fnv64_t) 0xe0aca20b624e423fULL },
+ { &fnv_test_str[55], (Fnv64_t) 0x13998e580afa800fULL },
+ { &fnv_test_str[56], (Fnv64_t) 0x08326507b4eb3401ULL },
+ { &fnv_test_str[57], (Fnv64_t) 0xd8d5ad186ba95dc1ULL },
+ { &fnv_test_str[58], (Fnv64_t) 0x1c72e17ef0ca4e97ULL },
+ { &fnv_test_str[59], (Fnv64_t) 0x2183c1b327c38ae6ULL },
+ { &fnv_test_str[60], (Fnv64_t) 0xb66d096c914504f2ULL },
+ { &fnv_test_str[61], (Fnv64_t) 0x404bf57ad8476757ULL },
+ { &fnv_test_str[62], (Fnv64_t) 0x887976bd815498bbULL },
+ { &fnv_test_str[63], (Fnv64_t) 0x3afd7f02c2bf85a5ULL },
+ { &fnv_test_str[64], (Fnv64_t) 0xfc4476b0eb70177fULL },
+ { &fnv_test_str[65], (Fnv64_t) 0x186d2da00f77ecbaULL },
+ { &fnv_test_str[66], (Fnv64_t) 0xf97140fa48c74066ULL },
+ { &fnv_test_str[67], (Fnv64_t) 0xa2b1cf49aa926d37ULL },
+ { &fnv_test_str[68], (Fnv64_t) 0x0690712cd6cf940cULL },
+ { &fnv_test_str[69], (Fnv64_t) 0xf7045b3102b8906eULL },
+ { &fnv_test_str[70], (Fnv64_t) 0xd8d5ad186ba95db3ULL },
+ { &fnv_test_str[71], (Fnv64_t) 0x1c72e17ef0ca4ef3ULL },
+ { &fnv_test_str[72], (Fnv64_t) 0x2183c1b327c38a95ULL },
+ { &fnv_test_str[73], (Fnv64_t) 0xb66d096c914504d2ULL },
+ { &fnv_test_str[74], (Fnv64_t) 0x404bf57ad8476736ULL },
+ { &fnv_test_str[75], (Fnv64_t) 0x887976bd815498d5ULL },
+ { &fnv_test_str[76], (Fnv64_t) 0x3afd7f02c2bf85c1ULL },
+ { &fnv_test_str[77], (Fnv64_t) 0xfc4476b0eb70175fULL },
+ { &fnv_test_str[78], (Fnv64_t) 0x186d2da00f77eccdULL },
+ { &fnv_test_str[79], (Fnv64_t) 0xf97140fa48c7400eULL },
+ { &fnv_test_str[80], (Fnv64_t) 0xa2b1cf49aa926d52ULL },
+ { &fnv_test_str[81], (Fnv64_t) 0x0690712cd6cf9475ULL },
+ { &fnv_test_str[82], (Fnv64_t) 0xf7045b3102b89064ULL },
+ { &fnv_test_str[83], (Fnv64_t) 0x74f762479f9d6aeaULL },
+ { &fnv_test_str[84], (Fnv64_t) 0x08326007b4eb2b9cULL },
+ { &fnv_test_str[85], (Fnv64_t) 0xd8c4c9186b9b1a14ULL },
+ { &fnv_test_str[86], (Fnv64_t) 0x7b495389bdbdd4c7ULL },
+ { &fnv_test_str[87], (Fnv64_t) 0x3b6dba0d69908e25ULL },
+ { &fnv_test_str[88], (Fnv64_t) 0xd6b2b17bf4b71261ULL },
+ { &fnv_test_str[89], (Fnv64_t) 0x447bfb7f98e615b5ULL },
+ { &fnv_test_str[90], (Fnv64_t) 0xd6b2b17bf4b71262ULL },
+ { &fnv_test_str[91], (Fnv64_t) 0x3bd2807f93fe1660ULL },
+ { &fnv_test_str[92], (Fnv64_t) 0xd6b2b17bf4b71263ULL },
+ { &fnv_test_str[93], (Fnv64_t) 0x3329057f8f16170bULL },
+ { &fnv_test_str[94], (Fnv64_t) 0xd6b2b17bf4b71264ULL },
+ { &fnv_test_str[95], (Fnv64_t) 0x2a7f8a7f8a2e19b6ULL },
+ { &fnv_test_str[96], (Fnv64_t) 0x23d3767e64b2f98aULL },
+ { &fnv_test_str[97], (Fnv64_t) 0xff768d7e4f9d86a4ULL },
+ { &fnv_test_str[98], (Fnv64_t) 0x23d3767e64b2f984ULL },
+ { &fnv_test_str[99], (Fnv64_t) 0xccd1837e334e4aa6ULL },
+ { &fnv_test_str[100], (Fnv64_t) 0x23d3767e64b2f99aULL },
+ { &fnv_test_str[101], (Fnv64_t) 0x7691fd7e028f6754ULL },
+ { &fnv_test_str[102], (Fnv64_t) 0x34ad3b1041204318ULL },
+ { &fnv_test_str[103], (Fnv64_t) 0xa29e749ea9d201c8ULL },
+ { &fnv_test_str[104], (Fnv64_t) 0x34ad3b104120431bULL },
+ { &fnv_test_str[105], (Fnv64_t) 0xa29e779ea9d206e1ULL },
+ { &fnv_test_str[106], (Fnv64_t) 0x34ad3b104120431aULL },
+ { &fnv_test_str[107], (Fnv64_t) 0xa29e769ea9d2052eULL },
+ { &fnv_test_str[108], (Fnv64_t) 0x02a17ebca4aa3497ULL },
+ { &fnv_test_str[109], (Fnv64_t) 0x229ef18bcd375c95ULL },
+ { &fnv_test_str[110], (Fnv64_t) 0x02a17dbca4aa32c8ULL },
+ { &fnv_test_str[111], (Fnv64_t) 0x229b6f8bcd3449d8ULL },
+ { &fnv_test_str[112], (Fnv64_t) 0x02a184bca4aa3ed5ULL },
+ { &fnv_test_str[113], (Fnv64_t) 0x22b3618bcd48c3efULL },
+ { &fnv_test_str[114], (Fnv64_t) 0x5c2c346706186f36ULL },
+ { &fnv_test_str[115], (Fnv64_t) 0xb78c410f5b84f8c2ULL },
+ { &fnv_test_str[116], (Fnv64_t) 0xed9478212b267395ULL },
+ { &fnv_test_str[117], (Fnv64_t) 0xd9bbb55c5256662fULL },
+ { &fnv_test_str[118], (Fnv64_t) 0x8c54f0203249438aULL },
+ { &fnv_test_str[119], (Fnv64_t) 0xbd9790b5727dc37eULL },
+ { &fnv_test_str[120], (Fnv64_t) 0xa64e5f36c9e2b0e3ULL },
+ { &fnv_test_str[121], (Fnv64_t) 0x8fd0680da3088a04ULL },
+ { &fnv_test_str[122], (Fnv64_t) 0x67aad32c078284ccULL },
+ { &fnv_test_str[123], (Fnv64_t) 0xb37d55d81c57b331ULL },
+ { &fnv_test_str[124], (Fnv64_t) 0x55ac0f3829057c43ULL },
+ { &fnv_test_str[125], (Fnv64_t) 0xcb27f4b8e1b6cc20ULL },
+ { &fnv_test_str[126], (Fnv64_t) 0x26caf88bcbef2d19ULL },
+ { &fnv_test_str[127], (Fnv64_t) 0x8e6e063b97e61b8fULL },
+ { &fnv_test_str[128], (Fnv64_t) 0xb42750f7f3b7c37eULL },
+ { &fnv_test_str[129], (Fnv64_t) 0xf3c6ba64cf7ca99bULL },
+ { &fnv_test_str[130], (Fnv64_t) 0xebfb69b427ea80feULL },
+ { &fnv_test_str[131], (Fnv64_t) 0x39b50c3ed970f46cULL },
+ { &fnv_test_str[132], (Fnv64_t) 0x5b9b177aa3eb3e8aULL },
+ { &fnv_test_str[133], (Fnv64_t) 0x6510063ecf4ec903ULL },
+ { &fnv_test_str[134], (Fnv64_t) 0x2b3bbd2c00797c7aULL },
+ { &fnv_test_str[135], (Fnv64_t) 0xf1d6204ff5cb4aa7ULL },
+ { &fnv_test_str[136], (Fnv64_t) 0x4836e27ccf099f38ULL },
+ { &fnv_test_str[137], (Fnv64_t) 0x82efbb0dd073b44dULL },
+ { &fnv_test_str[138], (Fnv64_t) 0x4a80c282ffd7d4c6ULL },
+ { &fnv_test_str[139], (Fnv64_t) 0x305d1a9c9ee43bdfULL },
+ { &fnv_test_str[140], (Fnv64_t) 0x15c366948ffc6997ULL },
+ { &fnv_test_str[141], (Fnv64_t) 0x80153ae218916e7bULL },
+ { &fnv_test_str[142], (Fnv64_t) 0xfa23e2bdf9e2a9e1ULL },
+ { &fnv_test_str[143], (Fnv64_t) 0xd47e8d8a2333c6deULL },
+ { &fnv_test_str[144], (Fnv64_t) 0x7e128095f688b056ULL },
+ { &fnv_test_str[145], (Fnv64_t) 0x2f5356890efcedabULL },
+ { &fnv_test_str[146], (Fnv64_t) 0x95c2b383014f55c5ULL },
+ { &fnv_test_str[147], (Fnv64_t) 0x4727a5339ce6070fULL },
+ { &fnv_test_str[148], (Fnv64_t) 0xb0555ecd575108e9ULL },
+ { &fnv_test_str[149], (Fnv64_t) 0x48d785770bb4af37ULL },
+ { &fnv_test_str[150], (Fnv64_t) 0x09d4701c12af02b1ULL },
+ { &fnv_test_str[151], (Fnv64_t) 0x79f031e78f3cf62eULL },
+ { &fnv_test_str[152], (Fnv64_t) 0x52a1ee85db1b5a94ULL },
+ { &fnv_test_str[153], (Fnv64_t) 0x6bd95b2eb37fa6b8ULL },
+ { &fnv_test_str[154], (Fnv64_t) 0x74971b7077aef85dULL },
+ { &fnv_test_str[155], (Fnv64_t) 0xb4e4fae2ffcc1aadULL },
+ { &fnv_test_str[156], (Fnv64_t) 0x2bd48bd898b8f63aULL },
+ { &fnv_test_str[157], (Fnv64_t) 0xe9966ac1556257f6ULL },
+ { &fnv_test_str[158], (Fnv64_t) 0x92a3d1cd078ba293ULL },
+ { &fnv_test_str[159], (Fnv64_t) 0xf81175a482e20ab8ULL },
+ { &fnv_test_str[160], (Fnv64_t) 0x5bbb3de722e73048ULL },
+ { &fnv_test_str[161], (Fnv64_t) 0x6b4f363492b9f2beULL },
+ { &fnv_test_str[162], (Fnv64_t) 0xc2d559df73d59875ULL },
+ { &fnv_test_str[163], (Fnv64_t) 0xf75f62284bc7a8c2ULL },
+ { &fnv_test_str[164], (Fnv64_t) 0xda8dd8e116a9f1ccULL },
+ { &fnv_test_str[165], (Fnv64_t) 0xbdc1e6ab76057885ULL },
+ { &fnv_test_str[166], (Fnv64_t) 0xfec6a4238a1224a0ULL },
+ { &fnv_test_str[167], (Fnv64_t) 0xc03f40f3223e290eULL },
+ { &fnv_test_str[168], (Fnv64_t) 0x1ed21673466ffda9ULL },
+ { &fnv_test_str[169], (Fnv64_t) 0xdf70f906bb0dd2afULL },
+ { &fnv_test_str[170], (Fnv64_t) 0xf3dcda369f2af666ULL },
+ { &fnv_test_str[171], (Fnv64_t) 0x9ebb11573cdcebdeULL },
+ { &fnv_test_str[172], (Fnv64_t) 0x81c72d9077fedca0ULL },
+ { &fnv_test_str[173], (Fnv64_t) 0x0ec074a31be5fb15ULL },
+ { &fnv_test_str[174], (Fnv64_t) 0x2a8b3280b6c48f20ULL },
+ { &fnv_test_str[175], (Fnv64_t) 0xfd31777513309344ULL },
+ { &fnv_test_str[176], (Fnv64_t) 0x194534a86ad006b6ULL },
+ { &fnv_test_str[177], (Fnv64_t) 0x3be6fdf46e0cfe12ULL },
+ { &fnv_test_str[178], (Fnv64_t) 0x017cc137a07eb057ULL },
+ { &fnv_test_str[179], (Fnv64_t) 0x9428fc6e7d26b54dULL },
+ { &fnv_test_str[180], (Fnv64_t) 0x9aaa2e3603ef8ad7ULL },
+ { &fnv_test_str[181], (Fnv64_t) 0x82c6d3f3a0ccdf7dULL },
+ { &fnv_test_str[182], (Fnv64_t) 0xc86eeea00cf09b65ULL },
+ { &fnv_test_str[183], (Fnv64_t) 0x705f8189dbb58299ULL },
+ { &fnv_test_str[184], (Fnv64_t) 0x415a7f554391ca69ULL },
+ { &fnv_test_str[185], (Fnv64_t) 0xcfe3d49fa2bdc555ULL },
+ { &fnv_test_str[186], (Fnv64_t) 0xf0f9c56039b25191ULL },
+ { &fnv_test_str[187], (Fnv64_t) 0x7075cb6abd1d32d9ULL },
+ { &fnv_test_str[188], (Fnv64_t) 0x43c94e2c8b277509ULL },
+ { &fnv_test_str[189], (Fnv64_t) 0x3cbfd4e4ea670359ULL },
+ { &fnv_test_str[190], (Fnv64_t) 0xc05887810f4d019dULL },
+ { &fnv_test_str[191], (Fnv64_t) 0x14468ff93ac22dc5ULL },
+ { &fnv_test_str[192], (Fnv64_t) 0xebed699589d99c05ULL },
+ { &fnv_test_str[193], (Fnv64_t) 0x6d99f6df321ca5d5ULL },
+ { &fnv_test_str[194], (Fnv64_t) 0x0cd410d08c36d625ULL },
+ { &fnv_test_str[195], (Fnv64_t) 0xef1b2a2c86831d35ULL },
+ { &fnv_test_str[196], (Fnv64_t) 0x3b349c4d69ee5f05ULL },
+ { &fnv_test_str[197], (Fnv64_t) 0x55248ce88f45f035ULL },
+ { &fnv_test_str[198], (Fnv64_t) 0xaa69ca6a18a4c885ULL },
+ { &fnv_test_str[199], (Fnv64_t) 0x1fe3fce62bd816b5ULL },
+ { &fnv_test_str[200], (Fnv64_t) 0x0289a488a8df69d9ULL },
+ { &fnv_test_str[201], (Fnv64_t) 0x15e96e1613df98b5ULL },
+ { &fnv_test_str[202], (Fnv64_t) 0xe6be57375ad89b99ULL },
+ { NULL, (Fnv64_t) 0 }
+};
+#else /* HAVE_64BIT_LONG_LONG */
+struct fnv1_64_test_vector fnv1_64_vector[] = {
+ { &fnv_test_str[0], (Fnv64_t) {0x84222325UL, 0xcbf29ce4UL} },
+ { &fnv_test_str[1], (Fnv64_t) {0x8601b7beUL, 0xaf63bd4cUL} },
+ { &fnv_test_str[2], (Fnv64_t) {0x8601b7bdUL, 0xaf63bd4cUL} },
+ { &fnv_test_str[3], (Fnv64_t) {0x8601b7bcUL, 0xaf63bd4cUL} },
+ { &fnv_test_str[4], (Fnv64_t) {0x8601b7bbUL, 0xaf63bd4cUL} },
+ { &fnv_test_str[5], (Fnv64_t) {0x8601b7baUL, 0xaf63bd4cUL} },
+ { &fnv_test_str[6], (Fnv64_t) {0x8601b7b9UL, 0xaf63bd4cUL} },
+ { &fnv_test_str[7], (Fnv64_t) {0xb4eb2f34UL, 0x08326207UL} },
+ { &fnv_test_str[8], (Fnv64_t) {0x6ba13533UL, 0xd8cbc718UL} },
+ { &fnv_test_str[9], (Fnv64_t) {0xe2ed65cbUL, 0x0378817eUL} },
+ { &fnv_test_str[10], (Fnv64_t) {0x9963f790UL, 0xd329d59bUL} },
+ { &fnv_test_str[11], (Fnv64_t) {0xa4dda9c2UL, 0x340d8765UL} },
+ { &fnv_test_str[12], (Fnv64_t) {0x8601b7dfUL, 0xaf63bd4cUL} },
+ { &fnv_test_str[13], (Fnv64_t) {0xb4eb37daUL, 0x08326707UL} },
+ { &fnv_test_str[14], (Fnv64_t) {0xb4eb3627UL, 0x08326607UL} },
+ { &fnv_test_str[15], (Fnv64_t) {0xb4eb3474UL, 0x08326507UL} },
+ { &fnv_test_str[16], (Fnv64_t) {0xb4eb32c1UL, 0x08326407UL} },
+ { &fnv_test_str[17], (Fnv64_t) {0xb4eb310eUL, 0x08326307UL} },
+ { &fnv_test_str[18], (Fnv64_t) {0xb4eb2f5bUL, 0x08326207UL} },
+ { &fnv_test_str[19], (Fnv64_t) {0x6ba1355cUL, 0xd8cbc718UL} },
+ { &fnv_test_str[20], (Fnv64_t) {0xe2ed65a9UL, 0x0378817eUL} },
+ { &fnv_test_str[21], (Fnv64_t) {0x9963f7f1UL, 0xd329d59bUL} },
+ { &fnv_test_str[22], (Fnv64_t) {0xa4dda9b0UL, 0x340d8765UL} },
+ { &fnv_test_str[23], (Fnv64_t) {0x24a774a6UL, 0x50a6d3b7UL} },
+ { &fnv_test_str[24], (Fnv64_t) {0xb4eb341cUL, 0x08326507UL} },
+ { &fnv_test_str[25], (Fnv64_t) {0x6ba98bfbUL, 0xd8d5c818UL} },
+ { &fnv_test_str[26], (Fnv64_t) {0xf118dbefUL, 0x1ccefc7eUL} },
+ { &fnv_test_str[27], (Fnv64_t) {0xad3db77aUL, 0x0c92fab3UL} },
+ { &fnv_test_str[28], (Fnv64_t) {0x5fdec421UL, 0x9b77794fUL} },
+ { &fnv_test_str[29], (Fnv64_t) {0xe7874433UL, 0x0ac742dfUL} },
+ { &fnv_test_str[30], (Fnv64_t) {0x6ad8e2deUL, 0xd7dad576UL} },
+ { &fnv_test_str[31], (Fnv64_t) {0x8e897f5bUL, 0xa1bb9637UL} },
+ { &fnv_test_str[32], (Fnv64_t) {0x33a367d2UL, 0x5b3f9b67UL} },
+ { &fnv_test_str[33], (Fnv64_t) {0xbea969f6UL, 0xb07ce25cUL} },
+ { &fnv_test_str[34], (Fnv64_t) {0xf9df0d6aUL, 0x8d9e9997UL} },
+ { &fnv_test_str[35], (Fnv64_t) {0x9603cb7bUL, 0x838c673dUL} },
+ { &fnv_test_str[36], (Fnv64_t) {0xe872c273UL, 0x8b5ee8a5UL} },
+ { &fnv_test_str[37], (Fnv64_t) {0xfb00690cUL, 0x4507c4e9UL} },
+ { &fnv_test_str[38], (Fnv64_t) {0x81b27f45UL, 0x4c9ca595UL} },
+ { &fnv_test_str[39], (Fnv64_t) {0x624e4235UL, 0xe0aca20bUL} },
+ { &fnv_test_str[40], (Fnv64_t) {0x6ba98b94UL, 0xd8d5c818UL} },
+ { &fnv_test_str[41], (Fnv64_t) {0xf118db81UL, 0x1ccefc7eUL} },
+ { &fnv_test_str[42], (Fnv64_t) {0xad3db71dUL, 0x0c92fab3UL} },
+ { &fnv_test_str[43], (Fnv64_t) {0x5fdec44eUL, 0x9b77794fUL} },
+ { &fnv_test_str[44], (Fnv64_t) {0xe7874413UL, 0x0ac742dfUL} },
+ { &fnv_test_str[45], (Fnv64_t) {0x6ad8e2a9UL, 0xd7dad576UL} },
+ { &fnv_test_str[46], (Fnv64_t) {0x8e897f3aUL, 0xa1bb9637UL} },
+ { &fnv_test_str[47], (Fnv64_t) {0x33a367a1UL, 0x5b3f9b67UL} },
+ { &fnv_test_str[48], (Fnv64_t) {0xbea969d6UL, 0xb07ce25cUL} },
+ { &fnv_test_str[49], (Fnv64_t) {0xf9df0d02UL, 0x8d9e9997UL} },
+ { &fnv_test_str[50], (Fnv64_t) {0x9603cb1eUL, 0x838c673dUL} },
+ { &fnv_test_str[51], (Fnv64_t) {0xe872c201UL, 0x8b5ee8a5UL} },
+ { &fnv_test_str[52], (Fnv64_t) {0xfb006969UL, 0x4507c4e9UL} },
+ { &fnv_test_str[53], (Fnv64_t) {0x81b27f64UL, 0x4c9ca595UL} },
+ { &fnv_test_str[54], (Fnv64_t) {0x624e423fUL, 0xe0aca20bUL} },
+ { &fnv_test_str[55], (Fnv64_t) {0x0afa800fUL, 0x13998e58UL} },
+ { &fnv_test_str[56], (Fnv64_t) {0xb4eb3401UL, 0x08326507UL} },
+ { &fnv_test_str[57], (Fnv64_t) {0x6ba95dc1UL, 0xd8d5ad18UL} },
+ { &fnv_test_str[58], (Fnv64_t) {0xf0ca4e97UL, 0x1c72e17eUL} },
+ { &fnv_test_str[59], (Fnv64_t) {0x27c38ae6UL, 0x2183c1b3UL} },
+ { &fnv_test_str[60], (Fnv64_t) {0x914504f2UL, 0xb66d096cUL} },
+ { &fnv_test_str[61], (Fnv64_t) {0xd8476757UL, 0x404bf57aUL} },
+ { &fnv_test_str[62], (Fnv64_t) {0x815498bbUL, 0x887976bdUL} },
+ { &fnv_test_str[63], (Fnv64_t) {0xc2bf85a5UL, 0x3afd7f02UL} },
+ { &fnv_test_str[64], (Fnv64_t) {0xeb70177fUL, 0xfc4476b0UL} },
+ { &fnv_test_str[65], (Fnv64_t) {0x0f77ecbaUL, 0x186d2da0UL} },
+ { &fnv_test_str[66], (Fnv64_t) {0x48c74066UL, 0xf97140faUL} },
+ { &fnv_test_str[67], (Fnv64_t) {0xaa926d37UL, 0xa2b1cf49UL} },
+ { &fnv_test_str[68], (Fnv64_t) {0xd6cf940cUL, 0x0690712cUL} },
+ { &fnv_test_str[69], (Fnv64_t) {0x02b8906eUL, 0xf7045b31UL} },
+ { &fnv_test_str[70], (Fnv64_t) {0x6ba95db3UL, 0xd8d5ad18UL} },
+ { &fnv_test_str[71], (Fnv64_t) {0xf0ca4ef3UL, 0x1c72e17eUL} },
+ { &fnv_test_str[72], (Fnv64_t) {0x27c38a95UL, 0x2183c1b3UL} },
+ { &fnv_test_str[73], (Fnv64_t) {0x914504d2UL, 0xb66d096cUL} },
+ { &fnv_test_str[74], (Fnv64_t) {0xd8476736UL, 0x404bf57aUL} },
+ { &fnv_test_str[75], (Fnv64_t) {0x815498d5UL, 0x887976bdUL} },
+ { &fnv_test_str[76], (Fnv64_t) {0xc2bf85c1UL, 0x3afd7f02UL} },
+ { &fnv_test_str[77], (Fnv64_t) {0xeb70175fUL, 0xfc4476b0UL} },
+ { &fnv_test_str[78], (Fnv64_t) {0x0f77eccdUL, 0x186d2da0UL} },
+ { &fnv_test_str[79], (Fnv64_t) {0x48c7400eUL, 0xf97140faUL} },
+ { &fnv_test_str[80], (Fnv64_t) {0xaa926d52UL, 0xa2b1cf49UL} },
+ { &fnv_test_str[81], (Fnv64_t) {0xd6cf9475UL, 0x0690712cUL} },
+ { &fnv_test_str[82], (Fnv64_t) {0x02b89064UL, 0xf7045b31UL} },
+ { &fnv_test_str[83], (Fnv64_t) {0x9f9d6aeaUL, 0x74f76247UL} },
+ { &fnv_test_str[84], (Fnv64_t) {0xb4eb2b9cUL, 0x08326007UL} },
+ { &fnv_test_str[85], (Fnv64_t) {0x6b9b1a14UL, 0xd8c4c918UL} },
+ { &fnv_test_str[86], (Fnv64_t) {0xbdbdd4c7UL, 0x7b495389UL} },
+ { &fnv_test_str[87], (Fnv64_t) {0x69908e25UL, 0x3b6dba0dUL} },
+ { &fnv_test_str[88], (Fnv64_t) {0xf4b71261UL, 0xd6b2b17bUL} },
+ { &fnv_test_str[89], (Fnv64_t) {0x98e615b5UL, 0x447bfb7fUL} },
+ { &fnv_test_str[90], (Fnv64_t) {0xf4b71262UL, 0xd6b2b17bUL} },
+ { &fnv_test_str[91], (Fnv64_t) {0x93fe1660UL, 0x3bd2807fUL} },
+ { &fnv_test_str[92], (Fnv64_t) {0xf4b71263UL, 0xd6b2b17bUL} },
+ { &fnv_test_str[93], (Fnv64_t) {0x8f16170bUL, 0x3329057fUL} },
+ { &fnv_test_str[94], (Fnv64_t) {0xf4b71264UL, 0xd6b2b17bUL} },
+ { &fnv_test_str[95], (Fnv64_t) {0x8a2e19b6UL, 0x2a7f8a7fUL} },
+ { &fnv_test_str[96], (Fnv64_t) {0x64b2f98aUL, 0x23d3767eUL} },
+ { &fnv_test_str[97], (Fnv64_t) {0x4f9d86a4UL, 0xff768d7eUL} },
+ { &fnv_test_str[98], (Fnv64_t) {0x64b2f984UL, 0x23d3767eUL} },
+ { &fnv_test_str[99], (Fnv64_t) {0x334e4aa6UL, 0xccd1837eUL} },
+ { &fnv_test_str[100], (Fnv64_t) {0x64b2f99aUL, 0x23d3767eUL} },
+ { &fnv_test_str[101], (Fnv64_t) {0x028f6754UL, 0x7691fd7eUL} },
+ { &fnv_test_str[102], (Fnv64_t) {0x41204318UL, 0x34ad3b10UL} },
+ { &fnv_test_str[103], (Fnv64_t) {0xa9d201c8UL, 0xa29e749eUL} },
+ { &fnv_test_str[104], (Fnv64_t) {0x4120431bUL, 0x34ad3b10UL} },
+ { &fnv_test_str[105], (Fnv64_t) {0xa9d206e1UL, 0xa29e779eUL} },
+ { &fnv_test_str[106], (Fnv64_t) {0x4120431aUL, 0x34ad3b10UL} },
+ { &fnv_test_str[107], (Fnv64_t) {0xa9d2052eUL, 0xa29e769eUL} },
+ { &fnv_test_str[108], (Fnv64_t) {0xa4aa3497UL, 0x02a17ebcUL} },
+ { &fnv_test_str[109], (Fnv64_t) {0xcd375c95UL, 0x229ef18bUL} },
+ { &fnv_test_str[110], (Fnv64_t) {0xa4aa32c8UL, 0x02a17dbcUL} },
+ { &fnv_test_str[111], (Fnv64_t) {0xcd3449d8UL, 0x229b6f8bUL} },
+ { &fnv_test_str[112], (Fnv64_t) {0xa4aa3ed5UL, 0x02a184bcUL} },
+ { &fnv_test_str[113], (Fnv64_t) {0xcd48c3efUL, 0x22b3618bUL} },
+ { &fnv_test_str[114], (Fnv64_t) {0x06186f36UL, 0x5c2c3467UL} },
+ { &fnv_test_str[115], (Fnv64_t) {0x5b84f8c2UL, 0xb78c410fUL} },
+ { &fnv_test_str[116], (Fnv64_t) {0x2b267395UL, 0xed947821UL} },
+ { &fnv_test_str[117], (Fnv64_t) {0x5256662fUL, 0xd9bbb55cUL} },
+ { &fnv_test_str[118], (Fnv64_t) {0x3249438aUL, 0x8c54f020UL} },
+ { &fnv_test_str[119], (Fnv64_t) {0x727dc37eUL, 0xbd9790b5UL} },
+ { &fnv_test_str[120], (Fnv64_t) {0xc9e2b0e3UL, 0xa64e5f36UL} },
+ { &fnv_test_str[121], (Fnv64_t) {0xa3088a04UL, 0x8fd0680dUL} },
+ { &fnv_test_str[122], (Fnv64_t) {0x078284ccUL, 0x67aad32cUL} },
+ { &fnv_test_str[123], (Fnv64_t) {0x1c57b331UL, 0xb37d55d8UL} },
+ { &fnv_test_str[124], (Fnv64_t) {0x29057c43UL, 0x55ac0f38UL} },
+ { &fnv_test_str[125], (Fnv64_t) {0xe1b6cc20UL, 0xcb27f4b8UL} },
+ { &fnv_test_str[126], (Fnv64_t) {0xcbef2d19UL, 0x26caf88bUL} },
+ { &fnv_test_str[127], (Fnv64_t) {0x97e61b8fUL, 0x8e6e063bUL} },
+ { &fnv_test_str[128], (Fnv64_t) {0xf3b7c37eUL, 0xb42750f7UL} },
+ { &fnv_test_str[129], (Fnv64_t) {0xcf7ca99bUL, 0xf3c6ba64UL} },
+ { &fnv_test_str[130], (Fnv64_t) {0x27ea80feUL, 0xebfb69b4UL} },
+ { &fnv_test_str[131], (Fnv64_t) {0xd970f46cUL, 0x39b50c3eUL} },
+ { &fnv_test_str[132], (Fnv64_t) {0xa3eb3e8aUL, 0x5b9b177aUL} },
+ { &fnv_test_str[133], (Fnv64_t) {0xcf4ec903UL, 0x6510063eUL} },
+ { &fnv_test_str[134], (Fnv64_t) {0x00797c7aUL, 0x2b3bbd2cUL} },
+ { &fnv_test_str[135], (Fnv64_t) {0xf5cb4aa7UL, 0xf1d6204fUL} },
+ { &fnv_test_str[136], (Fnv64_t) {0xcf099f38UL, 0x4836e27cUL} },
+ { &fnv_test_str[137], (Fnv64_t) {0xd073b44dUL, 0x82efbb0dUL} },
+ { &fnv_test_str[138], (Fnv64_t) {0xffd7d4c6UL, 0x4a80c282UL} },
+ { &fnv_test_str[139], (Fnv64_t) {0x9ee43bdfUL, 0x305d1a9cUL} },
+ { &fnv_test_str[140], (Fnv64_t) {0x8ffc6997UL, 0x15c36694UL} },
+ { &fnv_test_str[141], (Fnv64_t) {0x18916e7bUL, 0x80153ae2UL} },
+ { &fnv_test_str[142], (Fnv64_t) {0xf9e2a9e1UL, 0xfa23e2bdUL} },
+ { &fnv_test_str[143], (Fnv64_t) {0x2333c6deUL, 0xd47e8d8aUL} },
+ { &fnv_test_str[144], (Fnv64_t) {0xf688b056UL, 0x7e128095UL} },
+ { &fnv_test_str[145], (Fnv64_t) {0x0efcedabUL, 0x2f535689UL} },
+ { &fnv_test_str[146], (Fnv64_t) {0x014f55c5UL, 0x95c2b383UL} },
+ { &fnv_test_str[147], (Fnv64_t) {0x9ce6070fUL, 0x4727a533UL} },
+ { &fnv_test_str[148], (Fnv64_t) {0x575108e9UL, 0xb0555ecdUL} },
+ { &fnv_test_str[149], (Fnv64_t) {0x0bb4af37UL, 0x48d78577UL} },
+ { &fnv_test_str[150], (Fnv64_t) {0x12af02b1UL, 0x09d4701cUL} },
+ { &fnv_test_str[151], (Fnv64_t) {0x8f3cf62eUL, 0x79f031e7UL} },
+ { &fnv_test_str[152], (Fnv64_t) {0xdb1b5a94UL, 0x52a1ee85UL} },
+ { &fnv_test_str[153], (Fnv64_t) {0xb37fa6b8UL, 0x6bd95b2eUL} },
+ { &fnv_test_str[154], (Fnv64_t) {0x77aef85dUL, 0x74971b70UL} },
+ { &fnv_test_str[155], (Fnv64_t) {0xffcc1aadUL, 0xb4e4fae2UL} },
+ { &fnv_test_str[156], (Fnv64_t) {0x98b8f63aUL, 0x2bd48bd8UL} },
+ { &fnv_test_str[157], (Fnv64_t) {0x556257f6UL, 0xe9966ac1UL} },
+ { &fnv_test_str[158], (Fnv64_t) {0x078ba293UL, 0x92a3d1cdUL} },
+ { &fnv_test_str[159], (Fnv64_t) {0x82e20ab8UL, 0xf81175a4UL} },
+ { &fnv_test_str[160], (Fnv64_t) {0x22e73048UL, 0x5bbb3de7UL} },
+ { &fnv_test_str[161], (Fnv64_t) {0x92b9f2beUL, 0x6b4f3634UL} },
+ { &fnv_test_str[162], (Fnv64_t) {0x73d59875UL, 0xc2d559dfUL} },
+ { &fnv_test_str[163], (Fnv64_t) {0x4bc7a8c2UL, 0xf75f6228UL} },
+ { &fnv_test_str[164], (Fnv64_t) {0x16a9f1ccUL, 0xda8dd8e1UL} },
+ { &fnv_test_str[165], (Fnv64_t) {0x76057885UL, 0xbdc1e6abUL} },
+ { &fnv_test_str[166], (Fnv64_t) {0x8a1224a0UL, 0xfec6a423UL} },
+ { &fnv_test_str[167], (Fnv64_t) {0x223e290eUL, 0xc03f40f3UL} },
+ { &fnv_test_str[168], (Fnv64_t) {0x466ffda9UL, 0x1ed21673UL} },
+ { &fnv_test_str[169], (Fnv64_t) {0xbb0dd2afUL, 0xdf70f906UL} },
+ { &fnv_test_str[170], (Fnv64_t) {0x9f2af666UL, 0xf3dcda36UL} },
+ { &fnv_test_str[171], (Fnv64_t) {0x3cdcebdeUL, 0x9ebb1157UL} },
+ { &fnv_test_str[172], (Fnv64_t) {0x77fedca0UL, 0x81c72d90UL} },
+ { &fnv_test_str[173], (Fnv64_t) {0x1be5fb15UL, 0x0ec074a3UL} },
+ { &fnv_test_str[174], (Fnv64_t) {0xb6c48f20UL, 0x2a8b3280UL} },
+ { &fnv_test_str[175], (Fnv64_t) {0x13309344UL, 0xfd317775UL} },
+ { &fnv_test_str[176], (Fnv64_t) {0x6ad006b6UL, 0x194534a8UL} },
+ { &fnv_test_str[177], (Fnv64_t) {0x6e0cfe12UL, 0x3be6fdf4UL} },
+ { &fnv_test_str[178], (Fnv64_t) {0xa07eb057UL, 0x017cc137UL} },
+ { &fnv_test_str[179], (Fnv64_t) {0x7d26b54dUL, 0x9428fc6eUL} },
+ { &fnv_test_str[180], (Fnv64_t) {0x03ef8ad7UL, 0x9aaa2e36UL} },
+ { &fnv_test_str[181], (Fnv64_t) {0xa0ccdf7dUL, 0x82c6d3f3UL} },
+ { &fnv_test_str[182], (Fnv64_t) {0x0cf09b65UL, 0xc86eeea0UL} },
+ { &fnv_test_str[183], (Fnv64_t) {0xdbb58299UL, 0x705f8189UL} },
+ { &fnv_test_str[184], (Fnv64_t) {0x4391ca69UL, 0x415a7f55UL} },
+ { &fnv_test_str[185], (Fnv64_t) {0xa2bdc555UL, 0xcfe3d49fUL} },
+ { &fnv_test_str[186], (Fnv64_t) {0x39b25191UL, 0xf0f9c560UL} },
+ { &fnv_test_str[187], (Fnv64_t) {0xbd1d32d9UL, 0x7075cb6aUL} },
+ { &fnv_test_str[188], (Fnv64_t) {0x8b277509UL, 0x43c94e2cUL} },
+ { &fnv_test_str[189], (Fnv64_t) {0xea670359UL, 0x3cbfd4e4UL} },
+ { &fnv_test_str[190], (Fnv64_t) {0x0f4d019dUL, 0xc0588781UL} },
+ { &fnv_test_str[191], (Fnv64_t) {0x3ac22dc5UL, 0x14468ff9UL} },
+ { &fnv_test_str[192], (Fnv64_t) {0x89d99c05UL, 0xebed6995UL} },
+ { &fnv_test_str[193], (Fnv64_t) {0x321ca5d5UL, 0x6d99f6dfUL} },
+ { &fnv_test_str[194], (Fnv64_t) {0x8c36d625UL, 0x0cd410d0UL} },
+ { &fnv_test_str[195], (Fnv64_t) {0x86831d35UL, 0xef1b2a2cUL} },
+ { &fnv_test_str[196], (Fnv64_t) {0x69ee5f05UL, 0x3b349c4dUL} },
+ { &fnv_test_str[197], (Fnv64_t) {0x8f45f035UL, 0x55248ce8UL} },
+ { &fnv_test_str[198], (Fnv64_t) {0x18a4c885UL, 0xaa69ca6aUL} },
+ { &fnv_test_str[199], (Fnv64_t) {0x2bd816b5UL, 0x1fe3fce6UL} },
+ { &fnv_test_str[200], (Fnv64_t) {0xa8df69d9UL, 0x0289a488UL} },
+ { &fnv_test_str[201], (Fnv64_t) {0x13df98b5UL, 0x15e96e16UL} },
+ { &fnv_test_str[202], (Fnv64_t) {0x5ad89b99UL, 0xe6be5737UL} },
+ { NULL, (Fnv64_t) {0,0} }
+};
+#endif /* HAVE_64BIT_LONG_LONG */
+
+/* FNV-1a 64 bit test vectors */
+#if defined(HAVE_64BIT_LONG_LONG)
+struct fnv1a_64_test_vector fnv1a_64_vector[] = {
+ { &fnv_test_str[0], (Fnv64_t) 0xcbf29ce484222325ULL },
+ { &fnv_test_str[1], (Fnv64_t) 0xaf63dc4c8601ec8cULL },
+ { &fnv_test_str[2], (Fnv64_t) 0xaf63df4c8601f1a5ULL },
+ { &fnv_test_str[3], (Fnv64_t) 0xaf63de4c8601eff2ULL },
+ { &fnv_test_str[4], (Fnv64_t) 0xaf63d94c8601e773ULL },
+ { &fnv_test_str[5], (Fnv64_t) 0xaf63d84c8601e5c0ULL },
+ { &fnv_test_str[6], (Fnv64_t) 0xaf63db4c8601ead9ULL },
+ { &fnv_test_str[7], (Fnv64_t) 0x08985907b541d342ULL },
+ { &fnv_test_str[8], (Fnv64_t) 0xdcb27518fed9d577ULL },
+ { &fnv_test_str[9], (Fnv64_t) 0xdd120e790c2512afULL },
+ { &fnv_test_str[10], (Fnv64_t) 0xcac165afa2fef40aULL },
+ { &fnv_test_str[11], (Fnv64_t) 0x85944171f73967e8ULL },
+ { &fnv_test_str[12], (Fnv64_t) 0xaf63bd4c8601b7dfULL },
+ { &fnv_test_str[13], (Fnv64_t) 0x089be207b544f1e4ULL },
+ { &fnv_test_str[14], (Fnv64_t) 0x08a61407b54d9b5fULL },
+ { &fnv_test_str[15], (Fnv64_t) 0x08a2ae07b54ab836ULL },
+ { &fnv_test_str[16], (Fnv64_t) 0x0891b007b53c4869ULL },
+ { &fnv_test_str[17], (Fnv64_t) 0x088e4a07b5396540ULL },
+ { &fnv_test_str[18], (Fnv64_t) 0x08987c07b5420ebbULL },
+ { &fnv_test_str[19], (Fnv64_t) 0xdcb28a18fed9f926ULL },
+ { &fnv_test_str[20], (Fnv64_t) 0xdd1270790c25b935ULL },
+ { &fnv_test_str[21], (Fnv64_t) 0xcac146afa2febf5dULL },
+ { &fnv_test_str[22], (Fnv64_t) 0x8593d371f738acfeULL },
+ { &fnv_test_str[23], (Fnv64_t) 0x34531ca7168b8f38ULL },
+ { &fnv_test_str[24], (Fnv64_t) 0x08a25607b54a22aeULL },
+ { &fnv_test_str[25], (Fnv64_t) 0xf5faf0190cf90df3ULL },
+ { &fnv_test_str[26], (Fnv64_t) 0xf27397910b3221c7ULL },
+ { &fnv_test_str[27], (Fnv64_t) 0x2c8c2b76062f22e0ULL },
+ { &fnv_test_str[28], (Fnv64_t) 0xe150688c8217b8fdULL },
+ { &fnv_test_str[29], (Fnv64_t) 0xf35a83c10e4f1f87ULL },
+ { &fnv_test_str[30], (Fnv64_t) 0xd1edd10b507344d0ULL },
+ { &fnv_test_str[31], (Fnv64_t) 0x2a5ee739b3ddb8c3ULL },
+ { &fnv_test_str[32], (Fnv64_t) 0xdcfb970ca1c0d310ULL },
+ { &fnv_test_str[33], (Fnv64_t) 0x4054da76daa6da90ULL },
+ { &fnv_test_str[34], (Fnv64_t) 0xf70a2ff589861368ULL },
+ { &fnv_test_str[35], (Fnv64_t) 0x4c628b38aed25f17ULL },
+ { &fnv_test_str[36], (Fnv64_t) 0x9dd1f6510f78189fULL },
+ { &fnv_test_str[37], (Fnv64_t) 0xa3de85bd491270ceULL },
+ { &fnv_test_str[38], (Fnv64_t) 0x858e2fa32a55e61dULL },
+ { &fnv_test_str[39], (Fnv64_t) 0x46810940eff5f915ULL },
+ { &fnv_test_str[40], (Fnv64_t) 0xf5fadd190cf8edaaULL },
+ { &fnv_test_str[41], (Fnv64_t) 0xf273ed910b32b3e9ULL },
+ { &fnv_test_str[42], (Fnv64_t) 0x2c8c5276062f6525ULL },
+ { &fnv_test_str[43], (Fnv64_t) 0xe150b98c821842a0ULL },
+ { &fnv_test_str[44], (Fnv64_t) 0xf35aa3c10e4f55e7ULL },
+ { &fnv_test_str[45], (Fnv64_t) 0xd1ed680b50729265ULL },
+ { &fnv_test_str[46], (Fnv64_t) 0x2a5f0639b3dded70ULL },
+ { &fnv_test_str[47], (Fnv64_t) 0xdcfbaa0ca1c0f359ULL },
+ { &fnv_test_str[48], (Fnv64_t) 0x4054ba76daa6a430ULL },
+ { &fnv_test_str[49], (Fnv64_t) 0xf709c7f5898562b0ULL },
+ { &fnv_test_str[50], (Fnv64_t) 0x4c62e638aed2f9b8ULL },
+ { &fnv_test_str[51], (Fnv64_t) 0x9dd1a8510f779415ULL },
+ { &fnv_test_str[52], (Fnv64_t) 0xa3de2abd4911d62dULL },
+ { &fnv_test_str[53], (Fnv64_t) 0x858e0ea32a55ae0aULL },
+ { &fnv_test_str[54], (Fnv64_t) 0x46810f40eff60347ULL },
+ { &fnv_test_str[55], (Fnv64_t) 0xc33bce57bef63eafULL },
+ { &fnv_test_str[56], (Fnv64_t) 0x08a24307b54a0265ULL },
+ { &fnv_test_str[57], (Fnv64_t) 0xf5b9fd190cc18d15ULL },
+ { &fnv_test_str[58], (Fnv64_t) 0x4c968290ace35703ULL },
+ { &fnv_test_str[59], (Fnv64_t) 0x07174bd5c64d9350ULL },
+ { &fnv_test_str[60], (Fnv64_t) 0x5a294c3ff5d18750ULL },
+ { &fnv_test_str[61], (Fnv64_t) 0x05b3c1aeb308b843ULL },
+ { &fnv_test_str[62], (Fnv64_t) 0xb92a48da37d0f477ULL },
+ { &fnv_test_str[63], (Fnv64_t) 0x73cdddccd80ebc49ULL },
+ { &fnv_test_str[64], (Fnv64_t) 0xd58c4c13210a266bULL },
+ { &fnv_test_str[65], (Fnv64_t) 0xe78b6081243ec194ULL },
+ { &fnv_test_str[66], (Fnv64_t) 0xb096f77096a39f34ULL },
+ { &fnv_test_str[67], (Fnv64_t) 0xb425c54ff807b6a3ULL },
+ { &fnv_test_str[68], (Fnv64_t) 0x23e520e2751bb46eULL },
+ { &fnv_test_str[69], (Fnv64_t) 0x1a0b44ccfe1385ecULL },
+ { &fnv_test_str[70], (Fnv64_t) 0xf5ba4b190cc2119fULL },
+ { &fnv_test_str[71], (Fnv64_t) 0x4c962690ace2baafULL },
+ { &fnv_test_str[72], (Fnv64_t) 0x0716ded5c64cda19ULL },
+ { &fnv_test_str[73], (Fnv64_t) 0x5a292c3ff5d150f0ULL },
+ { &fnv_test_str[74], (Fnv64_t) 0x05b3e0aeb308ecf0ULL },
+ { &fnv_test_str[75], (Fnv64_t) 0xb92a5eda37d119d9ULL },
+ { &fnv_test_str[76], (Fnv64_t) 0x73ce41ccd80f6635ULL },
+ { &fnv_test_str[77], (Fnv64_t) 0xd58c2c132109f00bULL },
+ { &fnv_test_str[78], (Fnv64_t) 0xe78baf81243f47d1ULL },
+ { &fnv_test_str[79], (Fnv64_t) 0xb0968f7096a2ee7cULL },
+ { &fnv_test_str[80], (Fnv64_t) 0xb425a84ff807855cULL },
+ { &fnv_test_str[81], (Fnv64_t) 0x23e4e9e2751b56f9ULL },
+ { &fnv_test_str[82], (Fnv64_t) 0x1a0b4eccfe1396eaULL },
+ { &fnv_test_str[83], (Fnv64_t) 0x54abd453bb2c9004ULL },
+ { &fnv_test_str[84], (Fnv64_t) 0x08ba5f07b55ec3daULL },
+ { &fnv_test_str[85], (Fnv64_t) 0x337354193006cb6eULL },
+ { &fnv_test_str[86], (Fnv64_t) 0xa430d84680aabd0bULL },
+ { &fnv_test_str[87], (Fnv64_t) 0xa9bc8acca21f39b1ULL },
+ { &fnv_test_str[88], (Fnv64_t) 0x6961196491cc682dULL },
+ { &fnv_test_str[89], (Fnv64_t) 0xad2bb1774799dfe9ULL },
+ { &fnv_test_str[90], (Fnv64_t) 0x6961166491cc6314ULL },
+ { &fnv_test_str[91], (Fnv64_t) 0x8d1bb3904a3b1236ULL },
+ { &fnv_test_str[92], (Fnv64_t) 0x6961176491cc64c7ULL },
+ { &fnv_test_str[93], (Fnv64_t) 0xed205d87f40434c7ULL },
+ { &fnv_test_str[94], (Fnv64_t) 0x6961146491cc5faeULL },
+ { &fnv_test_str[95], (Fnv64_t) 0xcd3baf5e44f8ad9cULL },
+ { &fnv_test_str[96], (Fnv64_t) 0xe3b36596127cd6d8ULL },
+ { &fnv_test_str[97], (Fnv64_t) 0xf77f1072c8e8a646ULL },
+ { &fnv_test_str[98], (Fnv64_t) 0xe3b36396127cd372ULL },
+ { &fnv_test_str[99], (Fnv64_t) 0x6067dce9932ad458ULL },
+ { &fnv_test_str[100], (Fnv64_t) 0xe3b37596127cf208ULL },
+ { &fnv_test_str[101], (Fnv64_t) 0x4b7b10fa9fe83936ULL },
+ { &fnv_test_str[102], (Fnv64_t) 0xaabafe7104d914beULL },
+ { &fnv_test_str[103], (Fnv64_t) 0xf4d3180b3cde3edaULL },
+ { &fnv_test_str[104], (Fnv64_t) 0xaabafd7104d9130bULL },
+ { &fnv_test_str[105], (Fnv64_t) 0xf4cfb20b3cdb5bb1ULL },
+ { &fnv_test_str[106], (Fnv64_t) 0xaabafc7104d91158ULL },
+ { &fnv_test_str[107], (Fnv64_t) 0xf4cc4c0b3cd87888ULL },
+ { &fnv_test_str[108], (Fnv64_t) 0xe729bac5d2a8d3a7ULL },
+ { &fnv_test_str[109], (Fnv64_t) 0x74bc0524f4dfa4c5ULL },
+ { &fnv_test_str[110], (Fnv64_t) 0xe72630c5d2a5b352ULL },
+ { &fnv_test_str[111], (Fnv64_t) 0x6b983224ef8fb456ULL },
+ { &fnv_test_str[112], (Fnv64_t) 0xe73042c5d2ae266dULL },
+ { &fnv_test_str[113], (Fnv64_t) 0x8527e324fdeb4b37ULL },
+ { &fnv_test_str[114], (Fnv64_t) 0x0a83c86fee952abcULL },
+ { &fnv_test_str[115], (Fnv64_t) 0x7318523267779d74ULL },
+ { &fnv_test_str[116], (Fnv64_t) 0x3e66d3d56b8caca1ULL },
+ { &fnv_test_str[117], (Fnv64_t) 0x956694a5c0095593ULL },
+ { &fnv_test_str[118], (Fnv64_t) 0xcac54572bb1a6fc8ULL },
+ { &fnv_test_str[119], (Fnv64_t) 0xa7a4c9f3edebf0d8ULL },
+ { &fnv_test_str[120], (Fnv64_t) 0x7829851fac17b143ULL },
+ { &fnv_test_str[121], (Fnv64_t) 0x2c8f4c9af81bcf06ULL },
+ { &fnv_test_str[122], (Fnv64_t) 0xd34e31539740c732ULL },
+ { &fnv_test_str[123], (Fnv64_t) 0x3605a2ac253d2db1ULL },
+ { &fnv_test_str[124], (Fnv64_t) 0x08c11b8346f4a3c3ULL },
+ { &fnv_test_str[125], (Fnv64_t) 0x6be396289ce8a6daULL },
+ { &fnv_test_str[126], (Fnv64_t) 0xd9b957fb7fe794c5ULL },
+ { &fnv_test_str[127], (Fnv64_t) 0x05be33da04560a93ULL },
+ { &fnv_test_str[128], (Fnv64_t) 0x0957f1577ba9747cULL },
+ { &fnv_test_str[129], (Fnv64_t) 0xda2cc3acc24fba57ULL },
+ { &fnv_test_str[130], (Fnv64_t) 0x74136f185b29e7f0ULL },
+ { &fnv_test_str[131], (Fnv64_t) 0xb2f2b4590edb93b2ULL },
+ { &fnv_test_str[132], (Fnv64_t) 0xb3608fce8b86ae04ULL },
+ { &fnv_test_str[133], (Fnv64_t) 0x4a3a865079359063ULL },
+ { &fnv_test_str[134], (Fnv64_t) 0x5b3a7ef496880a50ULL },
+ { &fnv_test_str[135], (Fnv64_t) 0x48fae3163854c23bULL },
+ { &fnv_test_str[136], (Fnv64_t) 0x07aaa640476e0b9aULL },
+ { &fnv_test_str[137], (Fnv64_t) 0x2f653656383a687dULL },
+ { &fnv_test_str[138], (Fnv64_t) 0xa1031f8e7599d79cULL },
+ { &fnv_test_str[139], (Fnv64_t) 0xa31908178ff92477ULL },
+ { &fnv_test_str[140], (Fnv64_t) 0x097edf3c14c3fb83ULL },
+ { &fnv_test_str[141], (Fnv64_t) 0xb51ca83feaa0971bULL },
+ { &fnv_test_str[142], (Fnv64_t) 0xdd3c0d96d784f2e9ULL },
+ { &fnv_test_str[143], (Fnv64_t) 0x86cd26a9ea767d78ULL },
+ { &fnv_test_str[144], (Fnv64_t) 0xe6b215ff54a30c18ULL },
+ { &fnv_test_str[145], (Fnv64_t) 0xec5b06a1c5531093ULL },
+ { &fnv_test_str[146], (Fnv64_t) 0x45665a929f9ec5e5ULL },
+ { &fnv_test_str[147], (Fnv64_t) 0x8c7609b4a9f10907ULL },
+ { &fnv_test_str[148], (Fnv64_t) 0x89aac3a491f0d729ULL },
+ { &fnv_test_str[149], (Fnv64_t) 0x32ce6b26e0f4a403ULL },
+ { &fnv_test_str[150], (Fnv64_t) 0x614ab44e02b53e01ULL },
+ { &fnv_test_str[151], (Fnv64_t) 0xfa6472eb6eef3290ULL },
+ { &fnv_test_str[152], (Fnv64_t) 0x9e5d75eb1948eb6aULL },
+ { &fnv_test_str[153], (Fnv64_t) 0xb6d12ad4a8671852ULL },
+ { &fnv_test_str[154], (Fnv64_t) 0x88826f56eba07af1ULL },
+ { &fnv_test_str[155], (Fnv64_t) 0x44535bf2645bc0fdULL },
+ { &fnv_test_str[156], (Fnv64_t) 0x169388ffc21e3728ULL },
+ { &fnv_test_str[157], (Fnv64_t) 0xf68aac9e396d8224ULL },
+ { &fnv_test_str[158], (Fnv64_t) 0x8e87d7e7472b3883ULL },
+ { &fnv_test_str[159], (Fnv64_t) 0x295c26caa8b423deULL },
+ { &fnv_test_str[160], (Fnv64_t) 0x322c814292e72176ULL },
+ { &fnv_test_str[161], (Fnv64_t) 0x8a06550eb8af7268ULL },
+ { &fnv_test_str[162], (Fnv64_t) 0xef86d60e661bcf71ULL },
+ { &fnv_test_str[163], (Fnv64_t) 0x9e5426c87f30ee54ULL },
+ { &fnv_test_str[164], (Fnv64_t) 0xf1ea8aa826fd047eULL },
+ { &fnv_test_str[165], (Fnv64_t) 0x0babaf9a642cb769ULL },
+ { &fnv_test_str[166], (Fnv64_t) 0x4b3341d4068d012eULL },
+ { &fnv_test_str[167], (Fnv64_t) 0xd15605cbc30a335cULL },
+ { &fnv_test_str[168], (Fnv64_t) 0x5b21060aed8412e5ULL },
+ { &fnv_test_str[169], (Fnv64_t) 0x45e2cda1ce6f4227ULL },
+ { &fnv_test_str[170], (Fnv64_t) 0x50ae3745033ad7d4ULL },
+ { &fnv_test_str[171], (Fnv64_t) 0xaa4588ced46bf414ULL },
+ { &fnv_test_str[172], (Fnv64_t) 0xc1b0056c4a95467eULL },
+ { &fnv_test_str[173], (Fnv64_t) 0x56576a71de8b4089ULL },
+ { &fnv_test_str[174], (Fnv64_t) 0xbf20965fa6dc927eULL },
+ { &fnv_test_str[175], (Fnv64_t) 0x569f8383c2040882ULL },
+ { &fnv_test_str[176], (Fnv64_t) 0xe1e772fba08feca0ULL },
+ { &fnv_test_str[177], (Fnv64_t) 0x4ced94af97138ac4ULL },
+ { &fnv_test_str[178], (Fnv64_t) 0xc4112ffb337a82fbULL },
+ { &fnv_test_str[179], (Fnv64_t) 0xd64a4fd41de38b7dULL },
+ { &fnv_test_str[180], (Fnv64_t) 0x4cfc32329edebcbbULL },
+ { &fnv_test_str[181], (Fnv64_t) 0x0803564445050395ULL },
+ { &fnv_test_str[182], (Fnv64_t) 0xaa1574ecf4642ffdULL },
+ { &fnv_test_str[183], (Fnv64_t) 0x694bc4e54cc315f9ULL },
+ { &fnv_test_str[184], (Fnv64_t) 0xa3d7cb273b011721ULL },
+ { &fnv_test_str[185], (Fnv64_t) 0x577c2f8b6115bfa5ULL },
+ { &fnv_test_str[186], (Fnv64_t) 0xb7ec8c1a769fb4c1ULL },
+ { &fnv_test_str[187], (Fnv64_t) 0x5d5cfce63359ab19ULL },
+ { &fnv_test_str[188], (Fnv64_t) 0x33b96c3cd65b5f71ULL },
+ { &fnv_test_str[189], (Fnv64_t) 0xd845097780602bb9ULL },
+ { &fnv_test_str[190], (Fnv64_t) 0x84d47645d02da3d5ULL },
+ { &fnv_test_str[191], (Fnv64_t) 0x83544f33b58773a5ULL },
+ { &fnv_test_str[192], (Fnv64_t) 0x9175cbb2160836c5ULL },
+ { &fnv_test_str[193], (Fnv64_t) 0xc71b3bc175e72bc5ULL },
+ { &fnv_test_str[194], (Fnv64_t) 0x636806ac222ec985ULL },
+ { &fnv_test_str[195], (Fnv64_t) 0xb6ef0e6950f52ed5ULL },
+ { &fnv_test_str[196], (Fnv64_t) 0xead3d8a0f3dfdaa5ULL },
+ { &fnv_test_str[197], (Fnv64_t) 0x922908fe9a861ba5ULL },
+ { &fnv_test_str[198], (Fnv64_t) 0x6d4821de275fd5c5ULL },
+ { &fnv_test_str[199], (Fnv64_t) 0x1fe3fce62bd816b5ULL },
+ { &fnv_test_str[200], (Fnv64_t) 0xc23e9fccd6f70591ULL },
+ { &fnv_test_str[201], (Fnv64_t) 0xc1af12bdfe16b5b5ULL },
+ { &fnv_test_str[202], (Fnv64_t) 0x39e9f18f2f85e221ULL },
+ { NULL, (Fnv64_t) 0 }
+};
+#else /* HAVE_64BIT_LONG_LONG */
+struct fnv1a_64_test_vector fnv1a_64_vector[] = {
+ { &fnv_test_str[0], (Fnv64_t) {0x84222325UL, 0xcbf29ce4UL} },
+ { &fnv_test_str[1], (Fnv64_t) {0x8601ec8cUL, 0xaf63dc4cUL} },
+ { &fnv_test_str[2], (Fnv64_t) {0x8601f1a5UL, 0xaf63df4cUL} },
+ { &fnv_test_str[3], (Fnv64_t) {0x8601eff2UL, 0xaf63de4cUL} },
+ { &fnv_test_str[4], (Fnv64_t) {0x8601e773UL, 0xaf63d94cUL} },
+ { &fnv_test_str[5], (Fnv64_t) {0x8601e5c0UL, 0xaf63d84cUL} },
+ { &fnv_test_str[6], (Fnv64_t) {0x8601ead9UL, 0xaf63db4cUL} },
+ { &fnv_test_str[7], (Fnv64_t) {0xb541d342UL, 0x08985907UL} },
+ { &fnv_test_str[8], (Fnv64_t) {0xfed9d577UL, 0xdcb27518UL} },
+ { &fnv_test_str[9], (Fnv64_t) {0x0c2512afUL, 0xdd120e79UL} },
+ { &fnv_test_str[10], (Fnv64_t) {0xa2fef40aUL, 0xcac165afUL} },
+ { &fnv_test_str[11], (Fnv64_t) {0xf73967e8UL, 0x85944171UL} },
+ { &fnv_test_str[12], (Fnv64_t) {0x8601b7dfUL, 0xaf63bd4cUL} },
+ { &fnv_test_str[13], (Fnv64_t) {0xb544f1e4UL, 0x089be207UL} },
+ { &fnv_test_str[14], (Fnv64_t) {0xb54d9b5fUL, 0x08a61407UL} },
+ { &fnv_test_str[15], (Fnv64_t) {0xb54ab836UL, 0x08a2ae07UL} },
+ { &fnv_test_str[16], (Fnv64_t) {0xb53c4869UL, 0x0891b007UL} },
+ { &fnv_test_str[17], (Fnv64_t) {0xb5396540UL, 0x088e4a07UL} },
+ { &fnv_test_str[18], (Fnv64_t) {0xb5420ebbUL, 0x08987c07UL} },
+ { &fnv_test_str[19], (Fnv64_t) {0xfed9f926UL, 0xdcb28a18UL} },
+ { &fnv_test_str[20], (Fnv64_t) {0x0c25b935UL, 0xdd127079UL} },
+ { &fnv_test_str[21], (Fnv64_t) {0xa2febf5dUL, 0xcac146afUL} },
+ { &fnv_test_str[22], (Fnv64_t) {0xf738acfeUL, 0x8593d371UL} },
+ { &fnv_test_str[23], (Fnv64_t) {0x168b8f38UL, 0x34531ca7UL} },
+ { &fnv_test_str[24], (Fnv64_t) {0xb54a22aeUL, 0x08a25607UL} },
+ { &fnv_test_str[25], (Fnv64_t) {0x0cf90df3UL, 0xf5faf019UL} },
+ { &fnv_test_str[26], (Fnv64_t) {0x0b3221c7UL, 0xf2739791UL} },
+ { &fnv_test_str[27], (Fnv64_t) {0x062f22e0UL, 0x2c8c2b76UL} },
+ { &fnv_test_str[28], (Fnv64_t) {0x8217b8fdUL, 0xe150688cUL} },
+ { &fnv_test_str[29], (Fnv64_t) {0x0e4f1f87UL, 0xf35a83c1UL} },
+ { &fnv_test_str[30], (Fnv64_t) {0x507344d0UL, 0xd1edd10bUL} },
+ { &fnv_test_str[31], (Fnv64_t) {0xb3ddb8c3UL, 0x2a5ee739UL} },
+ { &fnv_test_str[32], (Fnv64_t) {0xa1c0d310UL, 0xdcfb970cUL} },
+ { &fnv_test_str[33], (Fnv64_t) {0xdaa6da90UL, 0x4054da76UL} },
+ { &fnv_test_str[34], (Fnv64_t) {0x89861368UL, 0xf70a2ff5UL} },
+ { &fnv_test_str[35], (Fnv64_t) {0xaed25f17UL, 0x4c628b38UL} },
+ { &fnv_test_str[36], (Fnv64_t) {0x0f78189fUL, 0x9dd1f651UL} },
+ { &fnv_test_str[37], (Fnv64_t) {0x491270ceUL, 0xa3de85bdUL} },
+ { &fnv_test_str[38], (Fnv64_t) {0x2a55e61dUL, 0x858e2fa3UL} },
+ { &fnv_test_str[39], (Fnv64_t) {0xeff5f915UL, 0x46810940UL} },
+ { &fnv_test_str[40], (Fnv64_t) {0x0cf8edaaUL, 0xf5fadd19UL} },
+ { &fnv_test_str[41], (Fnv64_t) {0x0b32b3e9UL, 0xf273ed91UL} },
+ { &fnv_test_str[42], (Fnv64_t) {0x062f6525UL, 0x2c8c5276UL} },
+ { &fnv_test_str[43], (Fnv64_t) {0x821842a0UL, 0xe150b98cUL} },
+ { &fnv_test_str[44], (Fnv64_t) {0x0e4f55e7UL, 0xf35aa3c1UL} },
+ { &fnv_test_str[45], (Fnv64_t) {0x50729265UL, 0xd1ed680bUL} },
+ { &fnv_test_str[46], (Fnv64_t) {0xb3dded70UL, 0x2a5f0639UL} },
+ { &fnv_test_str[47], (Fnv64_t) {0xa1c0f359UL, 0xdcfbaa0cUL} },
+ { &fnv_test_str[48], (Fnv64_t) {0xdaa6a430UL, 0x4054ba76UL} },
+ { &fnv_test_str[49], (Fnv64_t) {0x898562b0UL, 0xf709c7f5UL} },
+ { &fnv_test_str[50], (Fnv64_t) {0xaed2f9b8UL, 0x4c62e638UL} },
+ { &fnv_test_str[51], (Fnv64_t) {0x0f779415UL, 0x9dd1a851UL} },
+ { &fnv_test_str[52], (Fnv64_t) {0x4911d62dUL, 0xa3de2abdUL} },
+ { &fnv_test_str[53], (Fnv64_t) {0x2a55ae0aUL, 0x858e0ea3UL} },
+ { &fnv_test_str[54], (Fnv64_t) {0xeff60347UL, 0x46810f40UL} },
+ { &fnv_test_str[55], (Fnv64_t) {0xbef63eafUL, 0xc33bce57UL} },
+ { &fnv_test_str[56], (Fnv64_t) {0xb54a0265UL, 0x08a24307UL} },
+ { &fnv_test_str[57], (Fnv64_t) {0x0cc18d15UL, 0xf5b9fd19UL} },
+ { &fnv_test_str[58], (Fnv64_t) {0xace35703UL, 0x4c968290UL} },
+ { &fnv_test_str[59], (Fnv64_t) {0xc64d9350UL, 0x07174bd5UL} },
+ { &fnv_test_str[60], (Fnv64_t) {0xf5d18750UL, 0x5a294c3fUL} },
+ { &fnv_test_str[61], (Fnv64_t) {0xb308b843UL, 0x05b3c1aeUL} },
+ { &fnv_test_str[62], (Fnv64_t) {0x37d0f477UL, 0xb92a48daUL} },
+ { &fnv_test_str[63], (Fnv64_t) {0xd80ebc49UL, 0x73cdddccUL} },
+ { &fnv_test_str[64], (Fnv64_t) {0x210a266bUL, 0xd58c4c13UL} },
+ { &fnv_test_str[65], (Fnv64_t) {0x243ec194UL, 0xe78b6081UL} },
+ { &fnv_test_str[66], (Fnv64_t) {0x96a39f34UL, 0xb096f770UL} },
+ { &fnv_test_str[67], (Fnv64_t) {0xf807b6a3UL, 0xb425c54fUL} },
+ { &fnv_test_str[68], (Fnv64_t) {0x751bb46eUL, 0x23e520e2UL} },
+ { &fnv_test_str[69], (Fnv64_t) {0xfe1385ecUL, 0x1a0b44ccUL} },
+ { &fnv_test_str[70], (Fnv64_t) {0x0cc2119fUL, 0xf5ba4b19UL} },
+ { &fnv_test_str[71], (Fnv64_t) {0xace2baafUL, 0x4c962690UL} },
+ { &fnv_test_str[72], (Fnv64_t) {0xc64cda19UL, 0x0716ded5UL} },
+ { &fnv_test_str[73], (Fnv64_t) {0xf5d150f0UL, 0x5a292c3fUL} },
+ { &fnv_test_str[74], (Fnv64_t) {0xb308ecf0UL, 0x05b3e0aeUL} },
+ { &fnv_test_str[75], (Fnv64_t) {0x37d119d9UL, 0xb92a5edaUL} },
+ { &fnv_test_str[76], (Fnv64_t) {0xd80f6635UL, 0x73ce41ccUL} },
+ { &fnv_test_str[77], (Fnv64_t) {0x2109f00bUL, 0xd58c2c13UL} },
+ { &fnv_test_str[78], (Fnv64_t) {0x243f47d1UL, 0xe78baf81UL} },
+ { &fnv_test_str[79], (Fnv64_t) {0x96a2ee7cUL, 0xb0968f70UL} },
+ { &fnv_test_str[80], (Fnv64_t) {0xf807855cUL, 0xb425a84fUL} },
+ { &fnv_test_str[81], (Fnv64_t) {0x751b56f9UL, 0x23e4e9e2UL} },
+ { &fnv_test_str[82], (Fnv64_t) {0xfe1396eaUL, 0x1a0b4eccUL} },
+ { &fnv_test_str[83], (Fnv64_t) {0xbb2c9004UL, 0x54abd453UL} },
+ { &fnv_test_str[84], (Fnv64_t) {0xb55ec3daUL, 0x08ba5f07UL} },
+ { &fnv_test_str[85], (Fnv64_t) {0x3006cb6eUL, 0x33735419UL} },
+ { &fnv_test_str[86], (Fnv64_t) {0x80aabd0bUL, 0xa430d846UL} },
+ { &fnv_test_str[87], (Fnv64_t) {0xa21f39b1UL, 0xa9bc8accUL} },
+ { &fnv_test_str[88], (Fnv64_t) {0x91cc682dUL, 0x69611964UL} },
+ { &fnv_test_str[89], (Fnv64_t) {0x4799dfe9UL, 0xad2bb177UL} },
+ { &fnv_test_str[90], (Fnv64_t) {0x91cc6314UL, 0x69611664UL} },
+ { &fnv_test_str[91], (Fnv64_t) {0x4a3b1236UL, 0x8d1bb390UL} },
+ { &fnv_test_str[92], (Fnv64_t) {0x91cc64c7UL, 0x69611764UL} },
+ { &fnv_test_str[93], (Fnv64_t) {0xf40434c7UL, 0xed205d87UL} },
+ { &fnv_test_str[94], (Fnv64_t) {0x91cc5faeUL, 0x69611464UL} },
+ { &fnv_test_str[95], (Fnv64_t) {0x44f8ad9cUL, 0xcd3baf5eUL} },
+ { &fnv_test_str[96], (Fnv64_t) {0x127cd6d8UL, 0xe3b36596UL} },
+ { &fnv_test_str[97], (Fnv64_t) {0xc8e8a646UL, 0xf77f1072UL} },
+ { &fnv_test_str[98], (Fnv64_t) {0x127cd372UL, 0xe3b36396UL} },
+ { &fnv_test_str[99], (Fnv64_t) {0x932ad458UL, 0x6067dce9UL} },
+ { &fnv_test_str[100], (Fnv64_t) {0x127cf208UL, 0xe3b37596UL} },
+ { &fnv_test_str[101], (Fnv64_t) {0x9fe83936UL, 0x4b7b10faUL} },
+ { &fnv_test_str[102], (Fnv64_t) {0x04d914beUL, 0xaabafe71UL} },
+ { &fnv_test_str[103], (Fnv64_t) {0x3cde3edaUL, 0xf4d3180bUL} },
+ { &fnv_test_str[104], (Fnv64_t) {0x04d9130bUL, 0xaabafd71UL} },
+ { &fnv_test_str[105], (Fnv64_t) {0x3cdb5bb1UL, 0xf4cfb20bUL} },
+ { &fnv_test_str[106], (Fnv64_t) {0x04d91158UL, 0xaabafc71UL} },
+ { &fnv_test_str[107], (Fnv64_t) {0x3cd87888UL, 0xf4cc4c0bUL} },
+ { &fnv_test_str[108], (Fnv64_t) {0xd2a8d3a7UL, 0xe729bac5UL} },
+ { &fnv_test_str[109], (Fnv64_t) {0xf4dfa4c5UL, 0x74bc0524UL} },
+ { &fnv_test_str[110], (Fnv64_t) {0xd2a5b352UL, 0xe72630c5UL} },
+ { &fnv_test_str[111], (Fnv64_t) {0xef8fb456UL, 0x6b983224UL} },
+ { &fnv_test_str[112], (Fnv64_t) {0xd2ae266dUL, 0xe73042c5UL} },
+ { &fnv_test_str[113], (Fnv64_t) {0xfdeb4b37UL, 0x8527e324UL} },
+ { &fnv_test_str[114], (Fnv64_t) {0xee952abcUL, 0x0a83c86fUL} },
+ { &fnv_test_str[115], (Fnv64_t) {0x67779d74UL, 0x73185232UL} },
+ { &fnv_test_str[116], (Fnv64_t) {0x6b8caca1UL, 0x3e66d3d5UL} },
+ { &fnv_test_str[117], (Fnv64_t) {0xc0095593UL, 0x956694a5UL} },
+ { &fnv_test_str[118], (Fnv64_t) {0xbb1a6fc8UL, 0xcac54572UL} },
+ { &fnv_test_str[119], (Fnv64_t) {0xedebf0d8UL, 0xa7a4c9f3UL} },
+ { &fnv_test_str[120], (Fnv64_t) {0xac17b143UL, 0x7829851fUL} },
+ { &fnv_test_str[121], (Fnv64_t) {0xf81bcf06UL, 0x2c8f4c9aUL} },
+ { &fnv_test_str[122], (Fnv64_t) {0x9740c732UL, 0xd34e3153UL} },
+ { &fnv_test_str[123], (Fnv64_t) {0x253d2db1UL, 0x3605a2acUL} },
+ { &fnv_test_str[124], (Fnv64_t) {0x46f4a3c3UL, 0x08c11b83UL} },
+ { &fnv_test_str[125], (Fnv64_t) {0x9ce8a6daUL, 0x6be39628UL} },
+ { &fnv_test_str[126], (Fnv64_t) {0x7fe794c5UL, 0xd9b957fbUL} },
+ { &fnv_test_str[127], (Fnv64_t) {0x04560a93UL, 0x05be33daUL} },
+ { &fnv_test_str[128], (Fnv64_t) {0x7ba9747cUL, 0x0957f157UL} },
+ { &fnv_test_str[129], (Fnv64_t) {0xc24fba57UL, 0xda2cc3acUL} },
+ { &fnv_test_str[130], (Fnv64_t) {0x5b29e7f0UL, 0x74136f18UL} },
+ { &fnv_test_str[131], (Fnv64_t) {0x0edb93b2UL, 0xb2f2b459UL} },
+ { &fnv_test_str[132], (Fnv64_t) {0x8b86ae04UL, 0xb3608fceUL} },
+ { &fnv_test_str[133], (Fnv64_t) {0x79359063UL, 0x4a3a8650UL} },
+ { &fnv_test_str[134], (Fnv64_t) {0x96880a50UL, 0x5b3a7ef4UL} },
+ { &fnv_test_str[135], (Fnv64_t) {0x3854c23bUL, 0x48fae316UL} },
+ { &fnv_test_str[136], (Fnv64_t) {0x476e0b9aUL, 0x07aaa640UL} },
+ { &fnv_test_str[137], (Fnv64_t) {0x383a687dUL, 0x2f653656UL} },
+ { &fnv_test_str[138], (Fnv64_t) {0x7599d79cUL, 0xa1031f8eUL} },
+ { &fnv_test_str[139], (Fnv64_t) {0x8ff92477UL, 0xa3190817UL} },
+ { &fnv_test_str[140], (Fnv64_t) {0x14c3fb83UL, 0x097edf3cUL} },
+ { &fnv_test_str[141], (Fnv64_t) {0xeaa0971bUL, 0xb51ca83fUL} },
+ { &fnv_test_str[142], (Fnv64_t) {0xd784f2e9UL, 0xdd3c0d96UL} },
+ { &fnv_test_str[143], (Fnv64_t) {0xea767d78UL, 0x86cd26a9UL} },
+ { &fnv_test_str[144], (Fnv64_t) {0x54a30c18UL, 0xe6b215ffUL} },
+ { &fnv_test_str[145], (Fnv64_t) {0xc5531093UL, 0xec5b06a1UL} },
+ { &fnv_test_str[146], (Fnv64_t) {0x9f9ec5e5UL, 0x45665a92UL} },
+ { &fnv_test_str[147], (Fnv64_t) {0xa9f10907UL, 0x8c7609b4UL} },
+ { &fnv_test_str[148], (Fnv64_t) {0x91f0d729UL, 0x89aac3a4UL} },
+ { &fnv_test_str[149], (Fnv64_t) {0xe0f4a403UL, 0x32ce6b26UL} },
+ { &fnv_test_str[150], (Fnv64_t) {0x02b53e01UL, 0x614ab44eUL} },
+ { &fnv_test_str[151], (Fnv64_t) {0x6eef3290UL, 0xfa6472ebUL} },
+ { &fnv_test_str[152], (Fnv64_t) {0x1948eb6aUL, 0x9e5d75ebUL} },
+ { &fnv_test_str[153], (Fnv64_t) {0xa8671852UL, 0xb6d12ad4UL} },
+ { &fnv_test_str[154], (Fnv64_t) {0xeba07af1UL, 0x88826f56UL} },
+ { &fnv_test_str[155], (Fnv64_t) {0x645bc0fdUL, 0x44535bf2UL} },
+ { &fnv_test_str[156], (Fnv64_t) {0xc21e3728UL, 0x169388ffUL} },
+ { &fnv_test_str[157], (Fnv64_t) {0x396d8224UL, 0xf68aac9eUL} },
+ { &fnv_test_str[158], (Fnv64_t) {0x472b3883UL, 0x8e87d7e7UL} },
+ { &fnv_test_str[159], (Fnv64_t) {0xa8b423deUL, 0x295c26caUL} },
+ { &fnv_test_str[160], (Fnv64_t) {0x92e72176UL, 0x322c8142UL} },
+ { &fnv_test_str[161], (Fnv64_t) {0xb8af7268UL, 0x8a06550eUL} },
+ { &fnv_test_str[162], (Fnv64_t) {0x661bcf71UL, 0xef86d60eUL} },
+ { &fnv_test_str[163], (Fnv64_t) {0x7f30ee54UL, 0x9e5426c8UL} },
+ { &fnv_test_str[164], (Fnv64_t) {0x26fd047eUL, 0xf1ea8aa8UL} },
+ { &fnv_test_str[165], (Fnv64_t) {0x642cb769UL, 0x0babaf9aUL} },
+ { &fnv_test_str[166], (Fnv64_t) {0x068d012eUL, 0x4b3341d4UL} },
+ { &fnv_test_str[167], (Fnv64_t) {0xc30a335cUL, 0xd15605cbUL} },
+ { &fnv_test_str[168], (Fnv64_t) {0xed8412e5UL, 0x5b21060aUL} },
+ { &fnv_test_str[169], (Fnv64_t) {0xce6f4227UL, 0x45e2cda1UL} },
+ { &fnv_test_str[170], (Fnv64_t) {0x033ad7d4UL, 0x50ae3745UL} },
+ { &fnv_test_str[171], (Fnv64_t) {0xd46bf414UL, 0xaa4588ceUL} },
+ { &fnv_test_str[172], (Fnv64_t) {0x4a95467eUL, 0xc1b0056cUL} },
+ { &fnv_test_str[173], (Fnv64_t) {0xde8b4089UL, 0x56576a71UL} },
+ { &fnv_test_str[174], (Fnv64_t) {0xa6dc927eUL, 0xbf20965fUL} },
+ { &fnv_test_str[175], (Fnv64_t) {0xc2040882UL, 0x569f8383UL} },
+ { &fnv_test_str[176], (Fnv64_t) {0xa08feca0UL, 0xe1e772fbUL} },
+ { &fnv_test_str[177], (Fnv64_t) {0x97138ac4UL, 0x4ced94afUL} },
+ { &fnv_test_str[178], (Fnv64_t) {0x337a82fbUL, 0xc4112ffbUL} },
+ { &fnv_test_str[179], (Fnv64_t) {0x1de38b7dUL, 0xd64a4fd4UL} },
+ { &fnv_test_str[180], (Fnv64_t) {0x9edebcbbUL, 0x4cfc3232UL} },
+ { &fnv_test_str[181], (Fnv64_t) {0x45050395UL, 0x08035644UL} },
+ { &fnv_test_str[182], (Fnv64_t) {0xf4642ffdUL, 0xaa1574ecUL} },
+ { &fnv_test_str[183], (Fnv64_t) {0x4cc315f9UL, 0x694bc4e5UL} },
+ { &fnv_test_str[184], (Fnv64_t) {0x3b011721UL, 0xa3d7cb27UL} },
+ { &fnv_test_str[185], (Fnv64_t) {0x6115bfa5UL, 0x577c2f8bUL} },
+ { &fnv_test_str[186], (Fnv64_t) {0x769fb4c1UL, 0xb7ec8c1aUL} },
+ { &fnv_test_str[187], (Fnv64_t) {0x3359ab19UL, 0x5d5cfce6UL} },
+ { &fnv_test_str[188], (Fnv64_t) {0xd65b5f71UL, 0x33b96c3cUL} },
+ { &fnv_test_str[189], (Fnv64_t) {0x80602bb9UL, 0xd8450977UL} },
+ { &fnv_test_str[190], (Fnv64_t) {0xd02da3d5UL, 0x84d47645UL} },
+ { &fnv_test_str[191], (Fnv64_t) {0xb58773a5UL, 0x83544f33UL} },
+ { &fnv_test_str[192], (Fnv64_t) {0x160836c5UL, 0x9175cbb2UL} },
+ { &fnv_test_str[193], (Fnv64_t) {0x75e72bc5UL, 0xc71b3bc1UL} },
+ { &fnv_test_str[194], (Fnv64_t) {0x222ec985UL, 0x636806acUL} },
+ { &fnv_test_str[195], (Fnv64_t) {0x50f52ed5UL, 0xb6ef0e69UL} },
+ { &fnv_test_str[196], (Fnv64_t) {0xf3dfdaa5UL, 0xead3d8a0UL} },
+ { &fnv_test_str[197], (Fnv64_t) {0x9a861ba5UL, 0x922908feUL} },
+ { &fnv_test_str[198], (Fnv64_t) {0x275fd5c5UL, 0x6d4821deUL} },
+ { &fnv_test_str[199], (Fnv64_t) {0x2bd816b5UL, 0x1fe3fce6UL} },
+ { &fnv_test_str[200], (Fnv64_t) {0xd6f70591UL, 0xc23e9fccUL} },
+ { &fnv_test_str[201], (Fnv64_t) {0xfe16b5b5UL, 0xc1af12bdUL} },
+ { &fnv_test_str[202], (Fnv64_t) {0x2f85e221UL, 0x39e9f18fUL} },
+ { NULL, (Fnv64_t) {0,0} }
+};
+#endif /* HAVE_64BIT_LONG_LONG */
+
+/* end of output generated by make vector.c */
+/*
+ * insert the contents of vector.c above
+ */
+
+
+/*
+ * unknown_hash_type - report an unknown hash type error
+ *
+ * NOTE: Does not return.
+ */
+void
+unknown_hash_type(char *prog, enum fnv_type type, int code)
+{
+ fprintf(stderr, "%s: unknown or unexpexted hash type: %d\n", prog, type);
+ exit(code);
+}
+
+
+/*
+ * print_fnv32 - print an FNV hash
+ *
+ * given:
+ * hval the hash value to print
+ * mask lower bit mask
+ * verbose 1 => print arg with hash
+ * arg string or filename arg
+ */
+void
+print_fnv32(Fnv32_t hval, Fnv32_t mask, int verbose, char *arg)
+{
+ if (verbose) {
+ printf("0x%08lx %s\n", hval & mask, arg);
+ } else {
+ printf("0x%08lx\n", hval & mask);
+ }
+}
+
+
+/*
+ * print_fnv64 - print an FNV hash
+ *
+ * given:
+ * hval the hash value to print
+ * mask lower bit mask
+ * verbose 1 => print arg with hash
+ * arg string or filename arg
+ */
+void
+print_fnv64(Fnv64_t hval, Fnv64_t mask, int verbose, char *arg)
+{
+#if defined(HAVE_64BIT_LONG_LONG)
+ if (verbose) {
+ printf("0x%016llx %s\n", hval & mask, arg);
+ } else {
+ printf("0x%016llx\n", hval & mask);
+ }
+#else
+ if (verbose) {
+ printf("0x%08lx%08lx %s\n",
+ hval.w32[1] & mask.w32[1],
+ hval.w32[0] & mask.w32[0],
+ arg);
+ } else {
+ printf("0x%08lx%08lx\n",
+ hval.w32[1] & mask.w32[1],
+ hval.w32[0] & mask.w32[0]);
+ }
+#endif
+}
diff --git a/lib/lufa b/lib/lufa
-Subproject 19a5d533f02a7b46eeadca99cc9699659cef7a6
+Subproject 35cc3d92f557bc8874ca602d2f22642d77cfe12
diff --git a/lib/pico-sdk b/lib/pico-sdk
new file mode 160000
+Subproject 07edde8e49890d2172bbc272aacc119f999df06
diff --git a/lib/python/qmk/cli/doctor/macos.py b/lib/python/qmk/cli/doctor/macos.py
index 00fb272858..5d088c9492 100644
--- a/lib/python/qmk/cli/doctor/macos.py
+++ b/lib/python/qmk/cli/doctor/macos.py
@@ -8,6 +8,6 @@ from .check import CheckStatus
def os_test_macos():
"""Run the Mac specific tests.
"""
- cli.log.info("Detected {fg_cyan}macOS %s{fg_reset}.", platform.mac_ver()[0])
+ cli.log.info("Detected {fg_cyan}macOS %s (%s){fg_reset}.", platform.mac_ver()[0], 'Apple Silicon' if platform.processor() == 'arm' else 'Intel')
return CheckStatus.OK
diff --git a/lib/python/qmk/cli/flash.py b/lib/python/qmk/cli/flash.py
index 216896b974..ebe739c50e 100644
--- a/lib/python/qmk/cli/flash.py
+++ b/lib/python/qmk/cli/flash.py
@@ -33,6 +33,8 @@ def print_bootloader_help():
cli.echo('\tdfu-split-right')
cli.echo('\tdfu-util-split-left')
cli.echo('\tdfu-util-split-right')
+ cli.echo('\tuf2-split-left')
+ cli.echo('\tuf2-split-right')
cli.echo('For more info, visit https://docs.qmk.fm/#/flashing')
diff --git a/lib/python/qmk/cli/generate/config_h.py b/lib/python/qmk/cli/generate/config_h.py
index 893892c479..9d50368aba 100755
--- a/lib/python/qmk/cli/generate/config_h.py
+++ b/lib/python/qmk/cli/generate/config_h.py
@@ -134,6 +134,29 @@ def generate_config_items(kb_info_json, config_h_lines):
config_h_lines.append(f'#endif // {config_key}')
+def generate_encoder_config(encoder_json, config_h_lines, postfix=''):
+ """Generate the config.h lines for encoders."""
+ a_pads = []
+ b_pads = []
+ resolutions = []
+ for encoder in encoder_json.get("rotary", []):
+ a_pads.append(encoder["pin_a"])
+ b_pads.append(encoder["pin_b"])
+ resolutions.append(str(encoder.get("resolution", 4)))
+
+ config_h_lines.append(f'#ifndef ENCODERS_PAD_A{postfix}')
+ config_h_lines.append(f'# define ENCODERS_PAD_A{postfix} {{ { ", ".join(a_pads) } }}')
+ config_h_lines.append(f'#endif // ENCODERS_PAD_A{postfix}')
+
+ config_h_lines.append(f'#ifndef ENCODERS_PAD_B{postfix}')
+ config_h_lines.append(f'# define ENCODERS_PAD_B{postfix} {{ { ", ".join(b_pads) } }}')
+ config_h_lines.append(f'#endif // ENCODERS_PAD_B{postfix}')
+
+ config_h_lines.append(f'#ifndef ENCODER_RESOLUTIONS{postfix}')
+ config_h_lines.append(f'# define ENCODER_RESOLUTIONS{postfix} {{ { ", ".join(resolutions) } }}')
+ config_h_lines.append(f'#endif // ENCODER_RESOLUTIONS{postfix}')
+
+
def generate_split_config(kb_info_json, config_h_lines):
"""Generate the config.h lines for split boards."""
if 'primary' in kb_info_json['split']:
@@ -173,6 +196,9 @@ def generate_split_config(kb_info_json, config_h_lines):
if 'right' in kb_info_json['split'].get('matrix_pins', {}):
config_h_lines.append(matrix_pins(kb_info_json['split']['matrix_pins']['right'], '_RIGHT'))
+ if 'right' in kb_info_json['split'].get('encoder', {}):
+ generate_encoder_config(kb_info_json['split']['encoder']['right'], config_h_lines, '_RIGHT')
+
@cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
@@ -198,6 +224,9 @@ def generate_config_h(cli):
if 'matrix_pins' in kb_info_json:
config_h_lines.append(matrix_pins(kb_info_json['matrix_pins']))
+ if 'encoder' in kb_info_json:
+ generate_encoder_config(kb_info_json['encoder'], config_h_lines)
+
if 'split' in kb_info_json:
generate_split_config(kb_info_json, config_h_lines)
diff --git a/lib/python/qmk/cli/generate/info_json.py b/lib/python/qmk/cli/generate/info_json.py
index 284d1a8510..0dc80f10cc 100755
--- a/lib/python/qmk/cli/generate/info_json.py
+++ b/lib/python/qmk/cli/generate/info_json.py
@@ -5,7 +5,7 @@ Compile an info.json for a particular keyboard and pretty-print it.
import json
from argcomplete.completers import FilesCompleter
-from jsonschema import Draft7Validator, RefResolver, validators
+from jsonschema import Draft202012Validator, RefResolver, validators
from milc import cli
from pathlib import Path
@@ -18,7 +18,7 @@ from qmk.path import is_keyboard, normpath
def pruning_validator(validator_class):
- """Extends Draft7Validator to remove properties that aren't specified in the schema.
+ """Extends Draft202012Validator to remove properties that aren't specified in the schema.
"""
validate_properties = validator_class.VALIDATORS["properties"]
@@ -37,10 +37,10 @@ def strip_info_json(kb_info_json):
"""Remove the API-only properties from the info.json.
"""
schema_store = compile_schema_store()
- pruning_draft_7_validator = pruning_validator(Draft7Validator)
+ pruning_draft_validator = pruning_validator(Draft202012Validator)
schema = schema_store['qmk.keyboard.v1']
resolver = RefResolver.from_schema(schema_store['qmk.keyboard.v1'], store=schema_store)
- validator = pruning_draft_7_validator(schema, resolver=resolver).validate
+ validator = pruning_draft_validator(schema, resolver=resolver).validate
return validator(kb_info_json)
diff --git a/lib/python/qmk/constants.py b/lib/python/qmk/constants.py
index a54d9058bc..be85a1dbff 100644
--- a/lib/python/qmk/constants.py
+++ b/lib/python/qmk/constants.py
@@ -14,7 +14,7 @@ QMK_FIRMWARE_UPSTREAM = 'qmk/qmk_firmware'
MAX_KEYBOARD_SUBFOLDERS = 5
# Supported processor types
-CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66FX1M0', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F405', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32L412', 'STM32L422', 'STM32L432', 'STM32L433', 'STM32L442', 'STM32L443', 'GD32VF103', 'WB32F3G71', 'WB32FQ95'
+CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66FX1M0', 'RP2040', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F405', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32L412', 'STM32L422', 'STM32L432', 'STM32L433', 'STM32L442', 'STM32L443', 'GD32VF103', 'WB32F3G71', 'WB32FQ95'
LUFA_PROCESSORS = 'at90usb162', 'atmega16u2', 'atmega32u2', 'atmega16u4', 'atmega32u4', 'at90usb646', 'at90usb647', 'at90usb1286', 'at90usb1287', None
VUSB_PROCESSORS = 'atmega32a', 'atmega328p', 'atmega328', 'attiny85'
diff --git a/lib/python/qmk/git.py b/lib/python/qmk/git.py
index f493628492..960184a0a2 100644
--- a/lib/python/qmk/git.py
+++ b/lib/python/qmk/git.py
@@ -111,9 +111,9 @@ def git_check_deviation(active_branch):
def git_get_ignored_files(check_dir='.'):
- """Return a list of files that would be captured by the current .gitingore
+ """Return a list of files that would be captured by the current .gitignore
"""
- invalid = cli.run(['git', 'ls-files', '-c', '-o', '-i', '--exclude-standard', check_dir])
+ invalid = cli.run(['git', 'ls-files', '-c', '-o', '-i', '--exclude-from=.gitignore', check_dir])
if invalid.returncode != 0:
return []
return invalid.stdout.strip().splitlines()
diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py
index 23761d71b7..d308de9db8 100644
--- a/lib/python/qmk/info.py
+++ b/lib/python/qmk/info.py
@@ -218,6 +218,62 @@ def _extract_audio(info_data, config_c):
info_data['audio'] = {'pins': audio_pins}
+def _extract_encoders_values(config_c, postfix=''):
+ """Common encoder extraction logic
+ """
+ a_pad = config_c.get(f'ENCODERS_PAD_A{postfix}', '').replace(' ', '')[1:-1]
+ b_pad = config_c.get(f'ENCODERS_PAD_B{postfix}', '').replace(' ', '')[1:-1]
+ resolutions = config_c.get(f'ENCODER_RESOLUTIONS{postfix}', '').replace(' ', '')[1:-1]
+
+ default_resolution = config_c.get('ENCODER_RESOLUTION', '4')
+
+ if a_pad and b_pad:
+ a_pad = list(filter(None, a_pad.split(',')))
+ b_pad = list(filter(None, b_pad.split(',')))
+ resolutions = list(filter(None, resolutions.split(',')))
+ resolutions += [default_resolution] * (len(a_pad) - len(resolutions))
+
+ encoders = []
+ for index in range(len(a_pad)):
+ encoders.append({'pin_a': a_pad[index], 'pin_b': b_pad[index], "resolution": int(resolutions[index])})
+
+ return encoders
+
+
+def _extract_encoders(info_data, config_c):
+ """Populate data about encoder pins
+ """
+ encoders = _extract_encoders_values(config_c)
+ if encoders:
+ if 'encoder' not in info_data:
+ info_data['encoder'] = {}
+
+ if 'rotary' in info_data['encoder']:
+ _log_warning(info_data, 'Encoder config is specified in both config.h and info.json (encoder.rotary) (Value: %s), the config.h value wins.' % info_data['encoder']['rotary'])
+
+ info_data['encoder']['rotary'] = encoders
+
+
+def _extract_split_encoders(info_data, config_c):
+ """Populate data about split encoder pins
+ """
+ encoders = _extract_encoders_values(config_c, '_RIGHT')
+ if encoders:
+ if 'split' not in info_data:
+ info_data['split'] = {}
+
+ if 'encoder' not in info_data['split']:
+ info_data['split']['encoder'] = {}
+
+ if 'right' not in info_data['split']['encoder']:
+ info_data['split']['encoder']['right'] = {}
+
+ if 'rotary' in info_data['split']['encoder']['right']:
+ _log_warning(info_data, 'Encoder config is specified in both config.h and info.json (encoder.rotary) (Value: %s), the config.h value wins.' % info_data['split']['encoder']['right']['rotary'])
+
+ info_data['split']['encoder']['right']['rotary'] = encoders
+
+
def _extract_secure_unlock(info_data, config_c):
"""Populate data about the secure unlock sequence
"""
@@ -506,6 +562,8 @@ def _extract_config_h(info_data, config_c):
_extract_split_main(info_data, config_c)
_extract_split_transport(info_data, config_c)
_extract_split_right_pins(info_data, config_c)
+ _extract_encoders(info_data, config_c)
+ _extract_split_encoders(info_data, config_c)
_extract_device_version(info_data)
return info_data
diff --git a/lib/python/qmk/json_schema.py b/lib/python/qmk/json_schema.py
index 682346113e..01175146b5 100644
--- a/lib/python/qmk/json_schema.py
+++ b/lib/python/qmk/json_schema.py
@@ -68,11 +68,7 @@ def create_validator(schema):
schema_store = compile_schema_store()
resolver = jsonschema.RefResolver.from_schema(schema_store[schema], store=schema_store)
- # TODO: Remove this after the jsonschema>=4 requirement had time to reach users
- try:
- return jsonschema.Draft202012Validator(schema_store[schema], resolver=resolver).validate
- except AttributeError:
- return jsonschema.Draft7Validator(schema_store[schema], resolver=resolver).validate
+ return jsonschema.Draft202012Validator(schema_store[schema], resolver=resolver).validate
def validate(data, schema):
diff --git a/lib/vusb b/lib/vusb
-Subproject bdb53e4c043d089279d9891b68bea77614cb97e
+Subproject 819dbc1e5d5926b17e27e00ca6d3d2988adae04
diff --git a/platforms/arm_atsam/platform.mk b/platforms/arm_atsam/platform.mk
index b49bf764d7..9618838dc3 100644
--- a/platforms/arm_atsam/platform.mk
+++ b/platforms/arm_atsam/platform.mk
@@ -30,7 +30,7 @@ COMPILEFLAGS += -mthumb
CFLAGS += $(COMPILEFLAGS)
CXXFLAGS += $(COMPILEFLAGS)
-CXXFLAGS += -fno-exceptions -std=c++11
+CXXFLAGS += -fno-exceptions $(CXXSTANDARD)
LDFLAGS +=-Wl,--gc-sections
LDFLAGS += -Wl,-Map="%OUT%%PROJ_NAME%.map"
diff --git a/platforms/avr/drivers/i2c_master.c b/platforms/avr/drivers/i2c_master.c
index c1a7b5f72d..524494c99d 100644
--- a/platforms/avr/drivers/i2c_master.c
+++ b/platforms/avr/drivers/i2c_master.c
@@ -64,7 +64,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
uint16_t timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
+ if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
return I2C_STATUS_TIMEOUT;
}
}
@@ -81,7 +81,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
+ if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
return I2C_STATUS_TIMEOUT;
}
}
@@ -102,7 +102,7 @@ i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
i2c_status_t status;
do {
status = i2c_start_impl(address, time_slice);
- } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) < timeout)));
+ } while ((status < 0) && ((timeout == I2C_TIMEOUT_INFINITE) || (timer_elapsed(timeout_timer) <= timeout)));
return status;
}
@@ -114,7 +114,7 @@ i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
uint16_t timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
+ if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
return I2C_STATUS_TIMEOUT;
}
}
@@ -132,7 +132,7 @@ int16_t i2c_read_ack(uint16_t timeout) {
uint16_t timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
+ if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
return I2C_STATUS_TIMEOUT;
}
}
@@ -147,7 +147,7 @@ int16_t i2c_read_nack(uint16_t timeout) {
uint16_t timeout_timer = timer_read();
while (!(TWCR & (1 << TWINT))) {
- if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
+ if ((timeout != I2C_TIMEOUT_INFINITE) && (timer_elapsed(timeout_timer) > timeout)) {
return I2C_STATUS_TIMEOUT;
}
}
diff --git a/platforms/avr/drivers/ps2/ps2_usart.c b/platforms/avr/drivers/ps2/ps2_usart.c
index 39ec930d4a..581badac64 100644
--- a/platforms/avr/drivers/ps2/ps2_usart.c
+++ b/platforms/avr/drivers/ps2/ps2_usart.c
@@ -72,8 +72,8 @@ uint8_t ps2_error = PS2_ERR_NONE;
static inline uint8_t pbuf_dequeue(void);
static inline void pbuf_enqueue(uint8_t data);
-static inline bool pbuf_has_data(void);
static inline void pbuf_clear(void);
+bool pbuf_has_data(void);
void ps2_host_init(void) {
idle(); // without this many USART errors occur when cable is disconnected
@@ -212,7 +212,7 @@ static inline uint8_t pbuf_dequeue(void) {
return val;
}
-static inline bool pbuf_has_data(void) {
+bool pbuf_has_data(void) {
uint8_t sreg = SREG;
cli();
bool has_data = (pbuf_head != pbuf_tail);
diff --git a/platforms/avr/platform.mk b/platforms/avr/platform.mk
index 978199b385..b51a94c93a 100644
--- a/platforms/avr/platform.mk
+++ b/platforms/avr/platform.mk
@@ -38,7 +38,7 @@ CFLAGS += -fno-inline-small-functions
CFLAGS += -fno-strict-aliasing
CXXFLAGS += $(COMPILEFLAGS)
-CXXFLAGS += -fno-exceptions -std=c++11
+CXXFLAGS += -fno-exceptions $(CXXSTANDARD)
LDFLAGS += -Wl,--gc-sections
diff --git a/platforms/chibios/_pin_defs.h b/platforms/chibios/_pin_defs.h
index 0d96e2fc3b..414c9e3d11 100644
--- a/platforms/chibios/_pin_defs.h
+++ b/platforms/chibios/_pin_defs.h
@@ -21,6 +21,11 @@
# include <hal.h>
#endif
+/* Include the vendor specific pin defs */
+#if __has_include_next("_pin_defs.h")
+# include_next "_pin_defs.h"
+#endif
+
#define A0 PAL_LINE(GPIOA, 0)
#define A1 PAL_LINE(GPIOA, 1)
#define A2 PAL_LINE(GPIOA, 2)
diff --git a/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/board/board.mk b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/board/board.mk
new file mode 100644
index 0000000000..911cc5a058
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/board/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/RP_PICO_RP2040/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/RP_PICO_RP2040
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/board.h b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/board.h
new file mode 100644
index 0000000000..b4363595d0
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/board.h
@@ -0,0 +1,12 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include_next "board.h"
+
+#undef BOARD_RP_PICO_RP2040
+#define BOARD_GENERIC_PROMICRO_RP2040
+
+#undef BOARD_NAME
+#define BOARD_NAME "Pro Micro RP2040"
diff --git a/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/chconf.h b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/chconf.h
new file mode 100644
index 0000000000..d53f57edd9
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/chconf.h
@@ -0,0 +1,13 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#define CH_CFG_SMP_MODE TRUE
+#define CH_CFG_ST_RESOLUTION 32
+#define CH_CFG_ST_FREQUENCY 1000000
+#define CH_CFG_INTERVALS_SIZE 32
+#define CH_CFG_TIME_TYPES_SIZE 32
+#define CH_CFG_ST_TIMEDELTA 20
+
+#include_next <chconf.h>
diff --git a/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h
new file mode 100644
index 0000000000..7fe9b654e1
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h
@@ -0,0 +1,62 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+/**======================
+ ** I2C Driver
+ *========================**/
+
+#if !defined(I2C_DRIVER)
+# define I2C_DRIVER I2CD2
+#endif
+
+#if !defined(I2C1_SDA_PIN)
+# define I2C1_SDA_PIN GP2
+#endif
+
+#if !defined(I2C1_SCL_PIN)
+# define I2C1_SCL_PIN GP3
+#endif
+
+/**======================
+ ** SPI Driver
+ *========================**/
+
+#if !defined(SPI_DRIVER)
+# define SPI_DRIVER SPID0
+#endif
+
+#if !defined(SPI_SCK_PIN)
+# define SPI_SCK_PIN GP18
+#endif
+
+#if !defined(SPI_MISO_PIN)
+# define SPI_MISO_PIN GP20
+#endif
+
+#if !defined(SPI_MOSI_PIN)
+# define SPI_MOSI_PIN GP19
+#endif
+
+/**======================
+ ** SERIAL Driver
+ *========================**/
+
+#if !defined(SERIAL_USART_DRIVER)
+# define SERIAL_USART_DRIVER SIOD0
+#endif
+
+#if !defined(SERIAL_USART_TX_PIN) && !defined(SOFT_SERIAL_PIN)
+# define SERIAL_USART_TX_PIN GP0
+#endif
+
+#if !defined(SERIAL_USART_RX_PIN)
+# define SERIAL_USART_RX_PIN GP1
+#endif
+
+/**======================
+ ** Double-tap
+ *========================**/
+
+#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
diff --git a/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/mcuconf.h
new file mode 100644
index 0000000000..8348e5312f
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/mcuconf.h
@@ -0,0 +1,98 @@
+/*
+ ChibiOS - Copyright (C) 2006..2021 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef MCUCONF_H
+#define MCUCONF_H
+
+/*
+ * RP2040_MCUCONF drivers configuration.
+ *
+ * IRQ priorities:
+ * 3...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...1 Lowest...Highest.
+ */
+
+#define RP2040_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+#define RP_NO_INIT FALSE
+#define RP_CORE1_START FALSE
+#define RP_CORE1_VECTORS_TABLE _vectors
+#define RP_CORE1_ENTRY_POINT _crt0_c1_entry
+#define RP_CORE1_STACK_END __c1_main_stack_end__
+
+/*
+ * IRQ system settings.
+ */
+#define RP_IRQ_SYSTICK_PRIORITY 2
+#define RP_IRQ_TIMER_ALARM0_PRIORITY 2
+#define RP_IRQ_TIMER_ALARM1_PRIORITY 2
+#define RP_IRQ_TIMER_ALARM2_PRIORITY 2
+#define RP_IRQ_TIMER_ALARM3_PRIORITY 2
+#define RP_IRQ_UART0_PRIORITY 3
+#define RP_IRQ_UART1_PRIORITY 3
+#define RP_IRQ_SPI0_PRIORITY 2
+#define RP_IRQ_SPI1_PRIORITY 2
+#define RP_IRQ_USB0_PRIORITY 3
+#define RP_IRQ_I2C0_PRIORITY 2
+#define RP_IRQ_I2C1_PRIORITY 2
+
+/*
+ * ADC driver system settings.
+ */
+#define RP_ADC_USE_ADC1 FALSE
+
+/*
+ * SIO driver system settings.
+ */
+#define RP_SIO_USE_UART0 TRUE
+#define RP_SIO_USE_UART1 FALSE
+
+/*
+ * SPI driver system settings.
+ */
+#define RP_SPI_USE_SPI0 TRUE
+#define RP_SPI_USE_SPI1 FALSE
+#define RP_SPI_SPI0_RX_DMA_CHANNEL RP_DMA_CHANNEL_ID_ANY
+#define RP_SPI_SPI0_TX_DMA_CHANNEL RP_DMA_CHANNEL_ID_ANY
+#define RP_SPI_SPI1_RX_DMA_CHANNEL RP_DMA_CHANNEL_ID_ANY
+#define RP_SPI_SPI1_TX_DMA_CHANNEL RP_DMA_CHANNEL_ID_ANY
+#define RP_SPI_SPI0_DMA_PRIORITY 1
+#define RP_SPI_SPI1_DMA_PRIORITY 1
+#define RP_SPI_DMA_ERROR_HOOK(spip)
+
+/*
+ * I2C driver system settings.
+ */
+#define RP_I2C_USE_I2C0 FALSE
+#define RP_I2C_USE_I2C1 TRUE
+#define RP_I2C_BUSY_TIMEOUT 50
+#define RP_I2C_ADDRESS_MODE_10BIT FALSE
+
+/*
+ * USB driver system settings.
+ */
+#define RP_USB_USE_USBD0 TRUE
+#define RP_USB_FORCE_VBUS_DETECT TRUE
+#define RP_USE_EXTERNAL_VBUS_DETECT FALSE
+#define RP_USB_USE_SOF_INTR TRUE
+#define RP_USB_USE_ERROR_DATA_SEQ_INTR FALSE
+
+#endif /* MCUCONF_H */
diff --git a/platforms/chibios/boards/GENERIC_RP_RP2040/board/board.mk b/platforms/chibios/boards/GENERIC_RP_RP2040/board/board.mk
new file mode 100644
index 0000000000..911cc5a058
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_RP_RP2040/board/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/RP_PICO_RP2040/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/RP_PICO_RP2040
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/platforms/chibios/boards/GENERIC_RP_RP2040/configs/board.h b/platforms/chibios/boards/GENERIC_RP_RP2040/configs/board.h
new file mode 100644
index 0000000000..052050c944
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_RP_RP2040/configs/board.h
@@ -0,0 +1,12 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include_next "board.h"
+
+#undef BOARD_RP_PICO_RP2040
+#define BOARD_GENERIC_RP2040
+
+#undef BOARD_NAME
+#define BOARD_NAME "Generic Raspberry Pi RP2040"
diff --git a/platforms/chibios/boards/GENERIC_RP_RP2040/configs/chconf.h b/platforms/chibios/boards/GENERIC_RP_RP2040/configs/chconf.h
new file mode 100644
index 0000000000..d53f57edd9
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_RP_RP2040/configs/chconf.h
@@ -0,0 +1,13 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#define CH_CFG_SMP_MODE TRUE
+#define CH_CFG_ST_RESOLUTION 32
+#define CH_CFG_ST_FREQUENCY 1000000
+#define CH_CFG_INTERVALS_SIZE 32
+#define CH_CFG_TIME_TYPES_SIZE 32
+#define CH_CFG_ST_TIMEDELTA 20
+
+#include_next <chconf.h>
diff --git a/platforms/chibios/boards/GENERIC_RP_RP2040/configs/mcuconf.h b/platforms/chibios/boards/GENERIC_RP_RP2040/configs/mcuconf.h
new file mode 100644
index 0000000000..9d8dc61aac
--- /dev/null
+++ b/platforms/chibios/boards/GENERIC_RP_RP2040/configs/mcuconf.h
@@ -0,0 +1,98 @@
+/*
+ ChibiOS - Copyright (C) 2006..2021 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef MCUCONF_H
+#define MCUCONF_H
+
+/*
+ * RP2040_MCUCONF drivers configuration.
+ *
+ * IRQ priorities:
+ * 3...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...1 Lowest...Highest.
+ */
+
+#define RP2040_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+#define RP_NO_INIT FALSE
+#define RP_CORE1_START FALSE
+#define RP_CORE1_VECTORS_TABLE _vectors
+#define RP_CORE1_ENTRY_POINT _crt0_c1_entry
+#define RP_CORE1_STACK_END __c1_main_stack_end__
+
+/*
+ * IRQ system settings.
+ */
+#define RP_IRQ_SYSTICK_PRIORITY 2
+#define RP_IRQ_TIMER_ALARM0_PRIORITY 2
+#define RP_IRQ_TIMER_ALARM1_PRIORITY 2
+#define RP_IRQ_TIMER_ALARM2_PRIORITY 2
+#define RP_IRQ_TIMER_ALARM3_PRIORITY 2
+#define RP_IRQ_UART0_PRIORITY 3
+#define RP_IRQ_UART1_PRIORITY 3
+#define RP_IRQ_SPI0_PRIORITY 2
+#define RP_IRQ_SPI1_PRIORITY 2
+#define RP_IRQ_USB0_PRIORITY 3
+#define RP_IRQ_I2C0_PRIORITY 2
+#define RP_IRQ_I2C1_PRIORITY 2
+
+/*
+ * ADC driver system settings.
+ */
+#define RP_ADC_USE_ADC1 FALSE
+
+/*
+ * SIO driver system settings.
+ */
+#define RP_SIO_USE_UART0 FALSE
+#define RP_SIO_USE_UART1 FALSE
+
+/*
+ * SPI driver system settings.
+ */
+#define RP_SPI_USE_SPI0 FALSE
+#define RP_SPI_USE_SPI1 FALSE
+#define RP_SPI_SPI0_RX_DMA_CHANNEL RP_DMA_CHANNEL_ID_ANY
+#define RP_SPI_SPI0_TX_DMA_CHANNEL RP_DMA_CHANNEL_ID_ANY
+#define RP_SPI_SPI1_RX_DMA_CHANNEL RP_DMA_CHANNEL_ID_ANY
+#define RP_SPI_SPI1_TX_DMA_CHANNEL RP_DMA_CHANNEL_ID_ANY
+#define RP_SPI_SPI0_DMA_PRIORITY 1
+#define RP_SPI_SPI1_DMA_PRIORITY 1
+#define RP_SPI_DMA_ERROR_HOOK(spip)
+
+/*
+ * I2C driver system settings.
+ */
+#define RP_I2C_USE_I2C0 FALSE
+#define RP_I2C_USE_I2C1 FALSE
+#define RP_I2C_BUSY_TIMEOUT 50
+#define RP_I2C_ADDRESS_MODE_10BIT FALSE
+
+/*
+ * USB driver system settings.
+ */
+#define RP_USB_USE_USBD0 TRUE
+#define RP_USB_FORCE_VBUS_DETECT TRUE
+#define RP_USE_EXTERNAL_VBUS_DETECT FALSE
+#define RP_USB_USE_SOF_INTR TRUE
+#define RP_USB_USE_ERROR_DATA_SEQ_INTR FALSE
+
+#endif /* MCUCONF_H */
diff --git a/platforms/chibios/boards/common/ld/RP2040_FLASH_TIMECRIT.ld b/platforms/chibios/boards/common/ld/RP2040_FLASH_TIMECRIT.ld
new file mode 100644
index 0000000000..66ed4ce086
--- /dev/null
+++ b/platforms/chibios/boards/common/ld/RP2040_FLASH_TIMECRIT.ld
@@ -0,0 +1,117 @@
+/*
+ ChibiOS - Copyright (C) 2006..2021 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * RP2040 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x00000000, len = 16k /* ROM */
+ flash1 (rx) : org = 0x10000000, len = DEFINED(FLASH_LEN) ? FLASH_LEN : 2048k /* XIP */
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 256k /* SRAM0 striped */
+ ram1 (wx) : org = 0x00000000, len = 256k /* SRAM0 non striped */
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x20040000, len = 4k /* SRAM4 */
+ ram5 (wx) : org = 0x20041000, len = 4k /* SRAM5 */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x20041f00, len = 256 /* SRAM5 boot */
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash1);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash1);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash1);
+REGION_ALIAS("XTORS_FLASH_LMA", flash1);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash1);
+REGION_ALIAS("TEXT_FLASH_LMA", flash1);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash1);
+REGION_ALIAS("RODATA_FLASH_LMA", flash1);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash1);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash1);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash1);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram4);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram4);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("C1_MAIN_STACK_RAM", ram5);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("C1_PROCESS_STACK_RAM", ram5);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash1);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+SECTIONS
+{
+ .flash_begin : {
+ __flash_binary_start = .;
+ } > flash1
+
+ .boot2 : {
+ __boot2_start__ = .;
+ KEEP (*(.boot2))
+ __boot2_end__ = .;
+ } > flash1
+}
+
+/* Generic rules inclusion.*/
+INCLUDE rules_stacks.ld
+INCLUDE rules_stacks_c1.ld
+INCLUDE RP2040_rules_code_with_boot2.ld
+INCLUDE RP2040_rules_data_with_timecrit.ld
+INCLUDE rules_memory.ld
+
+SECTIONS
+{
+ .flash_end : {
+ __flash_binary_end = .;
+ } > flash1
+}
diff --git a/platforms/chibios/boards/common/ld/RP2040_rules_data_with_timecrit.ld b/platforms/chibios/boards/common/ld/RP2040_rules_data_with_timecrit.ld
new file mode 100644
index 0000000000..a9a47be983
--- /dev/null
+++ b/platforms/chibios/boards/common/ld/RP2040_rules_data_with_timecrit.ld
@@ -0,0 +1,46 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+SECTIONS
+{
+ .data : ALIGN(4)
+ {
+ PROVIDE(_textdata = LOADADDR(.data));
+ PROVIDE(_data = .);
+ __textdata_base__ = LOADADDR(.data);
+ __data_base__ = .;
+ *(vtable)
+ *(.time_critical*)
+ . = ALIGN(4);
+ *(.data)
+ *(.data.*)
+ *(.ramtext)
+ . = ALIGN(4);
+ PROVIDE(_edata = .);
+ __data_end__ = .;
+ } > DATA_RAM AT > DATA_RAM_LMA
+
+ .bss (NOLOAD) : ALIGN(4)
+ {
+ __bss_base__ = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ PROVIDE(end = .);
+ } > BSS_RAM
+}
diff --git a/platforms/chibios/bootloaders/rp2040.c b/platforms/chibios/bootloaders/rp2040.c
new file mode 100644
index 0000000000..13a54036ef
--- /dev/null
+++ b/platforms/chibios/bootloaders/rp2040.c
@@ -0,0 +1,57 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "quantum.h"
+#include "hal.h"
+#include "bootloader.h"
+#include "pico/bootrom.h"
+
+#if !defined(RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED)
+# define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED_MASK 0U
+#else
+# define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED_MASK (1U << RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED)
+#endif
+
+__attribute__((weak)) void mcu_reset(void) {
+ NVIC_SystemReset();
+}
+void bootloader_jump(void) {
+ reset_usb_boot(RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED_MASK, 0U);
+}
+
+void enter_bootloader_mode_if_requested(void) {}
+
+#if defined(RP2040_BOOTLOADER_DOUBLE_TAP_RESET)
+# if !defined(RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT)
+# define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 200U
+# endif
+
+// Needs to be located in a RAM section that is never initialized on boot to
+// preserve its value on reset
+static volatile uint32_t __attribute__((section(".ram0.bootloader_magic"))) magic_location;
+const uint32_t magic_token = 0xCAFEB0BA;
+
+// We can not use the __early_init / enter_bootloader_mode_if_requested hook as
+// we depend on an already initialized system with usable memory regions and
+// populated function pointer tables to the optimized math functions in the
+// bootrom. This function is called just prior to main.
+void __late_init(void) {
+ // All clocks have to be enabled before jumping to the bootloader function,
+ // otherwise the bootrom will be stuck infinitely.
+ clocks_init();
+
+ if (magic_location != magic_token) {
+ magic_location = magic_token;
+ // ChibiOS is not initialized at this point, so sleeping is only
+ // possible via busy waiting. The internal timer peripheral is running
+ // at this point with a precision of 1us.
+ chSysPolledDelayX(MS2RTC(1 * MHZ, RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT));
+ magic_location = 0;
+ return;
+ }
+
+ magic_location = 0;
+ reset_usb_boot(RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED_MASK, 0U);
+}
+
+#endif
diff --git a/platforms/chibios/bootloaders/stm32_dfu.c b/platforms/chibios/bootloaders/stm32_dfu.c
index ff866bd2bc..7b4ab86033 100644
--- a/platforms/chibios/bootloaders/stm32_dfu.c
+++ b/platforms/chibios/bootloaders/stm32_dfu.c
@@ -38,7 +38,7 @@ extern uint32_t __ram0_end__;
# endif
# ifndef STM32_BOOTLOADER_DUAL_BANK_DELAY
-# define STM32_BOOTLOADER_DUAL_BANK_DELAY 100000
+# define STM32_BOOTLOADER_DUAL_BANK_DELAY 100
# endif
__attribute__((weak)) void bootloader_jump(void) {
@@ -55,7 +55,7 @@ __attribute__((weak)) void bootloader_jump(void) {
# endif
// Wait for a while for the capacitor to charge
- wait_ms(100);
+ wait_ms(STM32_BOOTLOADER_DUAL_BANK_DELAY);
// Issue a system reset to get the ROM bootloader to execute, with BOOT0 high
NVIC_SystemReset();
diff --git a/platforms/chibios/chibios_config.h b/platforms/chibios/chibios_config.h
index a7098f2713..1571bd5cd3 100644
--- a/platforms/chibios/chibios_config.h
+++ b/platforms/chibios/chibios_config.h
@@ -19,6 +19,27 @@
# define SPLIT_USB_DETECT // Force this on when dedicated pin is not used
#endif
+#if defined(MCU_RP)
+# define CPU_CLOCK RP_CORE_CLK
+
+# define USE_GPIOV1
+# define PAL_OUTPUT_TYPE_OPENDRAIN _Static_assert(0, "RP2040 has no Open Drain GPIO configuration, setting this is not possible");
+
+# define usb_lld_endpoint_fields
+
+# define I2C1_SCL_PAL_MODE (PAL_MODE_ALTERNATE_I2C | PAL_RP_PAD_SLEWFAST | PAL_RP_PAD_PUE | PAL_RP_PAD_DRIVE4)
+# define I2C1_SDA_PAL_MODE I2C1_SCL_PAL_MODE
+
+# define USE_I2CV1_CONTRIB
+# if !defined(I2C1_CLOCK_SPEED)
+# define I2C1_CLOCK_SPEED 400000
+# endif
+
+# define SPI_SCK_PAL_MODE (PAL_MODE_ALTERNATE_SPI | PAL_RP_PAD_SLEWFAST | PAL_RP_PAD_DRIVE4)
+# define SPI_MOSI_PAL_MODE SPI_SCK_PAL_MODE
+# define SPI_MISO_PAL_MODE SPI_SCK_PAL_MODE
+#endif
+
// STM32 compatibility
#if defined(MCU_STM32)
# define CPU_CLOCK STM32_SYSCLK
diff --git a/platforms/chibios/eeprom_stm32.c b/platforms/chibios/drivers/eeprom/eeprom_stm32.c
index a15bfe09ed..a15bfe09ed 100644
--- a/platforms/chibios/eeprom_stm32.c
+++ b/platforms/chibios/drivers/eeprom/eeprom_stm32.c
diff --git a/platforms/chibios/eeprom_stm32.h b/platforms/chibios/drivers/eeprom/eeprom_stm32.h
index 8fcfb556b8..8fcfb556b8 100644
--- a/platforms/chibios/eeprom_stm32.h
+++ b/platforms/chibios/drivers/eeprom/eeprom_stm32.h
diff --git a/platforms/chibios/eeprom_stm32_defs.h b/platforms/chibios/drivers/eeprom/eeprom_stm32_defs.h
index 57d0440330..57d0440330 100644
--- a/platforms/chibios/eeprom_stm32_defs.h
+++ b/platforms/chibios/drivers/eeprom/eeprom_stm32_defs.h
diff --git a/platforms/chibios/eeprom_teensy.c b/platforms/chibios/drivers/eeprom/eeprom_teensy.c
index c8777febde..c8777febde 100644
--- a/platforms/chibios/eeprom_teensy.c
+++ b/platforms/chibios/drivers/eeprom/eeprom_teensy.c
diff --git a/platforms/chibios/eeprom_teensy.h b/platforms/chibios/drivers/eeprom/eeprom_teensy.h
index 9a14a1fa79..9a14a1fa79 100755
--- a/platforms/chibios/eeprom_teensy.h
+++ b/platforms/chibios/drivers/eeprom/eeprom_teensy.h
diff --git a/platforms/chibios/flash_stm32.c b/platforms/chibios/drivers/flash/flash_stm32.c
index 72c41b8b78..72c41b8b78 100644
--- a/platforms/chibios/flash_stm32.c
+++ b/platforms/chibios/drivers/flash/flash_stm32.c
diff --git a/platforms/chibios/flash_stm32.h b/platforms/chibios/drivers/flash/flash_stm32.h
index 6c66642ec5..6c66642ec5 100644
--- a/platforms/chibios/flash_stm32.h
+++ b/platforms/chibios/drivers/flash/flash_stm32.h
diff --git a/platforms/chibios/drivers/serial.c b/platforms/chibios/drivers/serial.c
index 0cff057d1d..3fae5cd3a4 100644
--- a/platforms/chibios/drivers/serial.c
+++ b/platforms/chibios/drivers/serial.c
@@ -87,10 +87,7 @@ static THD_FUNCTION(Thread1, arg) {
chRegSetThreadName("blinker");
while (true) {
palWaitLineTimeout(SOFT_SERIAL_PIN, TIME_INFINITE);
-
- split_shared_memory_lock();
interrupt_handler(NULL);
- split_shared_memory_unlock();
}
}
@@ -155,6 +152,7 @@ static void __attribute__((noinline)) serial_write_byte(uint8_t data) {
// interrupt handle to be used by the slave device
void interrupt_handler(void *arg) {
+ split_shared_memory_lock_autounlock();
chSysLockFromISR();
sync_send();
@@ -212,6 +210,8 @@ void interrupt_handler(void *arg) {
static inline bool initiate_transaction(uint8_t sstd_index) {
if (sstd_index > NUM_TOTAL_TRANSACTIONS) return false;
+ split_shared_memory_lock_autounlock();
+
split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
// TODO: remove extra delay between transactions
@@ -233,7 +233,7 @@ static inline bool initiate_transaction(uint8_t sstd_index) {
// check if the slave is present
if (serial_read_pin()) {
// slave failed to pull the line low, assume not present
- dprintf("serial::NO_RESPONSE\n");
+ serial_dprintf("serial::NO_RESPONSE\n");
chSysUnlock();
return false;
}
@@ -269,7 +269,7 @@ static inline bool initiate_transaction(uint8_t sstd_index) {
serial_delay();
if ((checksum_computed) != (checksum_received)) {
- dprintf("serial::FAIL[%u,%u,%u]\n", checksum_computed, checksum_received, sstd_index);
+ serial_dprintf("serial::FAIL[%u,%u,%u]\n", checksum_computed, checksum_received, sstd_index);
serial_output();
serial_high();
@@ -292,8 +292,5 @@ static inline bool initiate_transaction(uint8_t sstd_index) {
//
// this code is very time dependent, so we need to disable interrupts
bool soft_serial_transaction(int sstd_index) {
- split_shared_memory_lock();
- bool result = initiate_transaction((uint8_t)sstd_index);
- split_shared_memory_unlock();
- return result;
+ return initiate_transaction((uint8_t)sstd_index);
}
diff --git a/platforms/chibios/drivers/serial_protocol.c b/platforms/chibios/drivers/serial_protocol.c
new file mode 100644
index 0000000000..c95aed9885
--- /dev/null
+++ b/platforms/chibios/drivers/serial_protocol.c
@@ -0,0 +1,164 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <ch.h>
+
+#include "quantum.h"
+#include "serial.h"
+#include "serial_protocol.h"
+#include "printf.h"
+#include "synchronization_util.h"
+
+static inline bool initiate_transaction(uint8_t transaction_id);
+static inline bool react_to_transaction(void);
+
+/**
+ * @brief This thread runs on the slave and responds to transactions initiated
+ * by the master.
+ */
+static THD_WORKING_AREA(waSlaveThread, 1024);
+static THD_FUNCTION(SlaveThread, arg) {
+ (void)arg;
+ chRegSetThreadName("split_protocol_tx_rx");
+
+ while (true) {
+ if (unlikely(!react_to_transaction())) {
+ /* Clear the receive queue, to start with a clean slate.
+ * Parts of failed transactions or spurious bytes could still be in it. */
+ serial_transport_driver_clear();
+ }
+ }
+}
+
+/**
+ * @brief Slave specific initializations.
+ */
+void soft_serial_target_init(void) {
+ serial_transport_driver_slave_init();
+
+ /* Start transport thread. */
+ chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL);
+}
+
+/**
+ * @brief Master specific initializations.
+ */
+void soft_serial_initiator_init(void) {
+ serial_transport_driver_master_init();
+}
+
+/**
+ * @brief React to transactions started by the master.
+ */
+static inline bool react_to_transaction(void) {
+ uint8_t transaction_id = 0;
+ /* Wait until there is a transaction for us. */
+ if (unlikely(!serial_transport_receive_blocking(&transaction_id, sizeof(transaction_id)))) {
+ return false;
+ }
+
+ /* Sanity check that we are actually responding to a valid transaction. */
+ if (unlikely(transaction_id >= NUM_TOTAL_TRANSACTIONS)) {
+ return false;
+ }
+
+ split_shared_memory_lock_autounlock();
+
+ split_transaction_desc_t* transaction = &split_transaction_table[transaction_id];
+
+ /* Send back the handshake which is XORed as a simple checksum,
+ to signal that the slave is ready to receive possible transaction buffers */
+ transaction_id ^= NUM_TOTAL_TRANSACTIONS;
+ if (unlikely(!serial_transport_send(&transaction_id, sizeof(transaction_id)))) {
+ return false;
+ }
+
+ /* Receive transaction buffer from the master. If this transaction requires it.*/
+ if (transaction->initiator2target_buffer_size) {
+ if (unlikely(!serial_transport_receive(split_trans_initiator2target_buffer(transaction), transaction->initiator2target_buffer_size))) {
+ return false;
+ }
+ }
+
+ /* Allow any slave processing to occur. */
+ if (transaction->slave_callback) {
+ transaction->slave_callback(transaction->initiator2target_buffer_size, split_trans_initiator2target_buffer(transaction), transaction->initiator2target_buffer_size, split_trans_target2initiator_buffer(transaction));
+ }
+
+ /* Send transaction buffer to the master. If this transaction requires it. */
+ if (transaction->target2initiator_buffer_size) {
+ if (unlikely(!serial_transport_send(split_trans_target2initiator_buffer(transaction), transaction->target2initiator_buffer_size))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * @brief Start transaction from the master half to the slave half.
+ *
+ * @param index Transaction Table index of the transaction to start.
+ * @return bool Indicates success of transaction.
+ */
+bool soft_serial_transaction(int index) {
+ bool result = initiate_transaction((uint8_t)index);
+
+ if (unlikely(!result)) {
+ /* Clear the receive queue, to start with a clean slate.
+ * Parts of failed transactions or spurious bytes could still be in it. */
+ serial_transport_driver_clear();
+ }
+
+ return result;
+}
+
+/**
+ * @brief Initiate transaction to slave half.
+ */
+static inline bool initiate_transaction(uint8_t transaction_id) {
+ /* Sanity check that we are actually starting a valid transaction. */
+ if (unlikely(transaction_id >= NUM_TOTAL_TRANSACTIONS)) {
+ serial_dprintf("SPLIT: illegal transaction id\n");
+ return false;
+ }
+
+ split_shared_memory_lock_autounlock();
+
+ split_transaction_desc_t* transaction = &split_transaction_table[transaction_id];
+
+ /* Send transaction table index to the slave, which doubles as basic handshake token. */
+ if (unlikely(!serial_transport_send(&transaction_id, sizeof(transaction_id)))) {
+ serial_dprintf("SPLIT: sending handshake failed\n");
+ return false;
+ }
+
+ uint8_t transaction_id_shake = 0xFF;
+
+ /* Which we always read back first so that we can error out correctly.
+ * - due to the half duplex limitations on return codes, we always have to read *something*.
+ * - without the read, write only transactions *always* succeed, even during the boot process where the slave is not ready.
+ */
+ if (unlikely(!serial_transport_receive(&transaction_id_shake, sizeof(transaction_id_shake)) || (transaction_id_shake != (transaction_id ^ NUM_TOTAL_TRANSACTIONS)))) {
+ serial_dprintf("SPLIT: receiving handshake failed\n");
+ return false;
+ }
+
+ /* Send transaction buffer to the slave. If this transaction requires it. */
+ if (transaction->initiator2target_buffer_size) {
+ if (unlikely(!serial_transport_send(split_trans_initiator2target_buffer(transaction), transaction->initiator2target_buffer_size))) {
+ serial_dprintf("SPLIT: sending buffer failed\n");
+ return false;
+ }
+ }
+
+ /* Receive transaction buffer from the slave. If this transaction requires it. */
+ if (transaction->target2initiator_buffer_size) {
+ if (unlikely(!serial_transport_receive(split_trans_target2initiator_buffer(transaction), transaction->target2initiator_buffer_size))) {
+ serial_dprintf("SPLIT: receiving buffer failed\n");
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/platforms/chibios/drivers/serial_protocol.h b/platforms/chibios/drivers/serial_protocol.h
new file mode 100644
index 0000000000..4275a7f8d8
--- /dev/null
+++ b/platforms/chibios/drivers/serial_protocol.h
@@ -0,0 +1,49 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#pragma once
+
+/**
+ * @brief Clears any intermediate sending or receiving state of the driver to a known good
+ * state. This happens after errors in the middle of transactions, to start with
+ * a clean slate.
+ */
+void serial_transport_driver_clear(void);
+
+/**
+ * @brief Driver specific initialization on the slave half.
+ */
+void serial_transport_driver_slave_init(void);
+
+/**
+ * @brief Driver specific specific initialization on the master half.
+ */
+void serial_transport_driver_master_init(void);
+
+/**
+ * @brief Blocking receive of size * bytes.
+ *
+ * @return true Receive success.
+ * @return false Receive failed, e.g. by bit errors.
+ */
+bool __attribute__((nonnull, hot)) serial_transport_receive(uint8_t* destination, const size_t size);
+
+/**
+ * @brief Blocking receive of size * bytes with an implicitly defined timeout.
+ *
+ * @return true Receive success.
+ * @return false Receive failed, e.g. by timeout or bit errors.
+ */
+bool __attribute__((nonnull, hot)) serial_transport_receive_blocking(uint8_t* destination, const size_t size);
+
+/**
+ * @brief Blocking send of buffer with timeout.
+ *
+ * @return true Send success.
+ * @return false Send failed, e.g. by timeout or bit errors.
+ */
+bool __attribute__((nonnull, hot)) serial_transport_send(const uint8_t* source, const size_t size);
diff --git a/platforms/chibios/drivers/serial_usart.c b/platforms/chibios/drivers/serial_usart.c
index e9fa4af7a3..6581a5b6e9 100644
--- a/platforms/chibios/drivers/serial_usart.c
+++ b/platforms/chibios/drivers/serial_usart.c
@@ -1,49 +1,55 @@
-/* Copyright 2021 QMK
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
+// Copyright 2021 QMK
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
#include "serial_usart.h"
+#include "serial_protocol.h"
#include "synchronization_util.h"
#if defined(SERIAL_USART_CONFIG)
-static SerialConfig serial_config = SERIAL_USART_CONFIG;
-#else
-static SerialConfig serial_config = {
- .speed = (SERIAL_USART_SPEED), /* speed - mandatory */
+static QMKSerialConfig serial_config = SERIAL_USART_CONFIG;
+#elif defined(MCU_STM32) /* STM32 MCUs */
+static QMKSerialConfig serial_config = {
+# if HAL_USE_SERIAL
+ .speed = (SERIAL_USART_SPEED),
+# else
+ .baud = (SERIAL_USART_SPEED),
+# endif
.cr1 = (SERIAL_USART_CR1),
.cr2 = (SERIAL_USART_CR2),
# if !defined(SERIAL_USART_FULL_DUPLEX)
.cr3 = ((SERIAL_USART_CR3) | USART_CR3_HDSEL) /* activate half-duplex mode */
# else
- .cr3 = (SERIAL_USART_CR3)
+ .cr3 = (SERIAL_USART_CR3)
# endif
};
+#elif defined(MCU_RP) /* Raspberry Pi MCUs */
+/* USART in 8E2 config with RX and TX FIFOs enabled. */
+// clang-format off
+static QMKSerialConfig serial_config = {
+ .baud = (SERIAL_USART_SPEED),
+ .UARTLCR_H = UART_UARTLCR_H_WLEN_8BITS | UART_UARTLCR_H_PEN | UART_UARTLCR_H_STP2 | UART_UARTLCR_H_FEN,
+ .UARTCR = 0U,
+ .UARTIFLS = UART_UARTIFLS_RXIFLSEL_1_8F | UART_UARTIFLS_TXIFLSEL_1_8E,
+ .UARTDMACR = 0U
+};
+// clang-format on
+#else
+# error MCU Familiy not supported by default, supply your own serial_config by defining SERIAL_USART_CONFIG in your keyboard files.
#endif
-static SerialDriver* serial_driver = &SERIAL_USART_DRIVER;
+static QMKSerialDriver* serial_driver = (QMKSerialDriver*)&SERIAL_USART_DRIVER;
-static inline bool react_to_transactions(void);
-static inline bool __attribute__((nonnull)) receive(uint8_t* destination, const size_t size);
-static inline bool __attribute__((nonnull)) send(const uint8_t* source, const size_t size);
-static inline bool initiate_transaction(uint8_t sstd_index);
-static inline void usart_clear(void);
+#if HAL_USE_SERIAL
/**
- * @brief Clear the receive input queue.
+ * @brief SERIAL Driver startup routine.
*/
-static inline void usart_clear(void) {
+static inline void usart_driver_start(void) {
+ sdStart(serial_driver, &serial_config);
+}
+
+inline void serial_transport_driver_clear(void) {
osalSysLock();
bool volatile queue_not_empty = !iqIsEmptyI(&serial_driver->iqueue);
osalSysUnlock();
@@ -64,36 +70,96 @@ static inline void usart_clear(void) {
}
}
+#elif HAL_USE_SIO
+
+void clear_rx_evt_cb(SIODriver* siop) {
+ osalSysLockFromISR();
+ /* If errors occured during transactions this callback is invoked. We just
+ * clear the error sources and move on. We rely on the fact that we check
+ * for the success of the transaction by comparing the received/send bytes
+ * with the actual received/send bytes in the send/receive functions. */
+ sioGetAndClearEventsI(serial_driver);
+ osalSysUnlockFromISR();
+}
+
+static const SIOOperation serial_usart_operation = {.rx_cb = NULL, .rx_idle_cb = NULL, .tx_cb = NULL, .tx_end_cb = NULL, .rx_evt_cb = &clear_rx_evt_cb};
+
/**
- * @brief Blocking send of buffer with timeout.
- *
- * @return true Send success.
- * @return false Send failed.
+ * @brief SIO Driver startup routine.
*/
-static inline bool send(const uint8_t* source, const size_t size) {
- bool success = (size_t)sdWriteTimeout(serial_driver, source, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size;
+static inline void usart_driver_start(void) {
+ sioStart(serial_driver, &serial_config);
+ sioStartOperation(serial_driver, &serial_usart_operation);
+}
+
+inline void serial_transport_driver_clear(void) {
+ osalSysLock();
+ while (!sioIsRXEmptyX(serial_driver)) {
+ (void)sioGetX(serial_driver);
+ }
+ osalSysUnlock();
+}
+
+#else
+
+# error Either the SERIAL or SIO driver has to be activated to use the usart driver for split keyboards.
+
+#endif
+
+inline bool serial_transport_send(const uint8_t* source, const size_t size) {
+ bool success = (size_t)chnWriteTimeout(serial_driver, source, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size;
#if !defined(SERIAL_USART_FULL_DUPLEX)
- if (success) {
- /* Half duplex fills the input queue with the data we wrote - just throw it away.
- Under the right circumstances (e.g. bad cables paired with high baud rates)
- less bytes can be present in the input queue, therefore a timeout is needed. */
- uint8_t dump[size];
- return receive(dump, size);
+ /* Half duplex fills the input queue with the data we wrote - just throw it away. */
+ if (likely(success)) {
+ size_t bytes_left = size;
+# if HAL_USE_SERIAL
+ /* The SERIAL driver uses large soft FIFOs that are filled from an IRQ
+ * context, so there is a delay between receiving the data and it
+ * becoming actually available, therefore we have to apply a timeout
+ * mechanism. Under the right circumstances (e.g. bad cables paired with
+ * high baud rates) less bytes can be present in the input queue as
+ * well. */
+ uint8_t dump[64];
+
+ while (unlikely(bytes_left >= 64)) {
+ if (unlikely(!serial_transport_receive(dump, 64))) {
+ return false;
+ }
+ bytes_left -= 64;
+ }
+
+ return serial_transport_receive(dump, bytes_left);
+# else
+ /* The SIO driver directly accesses the hardware FIFOs of the USART
+ * peripheral. As these are limited in depth, the RX FIFO might have been
+ * overflowed by a large that we just send. Therefore we attempt to read
+ * back all the data we send or until the FIFO runs empty in case it
+ * overflowed and data was truncated. */
+ if (unlikely(sioSynchronizeTXEnd(serial_driver, TIME_MS2I(SERIAL_USART_TIMEOUT)) < MSG_OK)) {
+ return false;
+ }
+
+ osalSysLock();
+ while (bytes_left > 0 && !sioIsRXEmptyX(serial_driver)) {
+ (void)sioGetX(serial_driver);
+ bytes_left--;
+ }
+ osalSysUnlock();
+# endif
}
#endif
return success;
}
-/**
- * @brief Blocking receive of size * bytes with timeout.
- *
- * @return true Receive success.
- * @return false Receive failed.
- */
-static inline bool receive(uint8_t* destination, const size_t size) {
- bool success = (size_t)sdReadTimeout(serial_driver, destination, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size;
+inline bool serial_transport_receive(uint8_t* destination, const size_t size) {
+ bool success = (size_t)chnReadTimeout(serial_driver, destination, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size;
+ return success;
+}
+
+inline bool serial_transport_receive_blocking(uint8_t* destination, const size_t size) {
+ bool success = (size_t)chnRead(serial_driver, destination, size) == size;
return success;
}
@@ -103,7 +169,7 @@ static inline bool receive(uint8_t* destination, const size_t size) {
* @brief Initiate pins for USART peripheral. Half-duplex configuration.
*/
__attribute__((weak)) void usart_init(void) {
-# if defined(MCU_STM32)
+# if defined(MCU_STM32) /* STM32 MCUs */
# if defined(USE_GPIOV1)
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_OPENDRAIN);
# else
@@ -113,6 +179,8 @@ __attribute__((weak)) void usart_init(void) {
# if defined(USART_REMAP)
USART_REMAP;
# endif
+# elif defined(MCU_RP) /* Raspberry Pi MCUs */
+# error Half-duplex with the SIO driver is not supported due to hardware limitations on the RP2040, switch to the PIO driver which has half-duplex support.
# else
# pragma message "usart_init: MCU Familiy not supported by default, please supply your own init code by implementing usart_init() in your keyboard files."
# endif
@@ -124,7 +192,7 @@ __attribute__((weak)) void usart_init(void) {
* @brief Initiate pins for USART peripheral. Full-duplex configuration.
*/
__attribute__((weak)) void usart_init(void) {
-# if defined(MCU_STM32)
+# if defined(MCU_STM32) /* STM32 MCUs */
# if defined(USE_GPIOV1)
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_PUSHPULL);
palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT);
@@ -136,6 +204,9 @@ __attribute__((weak)) void usart_init(void) {
# if defined(USART_REMAP)
USART_REMAP;
# endif
+# elif defined(MCU_RP) /* Raspberry Pi MCUs */
+ palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE_UART);
+ palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_ALTERNATE_UART);
# else
# pragma message "usart_init: MCU Familiy not supported by default, please supply your own init code by implementing usart_init() in your keyboard files."
# endif
@@ -146,7 +217,7 @@ __attribute__((weak)) void usart_init(void) {
/**
* @brief Overridable master specific initializations.
*/
-__attribute__((weak, nonnull)) void usart_master_init(SerialDriver** driver) {
+__attribute__((weak, nonnull)) void usart_master_init(QMKSerialDriver** driver) {
(void)driver;
usart_init();
}
@@ -154,161 +225,22 @@ __attribute__((weak, nonnull)) void usart_master_init(SerialDriver** driver) {
/**
* @brief Overridable slave specific initializations.
*/
-__attribute__((weak, nonnull)) void usart_slave_init(SerialDriver** driver) {
+__attribute__((weak, nonnull)) void usart_slave_init(QMKSerialDriver** driver) {
(void)driver;
usart_init();
}
-/**
- * @brief This thread runs on the slave and responds to transactions initiated
- * by the master.
- */
-static THD_WORKING_AREA(waSlaveThread, 1024);
-static THD_FUNCTION(SlaveThread, arg) {
- (void)arg;
- chRegSetThreadName("usart_tx_rx");
-
- while (true) {
- if (!react_to_transactions()) {
- /* Clear the receive queue, to start with a clean slate.
- * Parts of failed transactions or spurious bytes could still be in it. */
- usart_clear();
- }
- split_shared_memory_unlock();
- }
-}
-
-/**
- * @brief Slave specific initializations.
- */
-void soft_serial_target_init(void) {
+void serial_transport_driver_slave_init(void) {
usart_slave_init(&serial_driver);
-
- sdStart(serial_driver, &serial_config);
-
- /* Start transport thread. */
- chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL);
+ usart_driver_start();
}
-/**
- * @brief React to transactions started by the master.
- */
-static inline bool react_to_transactions(void) {
- /* Wait until there is a transaction for us. */
- uint8_t sstd_index = (uint8_t)sdGet(serial_driver);
-
- /* Sanity check that we are actually responding to a valid transaction. */
- if (sstd_index >= NUM_TOTAL_TRANSACTIONS) {
- return false;
- }
-
- split_shared_memory_lock();
- split_transaction_desc_t* trans = &split_transaction_table[sstd_index];
-
- /* Send back the handshake which is XORed as a simple checksum,
- to signal that the slave is ready to receive possible transaction buffers */
- sstd_index ^= HANDSHAKE_MAGIC;
- if (!send(&sstd_index, sizeof(sstd_index))) {
- return false;
- }
-
- /* Receive transaction buffer from the master. If this transaction requires it.*/
- if (trans->initiator2target_buffer_size) {
- if (!receive(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) {
- return false;
- }
- }
-
- /* Allow any slave processing to occur. */
- if (trans->slave_callback) {
- trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, split_trans_target2initiator_buffer(trans));
- }
-
- /* Send transaction buffer to the master. If this transaction requires it. */
- if (trans->target2initiator_buffer_size) {
- if (!send(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) {
- return false;
- }
- }
-
- return true;
-}
-
-/**
- * @brief Master specific initializations.
- */
-void soft_serial_initiator_init(void) {
+void serial_transport_driver_master_init(void) {
usart_master_init(&serial_driver);
#if defined(MCU_STM32) && defined(SERIAL_USART_PIN_SWAP)
serial_config.cr2 |= USART_CR2_SWAP; // master has swapped TX/RX pins
#endif
- sdStart(serial_driver, &serial_config);
-}
-
-/**
- * @brief Start transaction from the master half to the slave half.
- *
- * @param index Transaction Table index of the transaction to start.
- * @return bool Indicates success of transaction.
- */
-bool soft_serial_transaction(int index) {
- /* Clear the receive queue, to start with a clean slate.
- * Parts of failed transactions or spurious bytes could still be in it. */
- usart_clear();
-
- split_shared_memory_lock();
- bool result = initiate_transaction((uint8_t)index);
- split_shared_memory_unlock();
-
- return result;
-}
-
-/**
- * @brief Initiate transaction to slave half.
- */
-static inline bool initiate_transaction(uint8_t sstd_index) {
- /* Sanity check that we are actually starting a valid transaction. */
- if (sstd_index >= NUM_TOTAL_TRANSACTIONS) {
- dprintln("USART: Illegal transaction Id.");
- return false;
- }
-
- split_transaction_desc_t* trans = &split_transaction_table[sstd_index];
-
- /* Send transaction table index to the slave, which doubles as basic handshake token. */
- if (!send(&sstd_index, sizeof(sstd_index))) {
- dprintln("USART: Send Handshake failed.");
- return false;
- }
-
- uint8_t sstd_index_shake = 0xFF;
-
- /* Which we always read back first so that we can error out correctly.
- * - due to the half duplex limitations on return codes, we always have to read *something*.
- * - without the read, write only transactions *always* succeed, even during the boot process where the slave is not ready.
- */
- if (!receive(&sstd_index_shake, sizeof(sstd_index_shake)) || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) {
- dprintln("USART: Handshake failed.");
- return false;
- }
-
- /* Send transaction buffer to the slave. If this transaction requires it. */
- if (trans->initiator2target_buffer_size) {
- if (!send(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) {
- dprintln("USART: Send failed.");
- return false;
- }
- }
-
- /* Receive transaction buffer from the slave. If this transaction requires it. */
- if (trans->target2initiator_buffer_size) {
- if (!receive(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) {
- dprintln("USART: Receive failed.");
- return false;
- }
- }
-
- return true;
+ usart_driver_start();
}
diff --git a/platforms/chibios/drivers/serial_usart.h b/platforms/chibios/drivers/serial_usart.h
index 81fe9e0113..fa062cd736 100644
--- a/platforms/chibios/drivers/serial_usart.h
+++ b/platforms/chibios/drivers/serial_usart.h
@@ -1,42 +1,12 @@
-/* Copyright 2021 QMK
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
+// Copyright 2021 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "quantum.h"
#include "serial.h"
-#include "printf.h"
-
-#include <ch.h>
#include <hal.h>
-#if !defined(SERIAL_USART_DRIVER)
-# define SERIAL_USART_DRIVER SD1
-#endif
-
-#if !defined(USE_GPIOV1)
-/* The default PAL alternate modes are used to signal that the pins are used for USART. */
-# if !defined(SERIAL_USART_TX_PAL_MODE)
-# define SERIAL_USART_TX_PAL_MODE 7
-# endif
-# if !defined(SERIAL_USART_RX_PAL_MODE)
-# define SERIAL_USART_RX_PAL_MODE 7
-# endif
-#endif
-
#if defined(SOFT_SERIAL_PIN)
# define SERIAL_USART_TX_PIN SOFT_SERIAL_PIN
#endif
@@ -49,6 +19,62 @@
# define SERIAL_USART_RX_PIN A10
#endif
+#if !defined(SELECT_SOFT_SERIAL_SPEED)
+# define SELECT_SOFT_SERIAL_SPEED 1
+#endif
+
+#if defined(SERIAL_USART_SPEED)
+// Allow advanced users to directly set SERIAL_USART_SPEED
+#elif SELECT_SOFT_SERIAL_SPEED == 0
+# define SERIAL_USART_SPEED 460800
+#elif SELECT_SOFT_SERIAL_SPEED == 1
+# define SERIAL_USART_SPEED 230400
+#elif SELECT_SOFT_SERIAL_SPEED == 2
+# define SERIAL_USART_SPEED 115200
+#elif SELECT_SOFT_SERIAL_SPEED == 3
+# define SERIAL_USART_SPEED 57600
+#elif SELECT_SOFT_SERIAL_SPEED == 4
+# define SERIAL_USART_SPEED 38400
+#elif SELECT_SOFT_SERIAL_SPEED == 5
+# define SERIAL_USART_SPEED 19200
+#else
+# error invalid SELECT_SOFT_SERIAL_SPEED value
+#endif
+
+#if !defined(SERIAL_USART_TIMEOUT)
+# define SERIAL_USART_TIMEOUT 20
+#endif
+
+#if HAL_USE_SERIAL
+
+typedef SerialDriver QMKSerialDriver;
+typedef SerialConfig QMKSerialConfig;
+
+# if !defined(SERIAL_USART_DRIVER)
+# define SERIAL_USART_DRIVER SD1
+# endif
+
+#elif HAL_USE_SIO
+
+typedef SIODriver QMKSerialDriver;
+typedef SIOConfig QMKSerialConfig;
+
+# if !defined(SERIAL_USART_DRIVER)
+# define SERIAL_USART_DRIVER SIOD1
+# endif
+
+#endif
+
+#if !defined(USE_GPIOV1)
+/* The default PAL alternate modes are used to signal that the pins are used for USART. */
+# if !defined(SERIAL_USART_TX_PAL_MODE)
+# define SERIAL_USART_TX_PAL_MODE 7
+# endif
+# if !defined(SERIAL_USART_RX_PAL_MODE)
+# define SERIAL_USART_RX_PAL_MODE 7
+# endif
+#endif
+
#if !defined(USART_CR1_M0)
# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so
#endif
@@ -86,31 +112,3 @@
(AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \
} while (0)
#endif
-
-#if !defined(SELECT_SOFT_SERIAL_SPEED)
-# define SELECT_SOFT_SERIAL_SPEED 1
-#endif
-
-#if defined(SERIAL_USART_SPEED)
-// Allow advanced users to directly set SERIAL_USART_SPEED
-#elif SELECT_SOFT_SERIAL_SPEED == 0
-# define SERIAL_USART_SPEED 460800
-#elif SELECT_SOFT_SERIAL_SPEED == 1
-# define SERIAL_USART_SPEED 230400
-#elif SELECT_SOFT_SERIAL_SPEED == 2
-# define SERIAL_USART_SPEED 115200
-#elif SELECT_SOFT_SERIAL_SPEED == 3
-# define SERIAL_USART_SPEED 57600
-#elif SELECT_SOFT_SERIAL_SPEED == 4
-# define SERIAL_USART_SPEED 38400
-#elif SELECT_SOFT_SERIAL_SPEED == 5
-# define SERIAL_USART_SPEED 19200
-#else
-# error invalid SELECT_SOFT_SERIAL_SPEED value
-#endif
-
-#if !defined(SERIAL_USART_TIMEOUT)
-# define SERIAL_USART_TIMEOUT 20
-#endif
-
-#define HANDSHAKE_MAGIC 7
diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c
index ce69e7f0ac..f9974d9f6b 100644
--- a/platforms/chibios/drivers/spi_master.c
+++ b/platforms/chibios/drivers/spi_master.c
@@ -20,7 +20,7 @@
static pin_t currentSlavePin = NO_PIN;
-#if defined(K20x) || defined(KL2x)
+#if defined(K20x) || defined(KL2x) || defined(RP2040)
static SPIConfig spiConfig = {NULL, 0, 0, 0};
#else
static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0};
@@ -167,7 +167,36 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
spiConfig.SPI_CPOL = SPI_CPOL_High;
break;
}
+#elif defined(MCU_RP)
+ if (lsbFirst) {
+ osalDbgAssert(lsbFirst == false, "RP2040s PrimeCell SPI implementation does not support sending LSB first.");
+ }
+
+ // Motorola frame format and 8bit transfer data size.
+ spiConfig.SSPCR0 = SPI_SSPCR0_FRF_MOTOROLA | SPI_SSPCR0_DSS_8BIT;
+ // Serial output clock = (ck_sys or ck_peri) / (SSPCPSR->CPSDVSR * (1 +
+ // SSPCR0->SCR)). SCR is always set to zero, as QMK SPI API expects the
+ // passed divisor to be the only value to divide the input clock by.
+ spiConfig.SSPCPSR = roundedDivisor; // Even number from 2 to 254
+ switch (mode) {
+ case 0:
+ spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPO; // Clock polarity: low
+ spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPH; // Clock phase: sample on first edge
+ break;
+ case 1:
+ spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPO; // Clock polarity: low
+ spiConfig.SSPCR0 |= SPI_SSPCR0_SPH; // Clock phase: sample on second edge transition
+ break;
+ case 2:
+ spiConfig.SSPCR0 |= SPI_SSPCR0_SPO; // Clock polarity: high
+ spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPH; // Clock phase: sample on first edge
+ break;
+ case 3:
+ spiConfig.SSPCR0 |= SPI_SSPCR0_SPO; // Clock polarity: high
+ spiConfig.SSPCR0 |= SPI_SSPCR0_SPH; // Clock phase: sample on second edge transition
+ break;
+ }
#else
spiConfig.cr1 = 0;
diff --git a/platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c b/platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c
new file mode 100644
index 0000000000..949fc6dd93
--- /dev/null
+++ b/platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c
@@ -0,0 +1,457 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "quantum.h"
+#include "serial_usart.h"
+#include "serial_protocol.h"
+#include "hardware/pio.h"
+#include "hardware/clocks.h"
+
+#if !defined(MCU_RP)
+# error PIO Driver is only available for Raspberry Pi 2040 MCUs!
+#endif
+
+static inline bool receive_impl(uint8_t* destination, const size_t size, sysinterval_t timeout);
+static inline bool send_impl(const uint8_t* source, const size_t size);
+static inline void pio_serve_interrupt(void);
+
+#define MSG_PIO_ERROR ((msg_t)(-3))
+
+#if defined(SERIAL_PIO_USE_PIO1)
+static const PIO pio = pio1;
+
+OSAL_IRQ_HANDLER(RP_PIO1_IRQ_0_HANDLER) {
+ OSAL_IRQ_PROLOGUE();
+ pio_serve_interrupt();
+ OSAL_IRQ_EPILOGUE();
+}
+#else
+static const PIO pio = pio0;
+
+OSAL_IRQ_HANDLER(RP_PIO0_IRQ_0_HANDLER) {
+ OSAL_IRQ_PROLOGUE();
+ pio_serve_interrupt();
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#define UART_TX_WRAP_TARGET 0
+#define UART_TX_WRAP 3
+
+// clang-format off
+#if defined(SERIAL_USART_FULL_DUPLEX)
+static const uint16_t uart_tx_program_instructions[] = {
+ // .wrap_target
+ 0x9fa0, // 0: pull block side 1 [7]
+ 0xf727, // 1: set x, 7 side 0 [7]
+ 0x6001, // 2: out pins, 1
+ 0x0642, // 3: jmp x--, 2 [6]
+ // .wrap
+};
+#else
+static const uint16_t uart_tx_program_instructions[] = {
+ // .wrap_target
+ 0x9fa0, // 0: pull block side 1 [7]
+ 0xf727, // 1: set x, 7 side 0 [7]
+ 0x6081, // 2: out pindirs, 1
+ 0x0642, // 3: jmp x--, 2 [6]
+ // .wrap
+};
+#endif
+// clang-format on
+
+static const pio_program_t uart_tx_program = {
+ .instructions = uart_tx_program_instructions,
+ .length = 4,
+ .origin = -1,
+};
+
+#define UART_RX_WRAP_TARGET 0
+#define UART_RX_WRAP 8
+
+// clang-format off
+static const uint16_t uart_rx_program_instructions[] = {
+ // .wrap_target
+ 0x2020, // 0: wait 0 pin, 0
+ 0xea27, // 1: set x, 7 [10]
+ 0x4001, // 2: in pins, 1
+ 0x0642, // 3: jmp x--, 2 [6]
+ 0x00c8, // 4: jmp pin, 8
+ 0xc020, // 5: irq wait 0
+ 0x20a0, // 6: wait 1 pin, 0
+ 0x0000, // 7: jmp 0
+ 0x8020, // 8: push block
+ // .wrap
+};
+// clang-format on
+
+static const pio_program_t uart_rx_program = {
+ .instructions = uart_rx_program_instructions,
+ .length = 9,
+ .origin = -1,
+};
+
+thread_reference_t rx_thread = NULL;
+static int rx_state_machine = -1;
+
+thread_reference_t tx_thread = NULL;
+static int tx_state_machine = -1;
+
+void pio_serve_interrupt(void) {
+ uint32_t irqs = pio->ints0;
+
+ // The RX FIFO is not empty any more, therefore wake any sleeping rx thread
+ if (irqs & (PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS << rx_state_machine)) {
+ // Disable rx not empty interrupt
+ pio_set_irq0_source_enabled(pio, pis_sm0_rx_fifo_not_empty + rx_state_machine, false);
+
+ osalSysLockFromISR();
+ osalThreadResumeI(&rx_thread, MSG_OK);
+ osalSysUnlockFromISR();
+ }
+
+ // The TX FIFO is not full any more, therefore wake any sleeping tx thread
+ if (irqs & (PIO_IRQ0_INTF_SM0_TXNFULL_BITS << tx_state_machine)) {
+ // Disable tx not full interrupt
+ pio_set_irq0_source_enabled(pio, pis_sm0_tx_fifo_not_full + tx_state_machine, false);
+ osalSysLockFromISR();
+ osalThreadResumeI(&tx_thread, MSG_OK);
+ osalSysUnlockFromISR();
+ }
+
+ // IRQ 0 is set on framing or break errors by the rx state machine
+ if (pio_interrupt_get(pio, 0UL)) {
+ pio_interrupt_clear(pio, 0UL);
+
+ osalSysLockFromISR();
+ osalThreadResumeI(&rx_thread, MSG_PIO_ERROR);
+ osalSysUnlockFromISR();
+ }
+}
+
+#if !defined(SERIAL_USART_FULL_DUPLEX)
+// The internal pull-ups of the RP2040 are rather weakish with a range of 50k to
+// 80k, which in turn do not provide enough current to guarantee fast signal rise
+// times with a parasitic capacitance of greater than 100pf. In real world
+// applications, like split keyboards which might have vias in the signal path
+// or long PCB traces, this prevents a successful communication. The solution
+// is to temporarily augment the weak pull ups from the receiving side by
+// driving the tx pin high. On the receiving side the lowest possible drive
+// strength is chosen because the transmitting side must still be able to drive
+// the signal low. With this configuration the rise times are fast enough and
+// the generated low level with 360mV will generate a logical zero.
+static inline void enter_rx_state(void) {
+ osalSysLock();
+ // Wait for the transmitting state machines FIFO to run empty. At this point
+ // the last byte has been pulled from the transmitting state machines FIFO
+ // into the output shift register. We have to wait a tiny bit more until
+ // this byte is transmitted, before we can turn on the receiving state
+ // machine again.
+ while (!pio_sm_is_tx_fifo_empty(pio, tx_state_machine)) {
+ }
+ // Wait for ~11 bits, 1 start bit + 8 data bits + 1 stop bit + 1 bit
+ // headroom.
+ chSysPolledDelayX(US2RTC(1 * MHZ, (1000000U * 11 / SERIAL_USART_SPEED)));
+ // Disable tx state machine to not interfere with our tx pin manipulation
+ pio_sm_set_enabled(pio, tx_state_machine, false);
+ gpio_set_drive_strength(SERIAL_USART_TX_PIN, GPIO_DRIVE_STRENGTH_2MA);
+ pio_sm_set_pins_with_mask(pio, tx_state_machine, 1U << SERIAL_USART_TX_PIN, 1U << SERIAL_USART_TX_PIN);
+ pio_sm_set_consecutive_pindirs(pio, tx_state_machine, SERIAL_USART_TX_PIN, 1U, false);
+ pio_sm_set_enabled(pio, rx_state_machine, true);
+ osalSysUnlock();
+}
+
+static inline void leave_rx_state(void) {
+ osalSysLock();
+ // In Half-duplex operation the tx pin dual-functions as sender and
+ // receiver. To not receive the data we will send, we disable the receiving
+ // state machine.
+ pio_sm_set_enabled(pio, rx_state_machine, false);
+ pio_sm_set_consecutive_pindirs(pio, tx_state_machine, SERIAL_USART_TX_PIN, 1U, true);
+ pio_sm_set_pins_with_mask(pio, tx_state_machine, 0U, 1U << SERIAL_USART_TX_PIN);
+ gpio_set_drive_strength(SERIAL_USART_TX_PIN, GPIO_DRIVE_STRENGTH_12MA);
+ pio_sm_restart(pio, tx_state_machine);
+ pio_sm_set_enabled(pio, tx_state_machine, true);
+ osalSysUnlock();
+}
+#else
+// All this trickery is gladly not necessary for full-duplex.
+static inline void enter_rx_state(void) {}
+static inline void leave_rx_state(void) {}
+#endif
+
+/**
+ * @brief Clear the RX and TX hardware FIFOs of the state machines.
+ */
+inline void serial_transport_driver_clear(void) {
+ osalSysLock();
+ pio_sm_clear_fifos(pio, rx_state_machine);
+ pio_sm_clear_fifos(pio, tx_state_machine);
+ osalSysUnlock();
+}
+
+static inline msg_t sync_tx(sysinterval_t timeout) {
+ msg_t msg = MSG_OK;
+ osalSysLock();
+ while (pio_sm_is_tx_fifo_full(pio, tx_state_machine)) {
+ pio_set_irq0_source_enabled(pio, pis_sm0_tx_fifo_not_full + tx_state_machine, true);
+ msg = osalThreadSuspendTimeoutS(&tx_thread, timeout);
+ if (msg < MSG_OK) {
+ break;
+ }
+ }
+ osalSysUnlock();
+ return msg;
+}
+
+static inline bool send_impl(const uint8_t* source, const size_t size) {
+ size_t send = 0;
+ msg_t msg;
+ while (send < size) {
+ msg = sync_tx(TIME_MS2I(SERIAL_USART_TIMEOUT));
+ if (msg < MSG_OK) {
+ return false;
+ }
+
+ osalSysLock();
+ while (send < size) {
+ if (pio_sm_is_tx_fifo_full(pio, tx_state_machine)) {
+ break;
+ }
+ if (send >= size) {
+ break;
+ }
+ pio_sm_put(pio, tx_state_machine, (uint32_t)(*source));
+ source++;
+ send++;
+ }
+ osalSysUnlock();
+ }
+
+ return send == size;
+}
+
+/**
+ * @brief Blocking send of buffer with timeout.
+ *
+ * @return true Send success.
+ * @return false Send failed.
+ */
+inline bool serial_transport_send(const uint8_t* source, const size_t size) {
+ leave_rx_state();
+ bool result = send_impl(source, size);
+ enter_rx_state();
+
+ return result;
+}
+
+static inline msg_t sync_rx(sysinterval_t timeout) {
+ msg_t msg = MSG_OK;
+ osalSysLock();
+ while (pio_sm_is_rx_fifo_empty(pio, rx_state_machine)) {
+ pio_set_irq0_source_enabled(pio, pis_sm0_rx_fifo_not_empty + rx_state_machine, true);
+ msg = osalThreadSuspendTimeoutS(&rx_thread, timeout);
+ if (msg < MSG_OK) {
+ break;
+ }
+ }
+ osalSysUnlock();
+ return msg;
+}
+
+static inline bool receive_impl(uint8_t* destination, const size_t size, sysinterval_t timeout) {
+ size_t read = 0U;
+
+ while (read < size) {
+ msg_t msg = sync_rx(timeout);
+ if (msg < MSG_OK) {
+ return false;
+ }
+ osalSysLock();
+ while (true) {
+ if (pio_sm_is_rx_fifo_empty(pio, rx_state_machine)) {
+ break;
+ }
+ if (read >= size) {
+ break;
+ }
+ *destination++ = *((uint8_t*)&pio->rxf[rx_state_machine] + 3U);
+ read++;
+ }
+ osalSysUnlock();
+ }
+
+ return read == size;
+}
+
+/**
+ * @brief Blocking receive of size * bytes with timeout.
+ *
+ * @return true Receive success.
+ * @return false Receive failed, e.g. by timeout.
+ */
+inline bool serial_transport_receive(uint8_t* destination, const size_t size) {
+ return receive_impl(destination, size, TIME_MS2I(SERIAL_USART_TIMEOUT));
+}
+
+/**
+ * @brief Blocking receive of size * bytes.
+ *
+ * @return true Receive success.
+ * @return false Receive failed.
+ */
+inline bool serial_transport_receive_blocking(uint8_t* destination, const size_t size) {
+ return receive_impl(destination, size, TIME_INFINITE);
+}
+
+static inline void pio_tx_init(pin_t tx_pin) {
+ uint pio_idx = pio_get_index(pio);
+ uint offset = pio_add_program(pio, &uart_tx_program);
+
+#if defined(SERIAL_USART_FULL_DUPLEX)
+ // clang-format off
+ iomode_t tx_pin_mode = PAL_RP_GPIO_OE |
+ PAL_RP_PAD_SLEWFAST |
+ PAL_RP_PAD_DRIVE4 |
+ (pio_idx == 0 ? PAL_MODE_ALTERNATE_PIO0 : PAL_MODE_ALTERNATE_PIO1);
+ // clang-format on
+ pio_sm_set_pins_with_mask(pio, tx_state_machine, 1U << tx_pin, 1U << tx_pin);
+ pio_sm_set_consecutive_pindirs(pio, tx_state_machine, tx_pin, 1U, true);
+#else
+ // clang-format off
+ iomode_t tx_pin_mode = PAL_RP_PAD_IE |
+ PAL_RP_GPIO_OE |
+ PAL_RP_PAD_SCHMITT |
+ PAL_RP_PAD_PUE |
+ PAL_RP_PAD_SLEWFAST |
+ PAL_RP_PAD_DRIVE12 |
+ PAL_RP_IOCTRL_OEOVER_DRVINVPERI |
+ (pio_idx == 0 ? PAL_MODE_ALTERNATE_PIO0 : PAL_MODE_ALTERNATE_PIO1);
+ // clang-format on
+ pio_sm_set_pins_with_mask(pio, tx_state_machine, 0U << tx_pin, 1U << tx_pin);
+ pio_sm_set_consecutive_pindirs(pio, tx_state_machine, tx_pin, 1U, true);
+#endif
+
+ palSetLineMode(tx_pin, tx_pin_mode);
+
+ pio_sm_config config = pio_get_default_sm_config();
+ sm_config_set_wrap(&config, offset + UART_TX_WRAP_TARGET, offset + UART_TX_WRAP);
+#if defined(SERIAL_USART_FULL_DUPLEX)
+ sm_config_set_sideset(&config, 2, true, false);
+#else
+ sm_config_set_sideset(&config, 2, true, true);
+#endif
+ // OUT shifts to right, no autopull
+ sm_config_set_out_shift(&config, true, false, 32);
+ // We are mapping both OUT and side-set to the same pin, because sometimes
+ // we need to assert user data onto the pin (with OUT) and sometimes
+ // assert constant values (start/stop bit)
+ sm_config_set_out_pins(&config, tx_pin, 1);
+ sm_config_set_sideset_pins(&config, tx_pin);
+ // We only need TX, so get an 8-deep FIFO!
+ sm_config_set_fifo_join(&config, PIO_FIFO_JOIN_TX);
+ // SM transmits 1 bit per 8 execution cycles.
+ float div = (float)clock_get_hz(clk_sys) / (8 * SERIAL_USART_SPEED);
+ sm_config_set_clkdiv(&config, div);
+ pio_sm_init(pio, tx_state_machine, offset, &config);
+ pio_sm_set_enabled(pio, tx_state_machine, true);
+}
+
+static inline void pio_rx_init(pin_t rx_pin) {
+ uint offset = pio_add_program(pio, &uart_rx_program);
+
+#if defined(SERIAL_USART_FULL_DUPLEX)
+ uint pio_idx = pio_get_index(pio);
+ pio_sm_set_consecutive_pindirs(pio, rx_state_machine, rx_pin, 1, false);
+ // clang-format off
+ iomode_t rx_pin_mode = PAL_RP_PAD_IE |
+ PAL_RP_PAD_SCHMITT |
+ PAL_RP_PAD_PUE |
+ (pio_idx == 0 ? PAL_MODE_ALTERNATE_PIO0 : PAL_MODE_ALTERNATE_PIO1);
+ // clang-format on
+ palSetLineMode(rx_pin, rx_pin_mode);
+#endif
+
+ pio_sm_config config = pio_get_default_sm_config();
+ sm_config_set_wrap(&config, offset + UART_RX_WRAP_TARGET, offset + UART_RX_WRAP);
+ sm_config_set_in_pins(&config, rx_pin); // for WAIT, IN
+ sm_config_set_jmp_pin(&config, rx_pin); // for JMP
+ // Shift to right, autopush disabled
+ sm_config_set_in_shift(&config, true, false, 32);
+ // Deeper FIFO as we're not doing any TX
+ sm_config_set_fifo_join(&config, PIO_FIFO_JOIN_RX);
+ // SM transmits 1 bit per 8 execution cycles.
+ float div = (float)clock_get_hz(clk_sys) / (8 * SERIAL_USART_SPEED);
+ sm_config_set_clkdiv(&config, div);
+ pio_sm_init(pio, rx_state_machine, offset, &config);
+ pio_sm_set_enabled(pio, rx_state_machine, true);
+}
+
+static inline void pio_init(pin_t tx_pin, pin_t rx_pin) {
+ uint pio_idx = pio_get_index(pio);
+
+ /* Get PIOx peripheral out of reset state. */
+ hal_lld_peripheral_unreset(pio_idx == 0 ? RESETS_ALLREG_PIO0 : RESETS_ALLREG_PIO1);
+
+ tx_state_machine = pio_claim_unused_sm(pio, true);
+ if (tx_state_machine < 0) {
+ dprintln("ERROR: Failed to acquire state machine for serial transmission!");
+ return;
+ }
+ pio_tx_init(tx_pin);
+
+ rx_state_machine = pio_claim_unused_sm(pio, true);
+ if (rx_state_machine < 0) {
+ dprintln("ERROR: Failed to acquire state machine for serial reception!");
+ return;
+ }
+ pio_rx_init(rx_pin);
+
+ // Enable error flag IRQ source for rx state machine
+ pio_set_irq0_source_enabled(pio, pis_sm0_rx_fifo_not_empty + rx_state_machine, true);
+ pio_set_irq0_source_enabled(pio, pis_sm0_tx_fifo_not_full + tx_state_machine, true);
+ pio_set_irq0_source_enabled(pio, pis_interrupt0, true);
+
+ // Enable PIO specific interrupt vector
+#if defined(SERIAL_PIO_USE_PIO1)
+ nvicEnableVector(RP_PIO1_IRQ_0_NUMBER, RP_IRQ_UART0_PRIORITY);
+#else
+ nvicEnableVector(RP_PIO0_IRQ_0_NUMBER, RP_IRQ_UART0_PRIORITY);
+#endif
+
+ enter_rx_state();
+}
+
+/**
+ * @brief PIO driver specific initialization function for the master side.
+ */
+void serial_transport_driver_master_init(void) {
+#if defined(SERIAL_USART_FULL_DUPLEX)
+ pin_t tx_pin = SERIAL_USART_TX_PIN;
+ pin_t rx_pin = SERIAL_USART_RX_PIN;
+#else
+ pin_t tx_pin = SERIAL_USART_TX_PIN;
+ pin_t rx_pin = SERIAL_USART_TX_PIN;
+#endif
+
+#if defined(SERIAL_USART_PIN_SWAP)
+ pio_init(rx_pin, tx_pin);
+#else
+ pio_init(tx_pin, rx_pin);
+#endif
+}
+
+/**
+ * @brief PIO driver specific initialization function for the slave side.
+ */
+void serial_transport_driver_slave_init(void) {
+#if defined(SERIAL_USART_FULL_DUPLEX)
+ pin_t tx_pin = SERIAL_USART_TX_PIN;
+ pin_t rx_pin = SERIAL_USART_RX_PIN;
+#else
+ pin_t tx_pin = SERIAL_USART_TX_PIN;
+ pin_t rx_pin = SERIAL_USART_TX_PIN;
+#endif
+
+ pio_init(tx_pin, rx_pin);
+}
diff --git a/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c b/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c
new file mode 100644
index 0000000000..bc34eded14
--- /dev/null
+++ b/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c
@@ -0,0 +1,189 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "quantum.h"
+#include "ws2812.h"
+#include "hardware/pio.h"
+#include "hardware/clocks.h"
+
+#if !defined(MCU_RP)
+# error PIO Driver is only available for Raspberry Pi 2040 MCUs!
+#endif
+
+#if defined(WS2812_PIO_USE_PIO1)
+static const PIO pio = pio1;
+#else
+static const PIO pio = pio0;
+#endif
+
+#if !defined(RP_DMA_PRIORITY_WS2812)
+# define RP_DMA_PRIORITY_WS2812 12
+#endif
+
+static int state_machine = -1;
+
+#define WS2812_WRAP_TARGET 0
+#define WS2812_WRAP 3
+
+#define WS2812_T1 2
+#define WS2812_T2 5
+#define WS2812_T3 3
+
+#if defined(WS2812_EXTERNAL_PULLUP)
+
+# pragma message "The GPIOs of the RP2040 are NOT 5V tolerant! Make sure to NOT apply any voltage over 3.3V to the RGB data pin."
+
+// clang-format off
+static const uint16_t ws2812_program_instructions[] = {
+ // .wrap_target
+ 0x7221, // 0: out x, 1 side 1 [2]
+ 0x0123, // 1: jmp !x, 3 side 0 [1]
+ 0x0400, // 2: jmp 0 side 0 [4]
+ 0xb442, // 3: nop side 1 [4]
+ // .wrap
+};
+
+#else
+
+static const uint16_t ws2812_program_instructions[] = {
+ // .wrap_target
+ 0x6221, // 0: out x, 1 side 0 [2]
+ 0x1123, // 1: jmp !x, 3 side 1 [1]
+ 0x1400, // 2: jmp 0 side 1 [4]
+ 0xa442, // 3: nop side 0 [4]
+ // .wrap
+};
+// clang-format on
+#endif
+
+static const pio_program_t ws2812_program = {
+ .instructions = ws2812_program_instructions,
+ .length = 4,
+ .origin = -1,
+};
+
+static uint32_t WS2812_BUFFER[RGBLED_NUM];
+static const rp_dma_channel_t* WS2812_DMA_CHANNEL;
+
+bool ws2812_init(void) {
+ uint pio_idx = pio_get_index(pio);
+ /* Get PIOx peripheral out of reset state. */
+ hal_lld_peripheral_unreset(pio_idx == 0 ? RESETS_ALLREG_PIO0 : RESETS_ALLREG_PIO1);
+
+ // clang-format off
+ iomode_t rgb_pin_mode = PAL_RP_PAD_SLEWFAST |
+ PAL_RP_GPIO_OE |
+ (pio_idx == 0 ? PAL_MODE_ALTERNATE_PIO0 : PAL_MODE_ALTERNATE_PIO1);
+ // clang-format on
+
+ palSetLineMode(RGB_DI_PIN, rgb_pin_mode);
+
+ state_machine = pio_claim_unused_sm(pio, true);
+ if (state_machine < 0) {
+ dprintln("ERROR: Failed to acquire state machine for WS2812 output!");
+ return false;
+ }
+
+ uint offset = pio_add_program(pio, &ws2812_program);
+
+ pio_sm_set_consecutive_pindirs(pio, state_machine, RGB_DI_PIN, 1, true);
+
+ pio_sm_config config = pio_get_default_sm_config();
+ sm_config_set_wrap(&config, offset + WS2812_WRAP_TARGET, offset + WS2812_WRAP);
+ sm_config_set_sideset_pins(&config, RGB_DI_PIN);
+ sm_config_set_fifo_join(&config, PIO_FIFO_JOIN_TX);
+
+#if defined(WS2812_EXTERNAL_PULLUP)
+ /* Instruct side-set to change the pin-directions instead of outputting
+ * a logic level. We generate our levels the following way:
+ *
+ * 1: Set RGB data pin to high impedance input and let the pull-up drive the
+ * signal high.
+ *
+ * 0: Set RGB data pin to low impedance output and drive the pin low.
+ */
+ sm_config_set_sideset(&config, 1, false, true);
+#else
+ sm_config_set_sideset(&config, 1, false, false);
+#endif
+
+#if defined(RGBW)
+ sm_config_set_out_shift(&config, false, true, 32);
+#else
+ sm_config_set_out_shift(&config, false, true, 24);
+#endif
+
+ int cycles_per_bit = WS2812_T1 + WS2812_T2 + WS2812_T3;
+ float div = clock_get_hz(clk_sys) / (800.0f * KHZ * cycles_per_bit);
+ sm_config_set_clkdiv(&config, div);
+
+ pio_sm_init(pio, state_machine, offset, &config);
+ pio_sm_set_enabled(pio, state_machine, true);
+
+ WS2812_DMA_CHANNEL = dmaChannelAlloc(RP_DMA_CHANNEL_ID_ANY, RP_DMA_PRIORITY_WS2812, NULL, NULL);
+
+ // clang-format off
+ uint32_t mode = DMA_CTRL_TRIG_INCR_READ |
+ DMA_CTRL_TRIG_DATA_SIZE_WORD |
+ DMA_CTRL_TRIG_IRQ_QUIET |
+ DMA_CTRL_TRIG_TREQ_SEL(pio_idx == 0 ? state_machine : state_machine + 8);
+ // clang-format on
+
+ dmaChannelSetModeX(WS2812_DMA_CHANNEL, mode);
+ dmaChannelSetDestinationX(WS2812_DMA_CHANNEL, (uint32_t)&pio->txf[state_machine]);
+ return true;
+}
+
+/**
+ * @brief Convert RGBW value into WS2812 compatible 32-bit data word.
+ */
+__always_inline static uint32_t rgbw8888_to_u32(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) {
+#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
+ return ((uint32_t)green << 24) | ((uint32_t)red << 16) | ((uint32_t)blue << 8) | ((uint32_t)white);
+#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
+ return ((uint32_t)red << 24) | ((uint32_t)green << 16) | ((uint32_t)blue << 8) | ((uint32_t)white);
+#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
+ return ((uint32_t)blue << 24) | ((uint32_t)green << 16) | ((uint32_t)red << 8) | ((uint32_t)white);
+#endif
+}
+
+static inline void sync_ws2812_transfer(void) {
+ if (unlikely(dmaChannelIsBusyX(WS2812_DMA_CHANNEL) || !pio_sm_is_tx_fifo_empty(pio, state_machine))) {
+ fast_timer_t start = timer_read_fast();
+ do {
+ // Abort the synchronization if we have to wait longer than the total
+ // count of LEDs in millisecounds. This is safely much longer than it
+ // would take to push all the data out.
+ if (unlikely(timer_elapsed_fast(start) > RGBLED_NUM)) {
+ dprintln("ERROR: WS2812 DMA transfer has stalled, aborting!");
+ dmaChannelDisableX(WS2812_DMA_CHANNEL);
+ return;
+ }
+
+ } while (dmaChannelIsBusyX(WS2812_DMA_CHANNEL) || !pio_sm_is_tx_fifo_empty(pio, state_machine));
+ // We wait for the WS2812 chain to reset after all data has been pushed
+ // out.
+ wait_us(WS2812_TRST_US);
+ }
+}
+
+void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {
+ static bool is_initialized = false;
+ if (unlikely(!is_initialized)) {
+ is_initialized = ws2812_init();
+ }
+
+ sync_ws2812_transfer();
+
+ for (int i = 0; i < leds; i++) {
+#if defined(RGBW)
+ WS2812_BUFFER[i] = rgbw8888_to_u32(ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w);
+#else
+ WS2812_BUFFER[i] = rgbw8888_to_u32(ledarray[i].r, ledarray[i].g, ledarray[i].b, 0);
+#endif
+ }
+
+ dmaChannelSetSourceX(WS2812_DMA_CHANNEL, (uint32_t)WS2812_BUFFER);
+ dmaChannelSetCounterX(WS2812_DMA_CHANNEL, leds);
+ dmaChannelEnableX(WS2812_DMA_CHANNEL);
+}
diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c
new file mode 100644
index 0000000000..4b5639ee4a
--- /dev/null
+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl.c
@@ -0,0 +1,140 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <stdbool.h>
+#include <hal.h>
+#include "timer.h"
+#include "wear_leveling.h"
+#include "wear_leveling_internal.h"
+
+static flash_offset_t base_offset = UINT32_MAX;
+
+#if defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
+static flash_sector_t first_sector = WEAR_LEVELING_EFL_FIRST_SECTOR;
+#else // defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
+static flash_sector_t first_sector = UINT16_MAX;
+#endif // defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
+
+static flash_sector_t sector_count = UINT16_MAX;
+static BaseFlash * flash;
+
+#ifndef WEAR_LEVELING_EFL_FIRST_SECTOR
+// "Automatic" detection of the flash size -- ideally ChibiOS would have this already, but alas, it doesn't.
+static inline uint32_t detect_flash_size(void) {
+# if defined(WEAR_LEVELING_EFL_FLASH_SIZE)
+ return WEAR_LEVELING_EFL_FLASH_SIZE;
+# elif defined(FLASH_BANK_SIZE)
+ return FLASH_BANK_SIZE;
+# elif defined(FLASH_SIZE)
+ return FLASH_SIZE;
+# elif defined(FLASHSIZE_BASE)
+# if defined(QMK_MCU_SERIES_STM32F0XX) || defined(QMK_MCU_SERIES_STM32F1XX) || defined(QMK_MCU_SERIES_STM32F3XX) || defined(QMK_MCU_SERIES_STM32F4XX) || defined(QMK_MCU_SERIES_STM32G4XX) || defined(QMK_MCU_SERIES_STM32L0XX) || defined(QMK_MCU_SERIES_STM32L4XX) || defined(QMK_MCU_SERIES_GD32VF103)
+ return ((*(uint32_t *)FLASHSIZE_BASE) & 0xFFFFU) << 10U; // this register has the flash size in kB, so we convert it to bytes
+# elif defined(QMK_MCU_SERIES_STM32L1XX)
+# error This MCU family has an uncommon flash size register definition and has not been implemented. Perhaps try using the true EEPROM on the MCU instead?
+# endif
+# else
+# error Unknown flash size definition.
+ return 0;
+# endif
+}
+#endif // WEAR_LEVELING_EFL_FIRST_SECTOR
+
+bool backing_store_init(void) {
+ bs_dprintf("Init\n");
+ flash = (BaseFlash *)&EFLD1;
+
+ const flash_descriptor_t *desc = flashGetDescriptor(flash);
+ uint32_t counter = 0;
+
+#if defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
+
+ // Work out how many sectors we want to use, working forwards from the first sector specified
+ for (flash_sector_t i = 0; i < desc->sectors_count - first_sector; ++i) {
+ counter += flashGetSectorSize(flash, first_sector + i);
+ if (counter >= (WEAR_LEVELING_BACKING_SIZE)) {
+ sector_count = i + 1;
+ base_offset = flashGetSectorOffset(flash, first_sector);
+ break;
+ }
+ }
+ if (sector_count == UINT16_MAX || base_offset >= flash_size) {
+ // We didn't get the required number of sectors. Can't do anything here. Fault.
+ chSysHalt("Invalid sector count intended to be used with wear_leveling");
+ }
+
+#else // defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
+
+ // Work out how many sectors we want to use, working backwards from the end of the flash
+ uint32_t flash_size = detect_flash_size();
+ flash_sector_t last_sector = desc->sectors_count;
+ for (flash_sector_t i = 0; i < desc->sectors_count; ++i) {
+ first_sector = desc->sectors_count - i - 1;
+ if (flashGetSectorOffset(flash, first_sector) >= flash_size) {
+ last_sector = first_sector;
+ continue;
+ }
+ counter += flashGetSectorSize(flash, first_sector);
+ if (counter >= (WEAR_LEVELING_BACKING_SIZE)) {
+ sector_count = last_sector - first_sector;
+ base_offset = flashGetSectorOffset(flash, first_sector);
+ break;
+ }
+ }
+
+#endif // defined(WEAR_LEVELING_EFL_FIRST_SECTOR)
+
+ return true;
+}
+
+bool backing_store_unlock(void) {
+ bs_dprintf("Unlock\n");
+ return eflStart(&EFLD1, NULL) == HAL_RET_SUCCESS;
+}
+
+bool backing_store_erase(void) {
+#ifdef WEAR_LEVELING_DEBUG_OUTPUT
+ uint32_t start = timer_read32();
+#endif
+
+ bool ret = true;
+ flash_error_t status;
+ for (int i = 0; i < sector_count; ++i) {
+ // Kick off the sector erase
+ status = flashStartEraseSector(flash, first_sector + i);
+ if (status != FLASH_NO_ERROR && status != FLASH_BUSY_ERASING) {
+ ret = false;
+ }
+
+ // Wait for the erase to complete
+ status = flashWaitErase(flash);
+ if (status != FLASH_NO_ERROR && status != FLASH_BUSY_ERASING) {
+ ret = false;
+ }
+ }
+
+ bs_dprintf("Backing store erase took %ldms to complete\n", ((long)(timer_read32() - start)));
+ return ret;
+}
+
+bool backing_store_write(uint32_t address, backing_store_int_t value) {
+ uint32_t offset = (base_offset + address);
+ bs_dprintf("Write ");
+ wl_dump(offset, &value, sizeof(value));
+ value = ~value;
+ return flashProgram(flash, offset, sizeof(value), (const uint8_t *)&value) == FLASH_NO_ERROR;
+}
+
+bool backing_store_lock(void) {
+ bs_dprintf("Lock \n");
+ eflStop(&EFLD1);
+ return true;
+}
+
+bool backing_store_read(uint32_t address, backing_store_int_t *value) {
+ uint32_t offset = (base_offset + address);
+ backing_store_int_t *loc = (backing_store_int_t *)offset;
+ *value = ~(*loc);
+ bs_dprintf("Read ");
+ wl_dump(offset, value, sizeof(backing_store_int_t));
+ return true;
+}
diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h
new file mode 100644
index 0000000000..9e38c2965d
--- /dev/null
+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_efl_config.h
@@ -0,0 +1,50 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#ifndef __ASSEMBLER__
+# include <hal.h>
+#endif
+
+// Work out how many bytes per write to internal flash
+#ifndef BACKING_STORE_WRITE_SIZE
+// These need to match EFL's XXXXXX_FLASH_LINE_SIZE, see associated code in `lib/chibios/os/hal/ports/**/hal_efl_lld.c`,
+// or associated `stm32_registry.h` for the MCU in question (or equivalent for the family).
+# if defined(QMK_MCU_SERIES_GD32VF103)
+# define BACKING_STORE_WRITE_SIZE 2 // from hal_efl_lld.c
+# elif defined(QMK_MCU_FAMILY_NUC123)
+# define BACKING_STORE_WRITE_SIZE 4 // from hal_efl_lld.c
+# elif defined(QMK_MCU_FAMILY_STM32)
+# if defined(STM32_FLASH_LINE_SIZE) // from some family's stm32_registry.h file
+# define BACKING_STORE_WRITE_SIZE (STM32_FLASH_LINE_SIZE)
+# else
+# if defined(QMK_MCU_SERIES_STM32F1XX)
+# define BACKING_STORE_WRITE_SIZE 2 // from hal_efl_lld.c
+# elif defined(QMK_MCU_SERIES_STM32F3XX)
+# define BACKING_STORE_WRITE_SIZE 2 // from hal_efl_lld.c
+# elif defined(QMK_MCU_SERIES_STM32F4XX)
+# define BACKING_STORE_WRITE_SIZE (1 << STM32_FLASH_PSIZE) // from hal_efl_lld.c
+# elif defined(QMK_MCU_SERIES_STM32L4XX)
+# define BACKING_STORE_WRITE_SIZE 8 // from hal_efl_lld.c
+# elif defined(QMK_MCU_SERIES_STM32G0XX)
+# define BACKING_STORE_WRITE_SIZE 8 // from hal_efl_lld.c
+# elif defined(QMK_MCU_SERIES_STM32G4XX)
+# define BACKING_STORE_WRITE_SIZE 8 // from hal_efl_lld.c
+# else
+# error "ChibiOS hasn't defined STM32_FLASH_LINE_SIZE, and could not automatically determine BACKING_STORE_WRITE_SIZE" // normally defined in stm32_registry.h, should be set by STM32_FLASH_LINE_SIZE
+# endif
+# endif
+# else
+# error "Could not automatically determine BACKING_STORE_WRITE_SIZE"
+# endif
+#endif
+
+// 2kB backing space allocated
+#ifndef WEAR_LEVELING_BACKING_SIZE
+# define WEAR_LEVELING_BACKING_SIZE 2048
+#endif // WEAR_LEVELING_BACKING_SIZE
+
+// 1kB logical EEPROM
+#ifndef WEAR_LEVELING_LOGICAL_SIZE
+# define WEAR_LEVELING_LOGICAL_SIZE 1024
+#endif // WEAR_LEVELING_LOGICAL_SIZE
diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy.c b/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy.c
new file mode 100644
index 0000000000..87126c4467
--- /dev/null
+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy.c
@@ -0,0 +1,59 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <stdbool.h>
+#include <hal.h>
+#include "timer.h"
+#include "wear_leveling.h"
+#include "wear_leveling_internal.h"
+#include "flash_stm32.h"
+
+bool backing_store_init(void) {
+ bs_dprintf("Init\n");
+ return true;
+}
+
+bool backing_store_unlock(void) {
+ bs_dprintf("Unlock\n");
+ FLASH_Unlock();
+ return true;
+}
+
+bool backing_store_erase(void) {
+#ifdef WEAR_LEVELING_DEBUG_OUTPUT
+ uint32_t start = timer_read32();
+#endif
+
+ bool ret = true;
+ FLASH_Status status;
+ for (int i = 0; i < (WEAR_LEVELING_LEGACY_EMULATION_PAGE_COUNT); ++i) {
+ status = FLASH_ErasePage(WEAR_LEVELING_LEGACY_EMULATION_BASE_PAGE_ADDRESS + (i * (WEAR_LEVELING_LEGACY_EMULATION_PAGE_SIZE)));
+ if (status != FLASH_COMPLETE) {
+ ret = false;
+ }
+ }
+
+ bs_dprintf("Backing store erase took %ldms to complete\n", ((long)(timer_read32() - start)));
+ return ret;
+}
+
+bool backing_store_write(uint32_t address, backing_store_int_t value) {
+ uint32_t offset = ((WEAR_LEVELING_LEGACY_EMULATION_BASE_PAGE_ADDRESS) + address);
+ bs_dprintf("Write ");
+ wl_dump(offset, &value, sizeof(backing_store_int_t));
+ return FLASH_ProgramHalfWord(offset, ~value) == FLASH_COMPLETE;
+}
+
+bool backing_store_lock(void) {
+ bs_dprintf("Lock \n");
+ FLASH_Lock();
+ return true;
+}
+
+bool backing_store_read(uint32_t address, backing_store_int_t* value) {
+ uint32_t offset = ((WEAR_LEVELING_LEGACY_EMULATION_BASE_PAGE_ADDRESS) + address);
+ backing_store_int_t* loc = (backing_store_int_t*)offset;
+ *value = ~(*loc);
+ bs_dprintf("Read ");
+ wl_dump(offset, loc, sizeof(backing_store_int_t));
+ return true;
+}
diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy_config.h b/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy_config.h
new file mode 100644
index 0000000000..1e4691a6c0
--- /dev/null
+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_legacy_config.h
@@ -0,0 +1,67 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+// Work out the page size to use
+#ifndef WEAR_LEVELING_LEGACY_EMULATION_PAGE_SIZE
+# if defined(QMK_MCU_STM32F042)
+# define WEAR_LEVELING_LEGACY_EMULATION_PAGE_SIZE 1024
+# elif defined(QMK_MCU_STM32F070) || defined(QMK_MCU_STM32F072)
+# define WEAR_LEVELING_LEGACY_EMULATION_PAGE_SIZE 2048
+# elif defined(QMK_MCU_STM32F401) || defined(QMK_MCU_STM32F411)
+# define WEAR_LEVELING_LEGACY_EMULATION_PAGE_SIZE 16384
+# endif
+#endif
+
+// Work out how much flash space we have
+#ifndef WEAR_LEVELING_LEGACY_EMULATION_FLASH_SIZE
+# define WEAR_LEVELING_LEGACY_EMULATION_FLASH_SIZE ((*(uint32_t *)FLASHSIZE_BASE) & 0xFFFFU) // in kB
+#endif
+
+// The base location of program memory
+#ifndef WEAR_LEVELING_LEGACY_EMULATION_FLASH_BASE
+# define WEAR_LEVELING_LEGACY_EMULATION_FLASH_BASE 0x08000000
+#endif
+
+// The number of pages to use
+#ifndef WEAR_LEVELING_LEGACY_EMULATION_PAGE_COUNT
+# if defined(QMK_MCU_STM32F042)
+# define WEAR_LEVELING_LEGACY_EMULATION_PAGE_COUNT 2
+# elif defined(QMK_MCU_STM32F070) || defined(QMK_MCU_STM32F072)
+# define WEAR_LEVELING_LEGACY_EMULATION_PAGE_COUNT 1
+# elif defined(QMK_MCU_STM32F401) || defined(QMK_MCU_STM32F411)
+# define WEAR_LEVELING_LEGACY_EMULATION_PAGE_COUNT 1
+# endif
+#endif
+
+// The origin of the emulated eeprom
+#ifndef WEAR_LEVELING_LEGACY_EMULATION_BASE_PAGE_ADDRESS
+# if defined(QMK_MCU_STM32F042) || defined(QMK_MCU_STM32F070) || defined(QMK_MCU_STM32F072)
+# define WEAR_LEVELING_LEGACY_EMULATION_BASE_PAGE_ADDRESS ((uintptr_t)(WEAR_LEVELING_LEGACY_EMULATION_FLASH_BASE) + WEAR_LEVELING_LEGACY_EMULATION_FLASH_SIZE * 1024 - (WEAR_LEVELING_LEGACY_EMULATION_PAGE_COUNT * WEAR_LEVELING_LEGACY_EMULATION_PAGE_SIZE))
+# elif defined(QMK_MCU_STM32F401) || defined(QMK_MCU_STM32F411)
+# if defined(BOOTLOADER_STM32)
+# define WEAR_LEVELING_LEGACY_EMULATION_BASE_PAGE_ADDRESS (WEAR_LEVELING_LEGACY_EMULATION_FLASH_BASE + (1 * (WEAR_LEVELING_LEGACY_EMULATION_PAGE_SIZE))) // +16k
+# elif defined(BOOTLOADER_TINYUF2)
+# define WEAR_LEVELING_LEGACY_EMULATION_BASE_PAGE_ADDRESS (WEAR_LEVELING_LEGACY_EMULATION_FLASH_BASE + (3 * (WEAR_LEVELING_LEGACY_EMULATION_PAGE_SIZE))) // +48k
+# endif
+# endif
+#endif
+
+// 2-byte writes
+#ifndef BACKING_STORE_WRITE_SIZE
+# define BACKING_STORE_WRITE_SIZE 2
+#endif
+
+// The amount of space to use for the entire set of emulation
+#ifndef WEAR_LEVELING_BACKING_SIZE
+# if defined(QMK_MCU_STM32F042) || defined(QMK_MCU_STM32F070) || defined(QMK_MCU_STM32F072)
+# define WEAR_LEVELING_BACKING_SIZE 2048
+# elif defined(QMK_MCU_STM32F401) || defined(QMK_MCU_STM32F411)
+# define WEAR_LEVELING_BACKING_SIZE 16384
+# endif
+#endif
+
+// The logical amount of eeprom available
+#ifndef WEAR_LEVELING_LOGICAL_SIZE
+# define WEAR_LEVELING_LOGICAL_SIZE 1024
+#endif
diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c b/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c
new file mode 100644
index 0000000000..640628e1e9
--- /dev/null
+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash.c
@@ -0,0 +1,221 @@
+/**
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ * Copyright (c) 2022 Nick Brassel (@tzarc)
+ * Copyright (c) 2022 Stefan Kerkmann (@KarlK90)
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "pico/bootrom.h"
+#include "hardware/flash.h"
+#include "hardware/sync.h"
+#include "hardware/structs/ssi.h"
+#include "hardware/structs/ioqspi.h"
+
+#include <stdbool.h>
+#include "timer.h"
+#include "wear_leveling.h"
+#include "wear_leveling_internal.h"
+
+#ifndef WEAR_LEVELING_RP2040_FLASH_BULK_COUNT
+# define WEAR_LEVELING_RP2040_FLASH_BULK_COUNT 64
+#endif // WEAR_LEVELING_RP2040_FLASH_BULK_COUNT
+
+#define FLASHCMD_PAGE_PROGRAM 0x02
+#define FLASHCMD_READ_STATUS 0x05
+#define FLASHCMD_WRITE_ENABLE 0x06
+
+extern uint8_t BOOT2_ROM[256];
+static uint32_t BOOT2_ROM_RAM[64];
+
+static ssi_hw_t *const ssi = (ssi_hw_t *)XIP_SSI_BASE;
+
+// Sanity check
+check_hw_layout(ssi_hw_t, ssienr, SSI_SSIENR_OFFSET);
+check_hw_layout(ssi_hw_t, spi_ctrlr0, SSI_SPI_CTRLR0_OFFSET);
+
+static void __no_inline_not_in_flash_func(flash_enable_xip_via_boot2)(void) {
+ ((void (*)(void))BOOT2_ROM_RAM + 1)();
+}
+
+// Bitbanging the chip select using IO overrides, in case RAM-resident IRQs
+// are still running, and the FIFO bottoms out. (the bootrom does the same)
+static void __no_inline_not_in_flash_func(flash_cs_force)(bool high) {
+ uint32_t field_val = high ? IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_HIGH : IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_LOW;
+ hw_write_masked(&ioqspi_hw->io[1].ctrl, field_val << IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_LSB, IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_BITS);
+}
+
+// Also allow any unbounded loops to check whether the above abort condition
+// was asserted, and terminate early
+static int __no_inline_not_in_flash_func(flash_was_aborted)(void) {
+ return *(io_rw_32 *)(IO_QSPI_BASE + IO_QSPI_GPIO_QSPI_SD1_CTRL_OFFSET) & IO_QSPI_GPIO_QSPI_SD1_CTRL_INOVER_BITS;
+}
+
+// Put bytes from one buffer, and get bytes into another buffer.
+// These can be the same buffer.
+// If tx is NULL then send zeroes.
+// If rx is NULL then all read data will be dropped.
+//
+// If rx_skip is nonzero, this many bytes will first be consumed from the FIFO,
+// before reading a further count bytes into *rx.
+// E.g. if you have written a command+address just before calling this function.
+static void __no_inline_not_in_flash_func(flash_put_get)(const uint8_t *tx, uint8_t *rx, size_t count, size_t rx_skip) {
+ // Make sure there is never more data in flight than the depth of the RX
+ // FIFO. Otherwise, when we are interrupted for long periods, hardware
+ // will overflow the RX FIFO.
+ const uint max_in_flight = 16 - 2; // account for data internal to SSI
+ size_t tx_count = count;
+ size_t rx_count = count;
+ while (tx_count || rx_skip || rx_count) {
+ // NB order of reads, for pessimism rather than optimism
+ uint32_t tx_level = ssi_hw->txflr;
+ uint32_t rx_level = ssi_hw->rxflr;
+ bool did_something = false; // Expect this to be folded into control flow, not register
+ if (tx_count && tx_level + rx_level < max_in_flight) {
+ ssi->dr0 = (uint32_t)(tx ? *tx++ : 0);
+ --tx_count;
+ did_something = true;
+ }
+ if (rx_level) {
+ uint8_t rxbyte = ssi->dr0;
+ did_something = true;
+ if (rx_skip) {
+ --rx_skip;
+ } else {
+ if (rx) *rx++ = rxbyte;
+ --rx_count;
+ }
+ }
+ // APB load costs 4 cycles, so only do it on idle loops (our budget is
+ // 48 cyc/byte)
+ if (!did_something && __builtin_expect(flash_was_aborted(), 0)) break;
+ }
+ flash_cs_force(1);
+}
+
+// Convenience wrapper for above
+// (And it's hard for the debug host to get the tight timing between
+// cmd DR0 write and the remaining data)
+static void __no_inline_not_in_flash_func(_flash_do_cmd)(uint8_t cmd, const uint8_t *tx, uint8_t *rx, size_t count) {
+ flash_cs_force(0);
+ ssi->dr0 = cmd;
+ flash_put_get(tx, rx, count, 1);
+}
+
+// Timing of this one is critical, so do not expose the symbol to debugger etc
+static void __no_inline_not_in_flash_func(flash_put_cmd_addr)(uint8_t cmd, uint32_t addr) {
+ flash_cs_force(0);
+ addr |= cmd << 24;
+ for (int i = 0; i < 4; ++i) {
+ ssi->dr0 = addr >> 24;
+ addr <<= 8;
+ }
+}
+
+// Poll the flash status register until the busy bit (LSB) clears
+static void __no_inline_not_in_flash_func(flash_wait_ready)(void) {
+ uint8_t stat;
+ do {
+ _flash_do_cmd(FLASHCMD_READ_STATUS, NULL, &stat, 1);
+ } while (stat & 0x1 && !flash_was_aborted());
+}
+
+// Set the WEL bit (needed before any program/erase operation)
+static void __no_inline_not_in_flash_func(flash_enable_write)(void) {
+ _flash_do_cmd(FLASHCMD_WRITE_ENABLE, NULL, NULL, 0);
+}
+
+static void __no_inline_not_in_flash_func(pico_program_bulk)(uint32_t flash_address, backing_store_int_t *values, size_t item_count) {
+ rom_connect_internal_flash_fn connect_internal_flash = (rom_connect_internal_flash_fn)rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH);
+ rom_flash_exit_xip_fn flash_exit_xip = (rom_flash_exit_xip_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP);
+ rom_flash_flush_cache_fn flash_flush_cache = (rom_flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);
+ assert(connect_internal_flash && flash_exit_xip && flash_flush_cache);
+
+ static backing_store_int_t bulk_write_buffer[WEAR_LEVELING_RP2040_FLASH_BULK_COUNT];
+
+ while (item_count) {
+ size_t batch_size = MIN(item_count, WEAR_LEVELING_RP2040_FLASH_BULK_COUNT);
+ for (size_t i = 0; i < batch_size; i++, values++, item_count--) {
+ bulk_write_buffer[i] = ~(*values);
+ }
+ __compiler_memory_barrier();
+
+ connect_internal_flash();
+ flash_exit_xip();
+ flash_enable_write();
+
+ flash_put_cmd_addr(FLASHCMD_PAGE_PROGRAM, flash_address);
+ flash_put_get((uint8_t *)bulk_write_buffer, NULL, batch_size * sizeof(backing_store_int_t), 4);
+ flash_wait_ready();
+ flash_address += batch_size * sizeof(backing_store_int_t);
+
+ flash_flush_cache();
+ flash_enable_xip_via_boot2();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// QMK Wear-Leveling Backing Store implementation
+
+static int interrupts;
+
+bool backing_store_init(void) {
+ bs_dprintf("Init\n");
+ memcpy(BOOT2_ROM_RAM, BOOT2_ROM, sizeof(BOOT2_ROM));
+ __compiler_memory_barrier();
+ return true;
+}
+
+bool backing_store_unlock(void) {
+ bs_dprintf("Unlock\n");
+ return true;
+}
+
+bool backing_store_erase(void) {
+#ifdef WEAR_LEVELING_DEBUG_OUTPUT
+ uint32_t start = timer_read32();
+#endif
+
+ // Ensure the backing size can be cleanly subtracted from the flash size without alignment issues.
+ _Static_assert((WEAR_LEVELING_BACKING_SIZE) % (FLASH_SECTOR_SIZE) == 0, "Backing size must be a multiple of FLASH_SECTOR_SIZE");
+
+ interrupts = save_and_disable_interrupts();
+ flash_range_erase((WEAR_LEVELING_RP2040_FLASH_BASE), (WEAR_LEVELING_BACKING_SIZE));
+ restore_interrupts(interrupts);
+
+ bs_dprintf("Backing store erase took %ldms to complete\n", ((long)(timer_read32() - start)));
+ return true;
+}
+
+bool backing_store_write(uint32_t address, backing_store_int_t value) {
+ return backing_store_write_bulk(address, &value, 1);
+}
+
+bool backing_store_write_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
+ uint32_t offset = (WEAR_LEVELING_RP2040_FLASH_BASE) + address;
+ bs_dprintf("Write ");
+ wl_dump(offset, values, sizeof(backing_store_int_t) * item_count);
+ interrupts = save_and_disable_interrupts();
+ pico_program_bulk(offset, values, item_count);
+ restore_interrupts(interrupts);
+ return true;
+}
+
+bool backing_store_lock(void) {
+ return true;
+}
+
+bool backing_store_read(uint32_t address, backing_store_int_t *value) {
+ return backing_store_read_bulk(address, value, 1);
+}
+
+bool backing_store_read_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
+ uint32_t offset = (WEAR_LEVELING_RP2040_FLASH_BASE) + address;
+ backing_store_int_t *loc = (backing_store_int_t *)((XIP_BASE) + offset);
+ for (size_t i = 0; i < item_count; ++i) {
+ values[i] = ~loc[i];
+ }
+ bs_dprintf("Read ");
+ wl_dump(offset, values, item_count * sizeof(backing_store_int_t));
+ return true;
+}
diff --git a/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash_config.h b/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash_config.h
new file mode 100644
index 0000000000..93a9aa0372
--- /dev/null
+++ b/platforms/chibios/drivers/wear_leveling/wear_leveling_rp2040_flash_config.h
@@ -0,0 +1,32 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#ifndef __ASSEMBLER__
+# include "hardware/flash.h"
+#endif
+
+// 2-byte writes
+#ifndef BACKING_STORE_WRITE_SIZE
+# define BACKING_STORE_WRITE_SIZE 2
+#endif
+
+// 64kB backing space allocated
+#ifndef WEAR_LEVELING_BACKING_SIZE
+# define WEAR_LEVELING_BACKING_SIZE 8192
+#endif // WEAR_LEVELING_BACKING_SIZE
+
+// 32kB logical EEPROM
+#ifndef WEAR_LEVELING_LOGICAL_SIZE
+# define WEAR_LEVELING_LOGICAL_SIZE 4096
+#endif // WEAR_LEVELING_LOGICAL_SIZE
+
+// Define how much flash space we have (defaults to lib/pico-sdk/src/boards/include/boards/***)
+#ifndef WEAR_LEVELING_RP2040_FLASH_SIZE
+# define WEAR_LEVELING_RP2040_FLASH_SIZE (PICO_FLASH_SIZE_BYTES)
+#endif
+
+// Define the location of emulated EEPROM
+#ifndef WEAR_LEVELING_RP2040_FLASH_BASE
+# define WEAR_LEVELING_RP2040_FLASH_BASE ((WEAR_LEVELING_RP2040_FLASH_SIZE) - (WEAR_LEVELING_BACKING_SIZE))
+#endif
diff --git a/platforms/chibios/flash.mk b/platforms/chibios/flash.mk
index a91ef2cf35..790c4f3316 100644
--- a/platforms/chibios/flash.mk
+++ b/platforms/chibios/flash.mk
@@ -54,11 +54,11 @@ endef
# TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS
# within the emulated eeprom via dfu-util or another tool
-ifneq (,$(filter $(MAKECMDGOALS),dfu-util-split-left))
+ifneq (,$(filter $(MAKECMDGOALS), dfu-util-split-left uf2-split-left))
OPT_DEFS += -DINIT_EE_HANDS_LEFT
endif
-ifneq (,$(filter $(MAKECMDGOALS),dfu-util-split-right))
+ifneq (,$(filter $(MAKECMDGOALS), dfu-util-split-right uf2-split-right))
OPT_DEFS += -DINIT_EE_HANDS_RIGHT
endif
@@ -66,6 +66,10 @@ dfu-util-split-left: dfu-util
dfu-util-split-right: dfu-util
+uf2-split-left: flash
+
+uf2-split-right: flash
+
ST_LINK_CLI ?= st-link_cli
ST_LINK_ARGS ?=
@@ -104,6 +108,8 @@ else ifeq ($(strip $(BOOTLOADER)),kiibohd)
$(UNSYNC_OUTPUT_CMD) && $(call EXEC_DFU_UTIL)
else ifeq ($(strip $(BOOTLOADER)),tinyuf2)
$(UNSYNC_OUTPUT_CMD) && $(call EXEC_UF2_UTIL_DEPLOY)
+else ifeq ($(strip $(BOOTLOADER)),rp2040)
+ $(UNSYNC_OUTPUT_CMD) && $(call EXEC_UF2_UTIL_DEPLOY)
else ifeq ($(strip $(MCU_FAMILY)),KINETIS)
$(UNSYNC_OUTPUT_CMD) && $(call EXEC_TEENSY)
else ifeq ($(strip $(MCU_FAMILY)),MIMXRT1062)
diff --git a/platforms/chibios/platform.mk b/platforms/chibios/platform.mk
index 21751f23fd..63cc1a4b33 100644
--- a/platforms/chibios/platform.mk
+++ b/platforms/chibios/platform.mk
@@ -36,6 +36,7 @@ ifeq ($(strip $(MCU)), risc-v)
# RISC-V Support
# As of 7.4.2021 there is only one supported RISC-V platform in Chibios-Contrib,
# therefore all required settings are hard-coded
+ USE_CHIBIOS_CONTRIB = yes
STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
PORT_V = $(CHIBIOS_CONTRIB)/os/common/ports/RISCV-ECLIC/compilers/GCC/mk/port.mk
RULESPATH = $(CHIBIOS_CONTRIB)/os/common/startup/RISCV-ECLIC/compilers/GCC
@@ -87,12 +88,17 @@ ifeq ("$(MCU_PORT_NAME)","")
endif
ifeq ("$(wildcard $(PLATFORM_MK))","")
- PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_PORT_NAME)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
+ PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_PORT_NAME)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
ifeq ("$(wildcard $(PLATFORM_MK))","")
- PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_PORT_NAME)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
+ PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_PORT_NAME)/$(MCU_SERIES)/$(PLATFORM_NAME).mk
endif
endif
+# If no MCU architecture specified, use the MCU instead (allows for mcu_selection.mk to swap to cortex-m0 etc.)
+ifeq ("$(MCU_ARCH)","")
+ MCU_ARCH = $(MCU)
+endif
+
include $(STARTUP_MK)
include $(PORT_V)
include $(PLATFORM_MK)
@@ -282,6 +288,17 @@ EXTRAINCDIRS += $(CHIBIOS)/os/license $(CHIBIOS)/os/oslib/include \
$(STREAMSINC) $(CHIBIOS)/os/various $(COMMON_VPATH)
#
+# QMK specific MCU family support selection.
+##############################################################################
+ifneq ("$(wildcard $(PLATFORM_PATH)/$(PLATFORM_KEY)/vendors/$(MCU_FAMILY)/$(MCU_SERIES).mk)","")
+ # Either by MCU series e.g. STM32/STM32F1xx.mk or...
+ include $(PLATFORM_PATH)/$(PLATFORM_KEY)/vendors/$(MCU_FAMILY)/$(MCU_SERIES).mk
+else ifneq ("$(wildcard $(PLATFORM_PATH)/$(PLATFORM_KEY)/vendors/$(MCU_FAMILY)/$(MCU_FAMILY).mk)","")
+ # By MCU family e.g. STM32/STM32.mk
+ include $(PLATFORM_PATH)/$(PLATFORM_KEY)/vendors/$(MCU_FAMILY)/$(MCU_FAMILY).mk
+endif
+
+#
# ChibiOS-Contrib
##############################################################################
@@ -334,8 +351,11 @@ SHARED_CFLAGS = -fomit-frame-pointer \
-fno-common \
-fshort-wchar
+LDSCRIPT_PATH := $(shell dirname "$(LDSCRIPT)")
+
# Shared Linker flags for all toolchains
SHARED_LDFLAGS = -T $(LDSCRIPT) \
+ -L $(LDSCRIPT_PATH) \
-Wl,--gc-sections \
-nostartfiles
diff --git a/platforms/chibios/vendors/RP/RP2040.mk b/platforms/chibios/vendors/RP/RP2040.mk
new file mode 100644
index 0000000000..de426c9c40
--- /dev/null
+++ b/platforms/chibios/vendors/RP/RP2040.mk
@@ -0,0 +1,287 @@
+#
+# Raspberry Pi RP2040 specific drivers
+##############################################################################
+COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/vendor/$(MCU_FAMILY)/$(MCU_SERIES)
+
+ifeq ($(strip $(WS2812_DRIVER)), vendor)
+ OPT_DEFS += -DRP_DMA_REQUIRED=TRUE
+endif
+
+#
+# Raspberry Pi Pico SDK Support
+##############################################################################
+ADEFS += -DCRT0_VTOR_INIT=1 \
+ -DCRT0_EXTRA_CORES_NUMBER=0
+
+CFLAGS += -DPICO_NO_FPGA_CHECK \
+ -DNDEBUG
+
+#
+# Pico SDK source and header files needed by QMK and ChibiOS
+##############################################################################
+PICOSDKROOT := $(TOP_DIR)/lib/pico-sdk
+
+PICOSDKSRC = $(PICOSDKROOT)/src/rp2_common/hardware_clocks/clocks.c \
+ $(PICOSDKROOT)/src/rp2_common/hardware_pll/pll.c \
+ $(PICOSDKROOT)/src/rp2_common/hardware_pio/pio.c \
+ $(PICOSDKROOT)/src/rp2_common/hardware_flash/flash.c \
+ $(PICOSDKROOT)/src/rp2_common/hardware_gpio/gpio.c \
+ $(PICOSDKROOT)/src/rp2_common/hardware_claim/claim.c \
+ $(PICOSDKROOT)/src/rp2_common/hardware_watchdog/watchdog.c \
+ $(PICOSDKROOT)/src/rp2_common/hardware_xosc/xosc.c \
+ $(PICOSDKROOT)/src/rp2_common/pico_bootrom/bootrom.c
+
+PICOSDKINC = $(CHIBIOS)//os/various/pico_bindings/dumb/include \
+ $(PICOSDKROOT)/src/common/pico_base/include \
+ $(PICOSDKROOT)/src/rp2_common/pico_platform/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_base/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_clocks/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_claim/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_flash/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_gpio/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_irq/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_pll/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_pio/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_sync/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_resets/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_watchdog/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_xosc/include \
+ $(PICOSDKROOT)/src/rp2040/hardware_regs/include \
+ $(PICOSDKROOT)/src/rp2040/hardware_structs/include \
+ $(PICOSDKROOT)/src/boards/include \
+ $(PICOSDKROOT)/src/rp2_common/pico_bootrom/include
+
+PLATFORM_SRC += $(PICOSDKSRC)
+EXTRAINCDIRS += $(PICOSDKINC)
+
+PLATFORM_RP2040_PATH := $(PLATFORM_PATH)/$(PLATFORM_KEY)/vendors/$(MCU_FAMILY)
+
+PLATFORM_SRC += $(PLATFORM_RP2040_PATH)/stage2_bootloaders.c \
+ $(PLATFORM_RP2040_PATH)/pico_sdk_shims.c
+
+EXTRAINCDIRS += $(PLATFORM_RP2040_PATH)
+
+#
+# RP2040 optimized compiler intrinsics
+##############################################################################
+
+# Enables optimized Compiler intrinsics which are located in the RP2040
+# bootrom. This needs startup code and linker script support from ChibiOS,
+# which is WIP. Therefore disabled by default for now.
+RP2040_INTRINSICS_ENABLED ?= no
+ifeq ($(strip $(RP2040_INTRINSICS_ENABLED)), yes)
+ PICOSDKINTRINSICSSRC = $(PICOSDKROOT)/src/rp2_common/pico_float/float_aeabi.S \
+ $(PICOSDKROOT)/src/rp2_common/pico_float/float_math.c \
+ $(PICOSDKROOT)/src/rp2_common/pico_float/float_init_rom.c \
+ $(PICOSDKROOT)/src/rp2_common/pico_float/float_v1_rom_shim.S \
+ $(PICOSDKROOT)/src/rp2_common/pico_double/double_aeabi.S \
+ $(PICOSDKROOT)/src/rp2_common/pico_double/double_math.c \
+ $(PICOSDKROOT)/src/rp2_common/pico_double/double_init_rom.c \
+ $(PICOSDKROOT)/src/rp2_common/pico_double/double_v1_rom_shim.S \
+ $(PICOSDKROOT)/src/rp2_common/pico_divider/divider.S \
+ $(PICOSDKROOT)/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S \
+ $(PICOSDKROOT)/src/rp2_common/pico_mem_ops/mem_ops_aeabi.S \
+ $(PICOSDKROOT)/src/rp2_common/pico_malloc/pico_malloc.c \
+ $(PICOSDKROOT)/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S
+
+ PICOSDKINTRINSICSINC = $(PICOSDKROOT)/src/common/pico_base/include \
+ $(PICOSDKROOT)/src/rp2_common/pico_platfrom/include \
+ $(PICOSDKROOT)/src/rp2_common/pico_bootrom/include \
+ $(PICOSDKROOT)/src/rp2_common/hardware_divider/include \
+ $(PICOSDKROOT)/src/rp2_common/pico_float/include \
+ $(PICOSDKROOT)/src/rp2_common/pico_double/include \
+ $(PICOSDKROOT)/src/rp2_common/pico_malloc/include
+
+ OPT_DEFS += -DPICO_FLOAT_SUPPORT_ROM_V1=0 -DPICO_DOUBLE_SUPPORT_ROM_V1=0
+
+ CFLAGS += -Wl,--defsym=__StackLimit=__heap_end__
+ CFLAGS += -Wl,--defsym=__unhandled_user_irq=_unhandled_exception
+ CFLAGS += -Wl,--build-id=none
+
+ # single precision floating point intrinsics
+ OPT_DEFS += -DPICO_FLOAT_IN_RAM=1
+ OPT_DEFS += -DPICO_FLOAT_PROPAGATE_NANS=0
+
+ CFLAGS += -Wl,--wrap=__aeabi_fdiv
+ CFLAGS += -Wl,--wrap=__aeabi_fmul
+ CFLAGS += -Wl,--wrap=__aeabi_frsub
+ CFLAGS += -Wl,--wrap=__aeabi_fsub
+ CFLAGS += -Wl,--wrap=__aeabi_cfcmpeq
+ CFLAGS += -Wl,--wrap=__aeabi_cfrcmple
+ CFLAGS += -Wl,--wrap=__aeabi_cfcmple
+ CFLAGS += -Wl,--wrap=__aeabi_fcmpeq
+ CFLAGS += -Wl,--wrap=__aeabi_fcmplt
+ CFLAGS += -Wl,--wrap=__aeabi_fcmple
+ CFLAGS += -Wl,--wrap=__aeabi_fcmpge
+ CFLAGS += -Wl,--wrap=__aeabi_fcmpgt
+ CFLAGS += -Wl,--wrap=__aeabi_fcmpun
+ CFLAGS += -Wl,--wrap=__aeabi_i2f
+ CFLAGS += -Wl,--wrap=__aeabi_l2f
+ CFLAGS += -Wl,--wrap=__aeabi_ui2f
+ CFLAGS += -Wl,--wrap=__aeabi_ul2f
+ CFLAGS += -Wl,--wrap=__aeabi_i2f
+ CFLAGS += -Wl,--wrap=__aeabi_f2iz
+ CFLAGS += -Wl,--wrap=__aeabi_f2lz
+ CFLAGS += -Wl,--wrap=__aeabi_f2uiz
+ CFLAGS += -Wl,--wrap=__aeabi_f2ulz
+ CFLAGS += -Wl,--wrap=__aeabi_f2d
+ CFLAGS += -Wl,--wrap=sqrtf
+ CFLAGS += -Wl,--wrap=cosf
+ CFLAGS += -Wl,--wrap=sinf
+ CFLAGS += -Wl,--wrap=tanf
+ CFLAGS += -Wl,--wrap=atan2f
+ CFLAGS += -Wl,--wrap=expf
+ CFLAGS += -Wl,--wrap=logf
+ CFLAGS += -Wl,--wrap=ldexpf
+ CFLAGS += -Wl,--wrap=copysignf
+ CFLAGS += -Wl,--wrap=truncf
+ CFLAGS += -Wl,--wrap=floorf
+ CFLAGS += -Wl,--wrap=ceilf
+ CFLAGS += -Wl,--wrap=roundf
+ CFLAGS += -Wl,--wrap=sincosf
+ CFLAGS += -Wl,--wrap=asinf
+ CFLAGS += -Wl,--wrap=acosf
+ CFLAGS += -Wl,--wrap=atanf
+ CFLAGS += -Wl,--wrap=sinhf
+ CFLAGS += -Wl,--wrap=coshf
+ CFLAGS += -Wl,--wrap=tanhf
+ CFLAGS += -Wl,--wrap=asinhf
+ CFLAGS += -Wl,--wrap=acoshf
+ CFLAGS += -Wl,--wrap=atanhf
+ CFLAGS += -Wl,--wrap=exp2f
+ CFLAGS += -Wl,--wrap=log2f
+ CFLAGS += -Wl,--wrap=exp10f
+ CFLAGS += -Wl,--wrap=log10f
+ CFLAGS += -Wl,--wrap=powf
+ CFLAGS += -Wl,--wrap=powintf
+ CFLAGS += -Wl,--wrap=hypotf
+ CFLAGS += -Wl,--wrap=cbrtf
+ CFLAGS += -Wl,--wrap=fmodf
+ CFLAGS += -Wl,--wrap=dremf
+ CFLAGS += -Wl,--wrap=remainderf
+ CFLAGS += -Wl,--wrap=remquof
+ CFLAGS += -Wl,--wrap=expm1f
+ CFLAGS += -Wl,--wrap=log1pf
+ CFLAGS += -Wl,--wrap=fmaf
+
+ # double precision floating point intrinsics
+ OPT_DEFS += -DPICO_DOUBLE_IN_RAM=1
+ OPT_DEFS += -DPICO_DOUBLE_PROPAGATE_NANS=0
+
+ CFLAGS += -Wl,--wrap=__aeabi_dadd
+ CFLAGS += -Wl,--wrap=__aeabi_ddiv
+ CFLAGS += -Wl,--wrap=__aeabi_dmul
+ CFLAGS += -Wl,--wrap=__aeabi_drsub
+ CFLAGS += -Wl,--wrap=__aeabi_dsub
+ CFLAGS += -Wl,--wrap=__aeabi_cdcmpeq
+ CFLAGS += -Wl,--wrap=__aeabi_cdrcmple
+ CFLAGS += -Wl,--wrap=__aeabi_cdcmple
+ CFLAGS += -Wl,--wrap=__aeabi_dcmpeq
+ CFLAGS += -Wl,--wrap=__aeabi_dcmplt
+ CFLAGS += -Wl,--wrap=__aeabi_dcmple
+ CFLAGS += -Wl,--wrap=__aeabi_dcmpge
+ CFLAGS += -Wl,--wrap=__aeabi_dcmpgt
+ CFLAGS += -Wl,--wrap=__aeabi_dcmpun
+ CFLAGS += -Wl,--wrap=__aeabi_i2d
+ CFLAGS += -Wl,--wrap=__aeabi_l2d
+ CFLAGS += -Wl,--wrap=__aeabi_ui2d
+ CFLAGS += -Wl,--wrap=__aeabi_ul2d
+ CFLAGS += -Wl,--wrap=__aeabi_d2iz
+ CFLAGS += -Wl,--wrap=__aeabi_d2lz
+ CFLAGS += -Wl,--wrap=__aeabi_d2uiz
+ CFLAGS += -Wl,--wrap=__aeabi_d2ulz
+ CFLAGS += -Wl,--wrap=__aeabi_d2f
+ CFLAGS += -Wl,--wrap=sqrt
+ CFLAGS += -Wl,--wrap=cos
+ CFLAGS += -Wl,--wrap=sin
+ CFLAGS += -Wl,--wrap=tan
+ CFLAGS += -Wl,--wrap=atan2
+ CFLAGS += -Wl,--wrap=exp
+ CFLAGS += -Wl,--wrap=log
+ CFLAGS += -Wl,--wrap=ldexp
+ CFLAGS += -Wl,--wrap=copysign
+ CFLAGS += -Wl,--wrap=trunc
+ CFLAGS += -Wl,--wrap=floor
+ CFLAGS += -Wl,--wrap=ceil
+ CFLAGS += -Wl,--wrap=round
+ CFLAGS += -Wl,--wrap=sincos
+ CFLAGS += -Wl,--wrap=asin
+ CFLAGS += -Wl,--wrap=acos
+ CFLAGS += -Wl,--wrap=atan
+ CFLAGS += -Wl,--wrap=sinh
+ CFLAGS += -Wl,--wrap=cosh
+ CFLAGS += -Wl,--wrap=tanh
+ CFLAGS += -Wl,--wrap=asinh
+ CFLAGS += -Wl,--wrap=acosh
+ CFLAGS += -Wl,--wrap=atanh
+ CFLAGS += -Wl,--wrap=exp2
+ CFLAGS += -Wl,--wrap=log2
+ CFLAGS += -Wl,--wrap=exp10
+ CFLAGS += -Wl,--wrap=log10
+ CFLAGS += -Wl,--wrap=pow
+ CFLAGS += -Wl,--wrap=powint
+ CFLAGS += -Wl,--wrap=hypot
+ CFLAGS += -Wl,--wrap=cbrt
+ CFLAGS += -Wl,--wrap=fmod
+ CFLAGS += -Wl,--wrap=drem
+ CFLAGS += -Wl,--wrap=remainder
+ CFLAGS += -Wl,--wrap=remquo
+ CFLAGS += -Wl,--wrap=expm1
+ CFLAGS += -Wl,--wrap=log1p
+ CFLAGS += -Wl,--wrap=fma
+
+ # bit operation intrinsics
+ OPT_DEFS += -DPICO_BITS_IN_RAM=1
+
+ CFLAGS += -Wl,--wrap=__clzsi2
+ CFLAGS += -Wl,--wrap=__clzsi2
+ CFLAGS += -Wl,--wrap=__clzdi2
+ CFLAGS += -Wl,--wrap=__ctzsi2
+ CFLAGS += -Wl,--wrap=__ctzdi2
+ CFLAGS += -Wl,--wrap=__popcountsi2
+ CFLAGS += -Wl,--wrap=__popcountdi2
+ CFLAGS += -Wl,--wrap=__clz
+ CFLAGS += -Wl,--wrap=__clzl
+ CFLAGS += -Wl,--wrap=__clzsi2
+ CFLAGS += -Wl,--wrap=__clzll
+
+ # integer division intrinsics
+ OPT_DEFS += -DPICO_DIVIDER_IN_RAM=1
+ OPT_DEFS += -DPICO_DIVIDER_DISABLE_INTERRUPTS=1
+
+ CFLAGS += -Wl,--wrap=__aeabi_idiv
+ CFLAGS += -Wl,--wrap=__aeabi_idivmod
+ CFLAGS += -Wl,--wrap=__aeabi_ldivmod
+ CFLAGS += -Wl,--wrap=__aeabi_uidiv
+ CFLAGS += -Wl,--wrap=__aeabi_uidivmod
+ CFLAGS += -Wl,--wrap=__aeabi_uldivmod
+
+ # 64bit integer intrinsics
+ OPT_DEFS += -DPICO_INT64_OPS_IN_RAM=1
+
+ CFLAGS += -Wl,--wrap=__aeabi_lmul
+
+ # malloc and friends functions
+ OPT_DEFS += -DPICO_USE_MALLOC_MUTEX=0
+ OPT_DEFS += -DPICO_DEBUG_MALLOC=0
+ OPT_DEFS ?= -DPICO_MALLOC_PANIC=0
+
+ CFLAGS += -Wl,--wrap=malloc
+ CFLAGS += -Wl,--wrap=calloc
+ CFLAGS += -Wl,--wrap=free
+
+ # memory operation intrinsics
+ OPT_DEFS += -DPICO_MEM_IN_RAM=1
+
+ CFLAGS += -Wl,--wrap=memcpy
+ CFLAGS += -Wl,--wrap=memset
+ CFLAGS += -Wl,--wrap=__aeabi_memcpy
+ CFLAGS += -Wl,--wrap=__aeabi_memset
+ CFLAGS += -Wl,--wrap=__aeabi_memcpy4
+ CFLAGS += -Wl,--wrap=__aeabi_memset4
+ CFLAGS += -Wl,--wrap=__aeabi_memcpy8
+ CFLAGS += -Wl,--wrap=__aeabi_memset8
+
+ PLATFORM_SRC += $(PICOSDKINTRINSICSSRC)
+ EXTRAINCDIRS += $(PICOSDKINTRINSICSINC)
+endif
diff --git a/platforms/chibios/vendors/RP/_pin_defs.h b/platforms/chibios/vendors/RP/_pin_defs.h
new file mode 100644
index 0000000000..4241845369
--- /dev/null
+++ b/platforms/chibios/vendors/RP/_pin_defs.h
@@ -0,0 +1,37 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+/* RP2040 GPIO Numbering */
+#define GP0 0U
+#define GP1 1U
+#define GP2 2U
+#define GP3 3U
+#define GP4 4U
+#define GP5 5U
+#define GP6 6U
+#define GP7 7U
+#define GP8 8U
+#define GP9 9U
+#define GP10 10U
+#define GP11 11U
+#define GP12 12U
+#define GP13 13U
+#define GP14 14U
+#define GP15 15U
+#define GP16 16U
+#define GP17 17U
+#define GP18 18U
+#define GP19 19U
+#define GP20 20U
+#define GP21 21U
+#define GP22 22U
+#define GP23 23U
+#define GP24 24U
+#define GP25 25U
+#define GP26 26U
+#define GP27 27U
+#define GP28 28U
+#define GP29 29U
+#define GP30 30U
diff --git a/platforms/chibios/vendors/RP/pico_sdk_shims.c b/platforms/chibios/vendors/RP/pico_sdk_shims.c
new file mode 100644
index 0000000000..239155c086
--- /dev/null
+++ b/platforms/chibios/vendors/RP/pico_sdk_shims.c
@@ -0,0 +1,13 @@
+// Copyright 2022 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <stdbool.h>
+#include <ch.h>
+
+void panic(const char *fmt, ...) {
+ chSysHalt(fmt);
+}
+
+void hard_assertion_failure(void) {
+ panic("hard assert");
+}
diff --git a/platforms/chibios/vendors/RP/stage2_bootloaders.c b/platforms/chibios/vendors/RP/stage2_bootloaders.c
new file mode 100644
index 0000000000..e65b0a5802
--- /dev/null
+++ b/platforms/chibios/vendors/RP/stage2_bootloaders.c
@@ -0,0 +1,178 @@
+// ----------------------------------------------------------------------------
+// Pre-compiled second stage boot code for RP2040.
+//
+// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.
+// SPDX-License-Identifier: BSD-3-Clause
+// ----------------------------------------------------------------------------
+
+#include <stdint.h>
+
+#define BOOTLOADER_SECTION __attribute__((used, section(".boot2")))
+
+// clang-format off
+
+#if defined(RP2040_FLASH_AT25SF128A)
+
+uint8_t BOOTLOADER_SECTION BOOT2_ROM[256] = {
+ 0x00, 0xb5, 0x31, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21,
+ 0x88, 0x43, 0x98, 0x60, 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2d, 0x4b,
+ 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61, 0x01, 0x21, 0xf0, 0x22,
+ 0x99, 0x50, 0x2a, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20,
+ 0x00, 0xf0, 0x42, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x12, 0xd0, 0x06, 0x21,
+ 0x19, 0x66, 0x00, 0xf0, 0x32, 0xf8, 0x19, 0x6e, 0x31, 0x21, 0x19, 0x66,
+ 0x1a, 0x66, 0x00, 0xf0, 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e,
+ 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21, 0x08, 0x42, 0xf9, 0xd1,
+ 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60,
+ 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21,
+ 0x19, 0x66, 0x20, 0x21, 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21,
+ 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60,
+ 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49,
+ 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5,
+ 0x99, 0x6a, 0x04, 0x20, 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42,
+ 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66, 0x18, 0x66, 0xff, 0xf7,
+ 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00,
+ 0x21, 0x22, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0x20,
+ 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0xdd, 0xc0, 0xb5
+};
+
+#elif defined(RP2040_FLASH_GD25Q64CS)
+
+uint8_t BOOTLOADER_SECTION BOOT2_ROM[256] = {
+ 0x00, 0xb5, 0x31, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21,
+ 0x88, 0x43, 0x98, 0x60, 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2d, 0x4b,
+ 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61, 0x01, 0x21, 0xf0, 0x22,
+ 0x99, 0x50, 0x2a, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20,
+ 0x00, 0xf0, 0x42, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x12, 0xd0, 0x06, 0x21,
+ 0x19, 0x66, 0x00, 0xf0, 0x32, 0xf8, 0x19, 0x6e, 0x31, 0x21, 0x19, 0x66,
+ 0x1a, 0x66, 0x00, 0xf0, 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e,
+ 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21, 0x08, 0x42, 0xf9, 0xd1,
+ 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60,
+ 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xe7, 0x21,
+ 0x19, 0x66, 0xa0, 0x21, 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21,
+ 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60,
+ 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49,
+ 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5,
+ 0x99, 0x6a, 0x04, 0x20, 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42,
+ 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66, 0x18, 0x66, 0xff, 0xf7,
+ 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00,
+ 0x21, 0x12, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x18, 0x22, 0x10, 0x00, 0xa0,
+ 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe2, 0xd9, 0xa2, 0xb5
+};
+
+#elif defined(RP2040_FLASH_W25X10CL)
+
+uint8_t BOOTLOADER_SECTION BOOT2_ROM[256] = {
+ 0x00, 0xb5, 0x14, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61,
+ 0x12, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60, 0x11, 0x49, 0x12, 0x48,
+ 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xbb, 0x21, 0x19, 0x66, 0x02, 0x21,
+ 0x19, 0x66, 0x08, 0x21, 0x98, 0x6a, 0x08, 0x42, 0xfc, 0xd0, 0x00, 0x21,
+ 0x99, 0x60, 0x0c, 0x49, 0x0a, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60,
+ 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x08, 0x48, 0x09, 0x49,
+ 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x3f, 0x00, 0x1d, 0x12, 0x00, 0x00,
+ 0xf4, 0x00, 0x00, 0x18, 0x1e, 0x10, 0x00, 0x20, 0x00, 0x01, 0x00, 0x10,
+ 0x08, 0xed, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7c, 0x81, 0x53, 0x9a
+};
+
+#elif defined(RP2040_FLASH_IS25LP080)
+
+uint8_t BOOTLOADER_SECTION BOOT2_ROM[256] = {
+ 0x00, 0xb5, 0x2b, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61,
+ 0x29, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x28, 0x48, 0x00, 0xf0,
+ 0x42, 0xf8, 0x28, 0x4a, 0x90, 0x42, 0x12, 0xd0, 0x06, 0x21, 0x19, 0x66,
+ 0x00, 0xf0, 0x32, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20,
+ 0x1a, 0x66, 0x00, 0xf0, 0x2b, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x1f, 0x48,
+ 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21, 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21,
+ 0x99, 0x60, 0x1d, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60, 0x1c, 0x49,
+ 0x1c, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66,
+ 0xa0, 0x21, 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60,
+ 0x17, 0x49, 0x16, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc,
+ 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x14, 0x48, 0x14, 0x49, 0x08, 0x60,
+ 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a,
+ 0x04, 0x20, 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1,
+ 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66, 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff,
+ 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x00, 0x00, 0x07, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x18,
+ 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x33, 0x43, 0xb2
+};
+
+#elif defined(RP2040_FLASH_GENERIC_03H)
+
+uint8_t BOOTLOADER_SECTION BOOT2_ROM[256] = {
+ 0x00, 0xb5, 0x0c, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61,
+ 0x0a, 0x49, 0x19, 0x60, 0x0a, 0x49, 0x0b, 0x48, 0x01, 0x60, 0x00, 0x21,
+ 0x59, 0x60, 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0,
+ 0x00, 0x47, 0x07, 0x48, 0x07, 0x49, 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3,
+ 0x08, 0x88, 0x08, 0x47, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x1f, 0x00,
+ 0x18, 0x02, 0x00, 0x03, 0xf4, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x10,
+ 0x08, 0xed, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2c, 0xec, 0x21, 0x0d
+};
+
+#else
+
+uint8_t BOOTLOADER_SECTION BOOT2_ROM[256] = {
+ 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21,
+ 0x88, 0x43, 0x98, 0x60, 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b,
+ 0x00, 0x21, 0x99, 0x60, 0x04, 0x21, 0x59, 0x61, 0x01, 0x21, 0xf0, 0x22,
+ 0x99, 0x50, 0x2b, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20,
+ 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21,
+ 0x19, 0x66, 0x00, 0xf0, 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66,
+ 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0, 0x2c, 0xf8, 0x19, 0x6e,
+ 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21,
+ 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60,
+ 0x00, 0x21, 0x59, 0x60, 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21,
+ 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21, 0x19, 0x66, 0x00, 0xf0,
+ 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60,
+ 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47,
+ 0x12, 0x48, 0x13, 0x49, 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88,
+ 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20, 0x01, 0x42, 0xfb, 0xd0,
+ 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66,
+ 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd,
+ 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00,
+ 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x18,
+ 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x0b, 0x8f, 0xd5
+};
+
+#endif
+
+// clang-format on
diff --git a/platforms/eeprom.h b/platforms/eeprom.h
index 091e6e4400..8cb7e342dc 100644
--- a/platforms/eeprom.h
+++ b/platforms/eeprom.h
@@ -27,6 +27,8 @@ void eeprom_update_block(const void *__src, void *__dst, size_t __n);
# error EEPROM_SIZE has not been defined for custom driver.
# endif
# define TOTAL_EEPROM_BYTE_COUNT (EEPROM_SIZE)
+#elif defined(EEPROM_WEAR_LEVELING)
+# define TOTAL_EEPROM_BYTE_COUNT (WEAR_LEVELING_LOGICAL_SIZE)
#elif defined(EEPROM_TRANSIENT)
# include "eeprom_transient.h"
# define TOTAL_EEPROM_BYTE_COUNT (TRANSIENT_EEPROM_SIZE)
diff --git a/platforms/synchronization_util.h b/platforms/synchronization_util.h
index 3730f271db..59933945c3 100644
--- a/platforms/synchronization_util.h
+++ b/platforms/synchronization_util.h
@@ -9,6 +9,40 @@ void split_shared_memory_lock(void);
void split_shared_memory_unlock(void);
# endif
#else
+# if defined(SPLIT_KEYBOARD)
inline void split_shared_memory_lock(void){};
inline void split_shared_memory_unlock(void){};
+# endif
+#endif
+
+/* GCCs cleanup attribute expects a function with one parameter, which is a
+ * pointer to a type compatible with the variable. As we don't want to expose
+ * the platforms internal mutex type this workaround with auto generated adapter
+ * function is defined */
+#define QMK_DECLARE_AUTOUNLOCK_HELPERS(prefix) \
+ inline unsigned prefix##_autounlock_lock_helper(void) { \
+ prefix##_lock(); \
+ return 0; \
+ } \
+ \
+ inline void prefix##_autounlock_unlock_helper(unsigned* unused_guard) { \
+ prefix##_unlock(); \
+ }
+
+/* Convinience macro the automatically generate the correct RAII-style
+ * lock_autounlock function macro */
+#define QMK_DECLARE_AUTOUNLOCK_CALL(prefix) unsigned prefix##_guard __attribute__((unused, cleanup(prefix##_autounlock_unlock_helper))) = prefix##_autounlock_lock_helper
+
+#if defined(SPLIT_KEYBOARD)
+QMK_DECLARE_AUTOUNLOCK_HELPERS(split_shared_memory)
+
+/**
+ * @brief Acquire exclusive access to the split keyboard shared memory, by
+ * calling the platforms `split_shared_memory_lock()` function. The lock is
+ * automatically released by calling the platforms `split_shared_memory_unlock()`
+ * function. This happens when the block where
+ * `split_shared_memory_lock_autounlock()` is called in goes out of scope i.e.
+ * when the enclosing function returns.
+ */
+# define split_shared_memory_lock_autounlock QMK_DECLARE_AUTOUNLOCK_CALL(split_shared_memory)
#endif
diff --git a/platforms/test/platform.mk b/platforms/test/platform.mk
index eb2424ec5c..f07c863e69 100644
--- a/platforms/test/platform.mk
+++ b/platforms/test/platform.mk
@@ -31,4 +31,4 @@ CFLAGS += -fno-strict-aliasing
CXXFLAGS += $(COMPILEFLAGS)
CXXFLAGS += -fno-exceptions
-CXXFLAGS += -std=gnu++11
+CXXFLAGS += $(CXXSTANDARD)
diff --git a/platforms/test/rules.mk b/platforms/test/rules.mk
index 55512c7392..a2baa283d0 100644
--- a/platforms/test/rules.mk
+++ b/platforms/test/rules.mk
@@ -11,7 +11,8 @@ eeprom_stm32_large_DEFS := $(eeprom_stm32_DEFS) \
-DFEE_PAGE_COUNT=16
eeprom_stm32_INC := \
- $(PLATFORM_PATH)/chibios/
+ $(PLATFORM_PATH)/chibios/drivers/eeprom/ \
+ $(PLATFORM_PATH)/chibios/drivers/flash/
eeprom_stm32_tiny_INC := $(eeprom_stm32_INC)
eeprom_stm32_large_INC := $(eeprom_stm32_INC)
@@ -19,6 +20,6 @@ eeprom_stm32_SRC := \
$(TOP_DIR)/drivers/eeprom/eeprom_driver.c \
$(PLATFORM_PATH)/$(PLATFORM_KEY)/eeprom_stm32_tests.cpp \
$(PLATFORM_PATH)/$(PLATFORM_KEY)/flash_stm32_mock.c \
- $(PLATFORM_PATH)/chibios/eeprom_stm32.c
+ $(PLATFORM_PATH)/chibios/drivers/eeprom/eeprom_stm32.c
eeprom_stm32_tiny_SRC := $(eeprom_stm32_SRC)
eeprom_stm32_large_SRC := $(eeprom_stm32_SRC)
diff --git a/quantum/action.c b/quantum/action.c
index 4e81a5466f..83f6e2a970 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -844,7 +844,7 @@ __attribute__((weak)) void register_code(uint8_t code) {
# endif
add_key(KC_CAPS_LOCK);
send_keyboard_report();
- wait_ms(100);
+ wait_ms(TAP_HOLD_CAPS_DELAY);
del_key(KC_CAPS_LOCK);
send_keyboard_report();
}
diff --git a/quantum/action_layer.h b/quantum/action_layer.h
index b87d096eed..bd1085a70f 100644
--- a/quantum/action_layer.h
+++ b/quantum/action_layer.h
@@ -41,7 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#if !defined(LAYER_STATE_8BIT) && !defined(LAYER_STATE_16BIT) && !defined(LAYER_STATE_32BIT)
-# define LAYER_STATE_32BIT
+# define LAYER_STATE_16BIT
#endif
#if defined(LAYER_STATE_8BIT)
diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c
index 3c8b5678b7..df3317ac05 100644
--- a/quantum/action_tapping.c
+++ b/quantum/action_tapping.c
@@ -125,7 +125,7 @@ void action_tapping_process(keyrecord_t record) {
/* return true when key event is processed or consumed. */
bool process_tapping(keyrecord_t *keyp) {
keyevent_t event = keyp->event;
-# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(TAPPING_TERM_PER_KEY) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(TAPPING_FORCE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
+# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(TAPPING_FORCE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
uint16_t tapping_keycode = get_record_keycode(&tapping_key, false);
# endif
@@ -164,17 +164,15 @@ bool process_tapping(keyrecord_t *keyp) {
* useful for long TAPPING_TERM but may prevent fast typing.
*/
// clang-format off
-# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
+# if defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
else if (
(
- (
- GET_TAPPING_TERM(tapping_keycode, &tapping_key) >= 500
+ IS_RELEASED(event) && waiting_buffer_typed(event)
# ifdef PERMISSIVE_HOLD_PER_KEY
- || get_permissive_hold(tapping_keycode, &tapping_key)
+ && get_permissive_hold(tapping_keycode, &tapping_key)
# elif defined(PERMISSIVE_HOLD)
- || true
+ && true
# endif
- ) && IS_RELEASED(event) && waiting_buffer_typed(event)
)
// Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
// unnecessarily and fixes them for Layer Taps.
diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h
index 3e425abb47..ff22e6fe95 100644
--- a/quantum/audio/song_list.h
+++ b/quantum/audio/song_list.h
@@ -144,6 +144,12 @@
*/
#define USSR_ANTHEM B__NOTE(_G6), B__NOTE(_C7), W__NOTE(_G6), H__NOTE(_A6), B__NOTE(_B6), W__NOTE(_E6), W__NOTE(_E6), B__NOTE(_A6), W__NOTE(_G6), H__NOTE(_F6), B__NOTE(_G6), W__NOTE(_C6), W__NOTE(_C6), B__NOTE(_D6), W__NOTE(_D6), W__NOTE(_E6), B__NOTE(_D6), W__NOTE(_D6), W__NOTE(_G6), B__NOTE(_F6), W__NOTE(_G6), W__NOTE(_A6), B__NOTE(_B6),
+/* Title: Hymn Risen
+ * Author/Composer: Terrance Andrew Davis
+ * License: Public Domain
+ */
+#define TOS_HYMN_RISEN H__NOTE(_D5), H__NOTE(_E5), HD_NOTE(_F5), HD_NOTE(_F5), H__NOTE(_F5), HD_NOTE(_D5), E__NOTE(_E5), E__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_D5), Q__NOTE(_D5), H__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_G5), Q__NOTE(_F5), H__NOTE(_D5), H__NOTE(_E5), HD_NOTE(_F5), HD_NOTE(_F5), H__NOTE(_F5), HD_NOTE(_D5), E__NOTE(_E5), E__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_D5), Q__NOTE(_D5), H__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_G5), Q__NOTE(_F5), H__NOTE(_D5), H__NOTE(_C5), W__NOTE(_D5), W__NOTE(_E5), Q__NOTE(_A4), H__NOTE(_A4), Q__NOTE(_E5), Q__NOTE(_E5), Q__NOTE(_F5), Q__NOTE(_E5), Q__NOTE(_D5), Q__NOTE(_G5), Q__NOTE(_B4), Q__NOTE(_D5), Q__NOTE(_C5), M__NOTE(_F5, 80), H__NOTE(_D5), H__NOTE(_C5), W__NOTE(_D5), W__NOTE(_E5), Q__NOTE(_A4), H__NOTE(_A4), Q__NOTE(_E5), Q__NOTE(_E5), Q__NOTE(_F5), Q__NOTE(_E5), Q__NOTE(_D5), Q__NOTE(_G5), Q__NOTE(_B4), Q__NOTE(_D5), Q__NOTE(_C5), M__NOTE(_F5, 80)
+
/* Removed sounds
+ This list is here solely for compatibility, so that removed songs don't just break things
* If you think that any of these songs were wrongfully removed, let us know and provide
diff --git a/quantum/keyboard.c b/quantum/keyboard.c
index a65f9d6d18..8273299a9a 100644
--- a/quantum/keyboard.c
+++ b/quantum/keyboard.c
@@ -381,7 +381,7 @@ void keyboard_init(void) {
#ifdef ENCODER_ENABLE
encoder_init();
#endif
-#ifdef STENO_ENABLE
+#ifdef STENO_ENABLE_ALL
steno_init();
#endif
#ifdef POINTING_DEVICE_ENABLE
diff --git a/quantum/keymap.h b/quantum/keymap.h
index d64b271efb..edff484129 100644
--- a/quantum/keymap.h
+++ b/quantum/keymap.h
@@ -46,6 +46,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "quantum_keycodes.h"
+// Gross hack, remove me and change RESET keycode to QK_BOOT
+#if defined(MCU_RP)
+# undef RESET
+#endif
+
// translates key to keycode
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
@@ -55,3 +60,5 @@ extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
// Ensure we have a forward declaration for the encoder map
# include "encoder.h"
#endif
+
+#include "keymap_introspection.h"
diff --git a/quantum/keymap_extras/keymap_steno.h b/quantum/keymap_extras/keymap_steno.h
index e888ccd643..07d96b7465 100644
--- a/quantum/keymap_extras/keymap_steno.h
+++ b/quantum/keymap_extras/keymap_steno.h
@@ -89,3 +89,31 @@ enum steno_combined_keycodes {
STN_COMB_MAX = STN_EU,
};
#endif
+
+#ifdef STENO_ENABLE_BOLT
+// TxBolt Codes
+# define TXB_NUL 0
+# define TXB_S_L 0b00000001
+# define TXB_T_L 0b00000010
+# define TXB_K_L 0b00000100
+# define TXB_P_L 0b00001000
+# define TXB_W_L 0b00010000
+# define TXB_H_L 0b00100000
+# define TXB_R_L 0b01000001
+# define TXB_A_L 0b01000010
+# define TXB_O_L 0b01000100
+# define TXB_STR 0b01001000
+# define TXB_E_R 0b01010000
+# define TXB_U_R 0b01100000
+# define TXB_F_R 0b10000001
+# define TXB_R_R 0b10000010
+# define TXB_P_R 0b10000100
+# define TXB_B_R 0b10001000
+# define TXB_L_R 0b10010000
+# define TXB_G_R 0b10100000
+# define TXB_T_R 0b11000001
+# define TXB_S_R 0b11000010
+# define TXB_D_R 0b11000100
+# define TXB_Z_R 0b11001000
+# define TXB_NUM 0b11010000
+#endif // STENO_ENABLE_BOLT
diff --git a/quantum/keymap_introspection.c b/quantum/keymap_introspection.c
new file mode 100644
index 0000000000..9628b41eef
--- /dev/null
+++ b/quantum/keymap_introspection.c
@@ -0,0 +1,25 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+// Pull the actual keymap code so that we can inspect stuff from it
+#include KEYMAP_C
+
+#include "keymap_introspection.h"
+
+#define NUM_KEYMAP_LAYERS ((uint8_t)(sizeof(keymaps) / ((MATRIX_ROWS) * (MATRIX_COLS) * sizeof(uint16_t))))
+
+uint8_t keymap_layer_count(void) {
+ return NUM_KEYMAP_LAYERS;
+}
+
+#if defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)
+
+# define NUM_ENCODERMAP_LAYERS ((uint8_t)(sizeof(encoder_map) / ((NUM_ENCODERS) * (2) * sizeof(uint16_t))))
+
+uint8_t encodermap_layer_count(void) {
+ return NUM_ENCODERMAP_LAYERS;
+}
+
+_Static_assert(NUM_KEYMAP_LAYERS == NUM_ENCODERMAP_LAYERS, "Number of encoder_map layers doesn't match the number of keymap layers");
+
+#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)
diff --git a/quantum/keymap_introspection.h b/quantum/keymap_introspection.h
new file mode 100644
index 0000000000..23f6f2016f
--- /dev/null
+++ b/quantum/keymap_introspection.h
@@ -0,0 +1,15 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#include <stdint.h>
+
+// Get the number of layers defined in the keymap
+uint8_t keymap_layer_count(void);
+
+#if defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)
+
+// Get the number of layers defined in the encoder map
+uint8_t encodermap_layer_count(void);
+
+#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)
diff --git a/quantum/mousekey.c b/quantum/mousekey.c
index c5e3f8bcda..25a89bdba7 100644
--- a/quantum/mousekey.c
+++ b/quantum/mousekey.c
@@ -66,11 +66,18 @@ uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
/* milliseconds between the initial key press and first repeated motion event (0-2550) */
uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10;
/* milliseconds between repeated motion events (0-255) */
-uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL;
+# ifdef MK_KINETIC_SPEED
+float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
+# else
+uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL;
+# endif
uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
# ifndef MK_COMBINED
+# ifndef MK_KINETIC_SPEED
+
+/* Default accelerated mode */
static uint8_t move_unit(void) {
uint16_t unit;
@@ -108,8 +115,7 @@ static uint8_t wheel_unit(void) {
return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
}
-# else /* #ifndef MK_COMBINED */
-# ifdef MK_KINETIC_SPEED
+# else /* #ifndef MK_KINETIC_SPEED */
/*
* Kinetic movement acceleration algorithm
@@ -147,27 +153,27 @@ static uint8_t move_unit(void) {
return speed > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : speed;
}
-float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
-
static uint8_t wheel_unit(void) {
float speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
if (mousekey_accel & ((1 << 0) | (1 << 2))) {
speed = mousekey_accel & (1 << 2) ? MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS : MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS;
- } else if (mousekey_repeat && mouse_timer) {
+ } else if (mousekey_wheel_repeat && mouse_timer) {
if (mk_wheel_interval != MOUSEKEY_WHEEL_BASE_MOVEMENTS) {
const float time_elapsed = timer_elapsed(mouse_timer) / 50;
speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS + 1 * time_elapsed + 1 * 0.5 * time_elapsed * time_elapsed;
}
speed = speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS ? MOUSEKEY_WHEEL_BASE_MOVEMENTS : speed;
}
-
mk_wheel_interval = 1000.0f / speed;
- return 1;
+ return (uint8_t)speed > MOUSEKEY_WHEEL_INITIAL_MOVEMENTS ? 2 : 1;
}
-# else /* #ifndef MK_KINETIC_SPEED */
+# endif /* #ifndef MK_KINETIC_SPEED */
+# else /* #ifndef MK_COMBINED */
+
+/* Combined mode */
static uint8_t move_unit(void) {
uint16_t unit;
@@ -205,8 +211,7 @@ static uint8_t wheel_unit(void) {
return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
}
-# endif /* #ifndef MK_KINETIC_SPEED */
-# endif /* #ifndef MK_COMBINED */
+# endif /* #ifndef MK_COMBINED */
void mousekey_task(void) {
// report cursor and scroll movement independently
diff --git a/quantum/mousekey.h b/quantum/mousekey.h
index 1714e52ff6..da2edb481a 100644
--- a/quantum/mousekey.h
+++ b/quantum/mousekey.h
@@ -39,7 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# ifndef MK_KINETIC_SPEED
# define MOUSEKEY_MOVE_DELTA 8
# else
-# define MOUSEKEY_MOVE_DELTA 5
+# define MOUSEKEY_MOVE_DELTA 16
# endif
# endif
# ifndef MOUSEKEY_WHEEL_DELTA
@@ -82,7 +82,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# define MOUSEKEY_INITIAL_SPEED 100
# endif
# ifndef MOUSEKEY_BASE_SPEED
-# define MOUSEKEY_BASE_SPEED 1000
+# define MOUSEKEY_BASE_SPEED 5000
# endif
# ifndef MOUSEKEY_DECELERATED_SPEED
# define MOUSEKEY_DECELERATED_SPEED 400
diff --git a/quantum/painter/qp.h b/quantum/painter/qp.h
index e1c14d156c..47f077d0cf 100644
--- a/quantum/painter/qp.h
+++ b/quantum/painter/qp.h
@@ -440,6 +440,10 @@ int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, pai
# include "qp_ili9341.h"
#endif // QUANTUM_PAINTER_ILI9341_ENABLE
+#ifdef QUANTUM_PAINTER_ILI9488_ENABLE
+# include "qp_ili9488.h"
+#endif // QUANTUM_PAINTER_ILI9488_ENABLE
+
#ifdef QUANTUM_PAINTER_ST7789_ENABLE
# include "qp_st7789.h"
#endif // QUANTUM_PAINTER_ST7789_ENABLE
diff --git a/quantum/painter/rules.mk b/quantum/painter/rules.mk
index 9115d3d406..675a1a5460 100644
--- a/quantum/painter/rules.mk
+++ b/quantum/painter/rules.mk
@@ -3,7 +3,7 @@ QUANTUM_PAINTER_DRIVERS ?=
QUANTUM_PAINTER_ANIMATIONS_ENABLE ?= yes
# The list of permissible drivers that can be listed in QUANTUM_PAINTER_DRIVERS
-VALID_QUANTUM_PAINTER_DRIVERS := ili9163_spi ili9341_spi st7789_spi gc9a01_spi ssd1351_spi
+VALID_QUANTUM_PAINTER_DRIVERS := ili9163_spi ili9341_spi ili9488_spi st7789_spi gc9a01_spi ssd1351_spi
#-------------------------------------------------------------------------------
@@ -61,6 +61,17 @@ define handle_quantum_painter_driver
$(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \
$(DRIVER_PATH)/painter/ili9xxx/qp_ili9341.c \
+ else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),ili9488_spi)
+ QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
+ QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
+ OPT_DEFS += -DQUANTUM_PAINTER_ILI9488_ENABLE -DQUANTUM_PAINTER_ILI9488_SPI_ENABLE
+ COMMON_VPATH += \
+ $(DRIVER_PATH)/painter/tft_panel \
+ $(DRIVER_PATH)/painter/ili9xxx
+ SRC += \
+ $(DRIVER_PATH)/painter/tft_panel/qp_tft_panel.c \
+ $(DRIVER_PATH)/painter/ili9xxx/qp_ili9488.c \
+
else ifeq ($$(strip $$(CURRENT_PAINTER_DRIVER)),st7789_spi)
QUANTUM_PAINTER_NEEDS_COMMS_SPI := yes
QUANTUM_PAINTER_NEEDS_COMMS_SPI_DC_RESET := yes
diff --git a/quantum/pointing_device.c b/quantum/pointing_device.c
index a160647890..3aa4941687 100644
--- a/quantum/pointing_device.c
+++ b/quantum/pointing_device.c
@@ -25,6 +25,13 @@
#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
# error More than one rotation selected. This is not supported.
#endif
+
+#if defined(POINTING_DEVICE_LEFT) || defined(POINTING_DEVICE_RIGHT) || defined(POINTING_DEVICE_COMBINED)
+# ifndef SPLIT_POINTING_ENABLE
+# error "Using POINTING_DEVICE_LEFT or POINTING_DEVICE_RIGHT or POINTING_DEVICE_COMBINED, then SPLIT_POINTING_ENABLE is required but has not been defined"
+# endif
+#endif
+
#if defined(SPLIT_POINTING_ENABLE)
# include "transactions.h"
# include "keyboard.h"
@@ -177,7 +184,8 @@ __attribute__((weak)) void pointing_device_send(void) {
report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report) {
// Support rotation of the sensor data
#if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270)
- int8_t x = mouse_report.x, y = mouse_report.y;
+ mouse_xy_report_t x = mouse_report.x;
+ mouse_xy_report_t y = mouse_report.y;
# if defined(POINTING_DEVICE_ROTATION_90)
mouse_report.x = y;
mouse_report.y = -x;
@@ -347,7 +355,7 @@ void pointing_device_set_cpi_on_side(bool left, uint16_t cpi) {
* @param[in] int16_t value
* @return int8_t clamped value
*/
-static inline int8_t pointing_device_movement_clamp(int16_t value) {
+static inline int8_t pointing_device_hv_clamp(int16_t value) {
if (value < INT8_MIN) {
return INT8_MIN;
} else if (value > INT8_MAX) {
@@ -358,6 +366,21 @@ static inline int8_t pointing_device_movement_clamp(int16_t value) {
}
/**
+ * @brief clamps int16_t to int8_t
+ *
+ * @param[in] clamp_range_t value
+ * @return mouse_xy_report_t clamped value
+ */
+static inline mouse_xy_report_t pointing_device_xy_clamp(clamp_range_t value) {
+ if (value < XY_REPORT_MIN) {
+ return XY_REPORT_MIN;
+ } else if (value > XY_REPORT_MAX) {
+ return XY_REPORT_MAX;
+ } else {
+ return value;
+ }
+}
+/**
* @brief combines 2 mouse reports and returns 2
*
* Combines 2 report_mouse_t structs, clamping movement values to int8_t and ignores report_id then returns the resulting report_mouse_t struct.
@@ -369,10 +392,10 @@ static inline int8_t pointing_device_movement_clamp(int16_t value) {
* @return combined report_mouse_t of left_report and right_report
*/
report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report) {
- left_report.x = pointing_device_movement_clamp((int16_t)left_report.x + right_report.x);
- left_report.y = pointing_device_movement_clamp((int16_t)left_report.y + right_report.y);
- left_report.h = pointing_device_movement_clamp((int16_t)left_report.h + right_report.h);
- left_report.v = pointing_device_movement_clamp((int16_t)left_report.v + right_report.v);
+ left_report.x = pointing_device_xy_clamp((clamp_range_t)left_report.x + right_report.x);
+ left_report.y = pointing_device_xy_clamp((clamp_range_t)left_report.y + right_report.y);
+ left_report.h = pointing_device_hv_clamp((int16_t)left_report.h + right_report.h);
+ left_report.v = pointing_device_hv_clamp((int16_t)left_report.v + right_report.v);
left_report.buttons |= right_report.buttons;
return left_report;
}
@@ -390,7 +413,8 @@ report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, repor
report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report) {
// Support rotation of the sensor data
# if defined(POINTING_DEVICE_ROTATION_90_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT)
- int8_t x = mouse_report.x, y = mouse_report.y;
+ mouse_xy_report_t x = mouse_report.x;
+ mouse_xy_report_t y = mouse_report.y;
# if defined(POINTING_DEVICE_ROTATION_90_RIGHT)
mouse_report.x = y;
mouse_report.y = -x;
diff --git a/quantum/pointing_device.h b/quantum/pointing_device.h
index 5c0eaeaf34..1e5ef9590c 100644
--- a/quantum/pointing_device.h
+++ b/quantum/pointing_device.h
@@ -75,6 +75,16 @@ typedef enum {
POINTING_DEVICE_BUTTON8,
} pointing_device_buttons_t;
+#ifdef MOUSE_EXTENDED_REPORT
+# define XY_REPORT_MIN INT16_MIN
+# define XY_REPORT_MAX INT16_MAX
+typedef int32_t clamp_range_t;
+#else
+# define XY_REPORT_MIN INT8_MIN
+# define XY_REPORT_MAX INT8_MAX
+typedef int16_t clamp_range_t;
+#endif
+
void pointing_device_init(void);
void pointing_device_task(void);
void pointing_device_send(void);
diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c
index 56363c7ac6..435fcabf7c 100644
--- a/quantum/pointing_device_drivers.c
+++ b/quantum/pointing_device_drivers.c
@@ -22,8 +22,8 @@
#include "timer.h"
#include <stddef.h>
-// hid mouse reports cannot exceed -127 to 127, so constrain to that value
-#define constrain_hid(amt) ((amt) < -127 ? -127 : ((amt) > 127 ? 127 : (amt)))
+#define CONSTRAIN_HID(amt) ((amt) < INT8_MIN ? INT8_MIN : ((amt) > INT8_MAX ? INT8_MAX : (amt)))
+#define CONSTRAIN_HID_XY(amt) ((amt) < XY_REPORT_MIN ? XY_REPORT_MIN : ((amt) > XY_REPORT_MAX ? XY_REPORT_MAX : (amt)))
// get_report functions should probably be moved to their respective drivers.
#if defined(POINTING_DEVICE_DRIVER_adns5050)
@@ -35,8 +35,8 @@ report_mouse_t adns5050_get_report(report_mouse_t mouse_report) {
if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy);
# endif
- mouse_report.x = data.dx;
- mouse_report.y = data.dy;
+ mouse_report.x = (mouse_xy_report_t)data.dx;
+ mouse_report.y = (mouse_xy_report_t)data.dy;
}
return mouse_report;
@@ -50,16 +50,14 @@ const pointing_device_driver_t pointing_device_driver = {
.get_cpi = adns5050_get_cpi,
};
// clang-format on
+
#elif defined(POINTING_DEVICE_DRIVER_adns9800)
report_mouse_t adns9800_get_report_driver(report_mouse_t mouse_report) {
report_adns9800_t sensor_report = adns9800_get_report();
- int8_t clamped_x = constrain_hid(sensor_report.x);
- int8_t clamped_y = constrain_hid(sensor_report.y);
-
- mouse_report.x = clamped_x;
- mouse_report.y = clamped_y;
+ mouse_report.x = CONSTRAIN_HID_XY(sensor_report.x);
+ mouse_report.y = CONSTRAIN_HID_XY(sensor_report.y);
return mouse_report;
}
@@ -72,6 +70,7 @@ const pointing_device_driver_t pointing_device_driver = {
.get_cpi = adns9800_get_cpi
};
// clang-format on
+
#elif defined(POINTING_DEVICE_DRIVER_analog_joystick)
report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) {
report_analog_joystick_t data = analog_joystick_read();
@@ -96,6 +95,7 @@ const pointing_device_driver_t pointing_device_driver = {
.get_cpi = NULL
};
// clang-format on
+
#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
# ifndef CIRQUE_PINNACLE_TAPPING_TERM
# include "action.h"
@@ -107,22 +107,40 @@ const pointing_device_driver_t pointing_device_driver = {
# endif
report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
- pinnacle_data_t touchData = cirque_pinnacle_read_data();
- static uint16_t x = 0, y = 0, mouse_timer = 0;
- int8_t report_x = 0, report_y = 0;
- static bool is_z_down = false;
+ pinnacle_data_t touchData = cirque_pinnacle_read_data();
+ mouse_xy_report_t report_x = 0, report_y = 0;
+ static mouse_xy_report_t x = 0, y = 0;
+ static uint16_t mouse_timer = 0;
+ static bool is_z_down = false;
+
+# if !CIRQUE_PINNACLE_POSITION_MODE
+# error Cirque Pinnacle with relative mode not implemented yet.
+# endif
- cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); // Scale coordinates to arbitrary X, Y resolution
+ if (!touchData.valid) {
+ return mouse_report;
+ }
+
+# if CONSOLE_ENABLE
+ if (debug_mouse && touchData.touchDown) {
+ dprintf("cirque_pinnacle touchData x=%4d y=%4d z=%2d\n", touchData.xValue, touchData.yValue, touchData.zValue);
+ }
+# endif
+
+ // Scale coordinates to arbitrary X, Y resolution
+ cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale());
if (x && y && touchData.xValue && touchData.yValue) {
- report_x = (int8_t)(touchData.xValue - x);
- report_y = (int8_t)(touchData.yValue - y);
+ report_x = (mouse_xy_report_t)(touchData.xValue - x);
+ report_y = (mouse_xy_report_t)(touchData.yValue - y);
}
- x = touchData.xValue;
- y = touchData.yValue;
+ x = touchData.xValue;
+ y = touchData.yValue;
+ mouse_report.x = report_x;
+ mouse_report.y = report_y;
- if ((bool)touchData.zValue != is_z_down) {
- is_z_down = (bool)touchData.zValue;
+ if (touchData.touchDown != is_z_down) {
+ is_z_down = touchData.touchDown;
if (!touchData.zValue) {
if (timer_elapsed(mouse_timer) < CIRQUE_PINNACLE_TAPPING_TERM && mouse_timer != 0) {
mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
@@ -141,8 +159,6 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
if (timer_elapsed(mouse_timer) > (CIRQUE_PINNACLE_TOUCH_DEBOUNCE)) {
mouse_timer = 0;
}
- mouse_report.x = report_x;
- mouse_report.y = report_y;
return mouse_report;
}
@@ -157,11 +173,26 @@ const pointing_device_driver_t pointing_device_driver = {
// clang-format on
#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
+
+mouse_xy_report_t pimoroni_trackball_adapt_values(clamp_range_t* offset) {
+ if (*offset > XY_REPORT_MAX) {
+ *offset -= XY_REPORT_MAX;
+ return (mouse_xy_report_t)XY_REPORT_MAX;
+ } else if (*offset < XY_REPORT_MIN) {
+ *offset += XY_REPORT_MAX;
+ return (mouse_xy_report_t)XY_REPORT_MIN;
+ } else {
+ mouse_xy_report_t temp_return = *offset;
+ *offset = 0;
+ return temp_return;
+ }
+}
+
report_mouse_t pimoroni_trackball_get_report(report_mouse_t mouse_report) {
- static uint16_t debounce = 0;
- static uint8_t error_count = 0;
- pimoroni_data_t pimoroni_data = {0};
- static int16_t x_offset = 0, y_offset = 0;
+ static uint16_t debounce = 0;
+ static uint8_t error_count = 0;
+ pimoroni_data_t pimoroni_data = {0};
+ static clamp_range_t x_offset = 0, y_offset = 0;
if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT) {
i2c_status_t status = read_pimoroni_trackball(&pimoroni_data);
@@ -174,8 +205,8 @@ report_mouse_t pimoroni_trackball_get_report(report_mouse_t mouse_report) {
if (!debounce) {
x_offset += pimoroni_trackball_get_offsets(pimoroni_data.right, pimoroni_data.left, PIMORONI_TRACKBALL_SCALE);
y_offset += pimoroni_trackball_get_offsets(pimoroni_data.down, pimoroni_data.up, PIMORONI_TRACKBALL_SCALE);
- pimoroni_trackball_adapt_values(&mouse_report.x, &x_offset);
- pimoroni_trackball_adapt_values(&mouse_report.y, &y_offset);
+ mouse_report.x = pimoroni_trackball_adapt_values(&x_offset);
+ mouse_report.y = pimoroni_trackball_adapt_values(&y_offset);
} else {
debounce--;
}
@@ -198,6 +229,7 @@ const pointing_device_driver_t pointing_device_driver = {
.get_cpi = pimoroni_trackball_get_cpi
};
// clang-format on
+
#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
static void pmw3360_device_init(void) {
pmw3360_init(0);
@@ -221,8 +253,8 @@ report_mouse_t pmw3360_get_report(report_mouse_t mouse_report) {
# endif
MotionStart = timer_read();
}
- mouse_report.x = constrain_hid(data.dx);
- mouse_report.y = constrain_hid(data.dy);
+ mouse_report.x = CONSTRAIN_HID_XY(data.dx);
+ mouse_report.y = CONSTRAIN_HID_XY(data.dy);
}
return mouse_report;
@@ -236,6 +268,7 @@ const pointing_device_driver_t pointing_device_driver = {
.get_cpi = pmw3360_get_cpi
};
// clang-format on
+
#elif defined(POINTING_DEVICE_DRIVER_pmw3389)
static void pmw3389_device_init(void) {
pmw3389_init();
@@ -259,8 +292,8 @@ report_mouse_t pmw3389_get_report(report_mouse_t mouse_report) {
# endif
MotionStart = timer_read();
}
- mouse_report.x = constrain_hid(data.dx);
- mouse_report.y = constrain_hid(data.dy);
+ mouse_report.x = CONSTRAIN_HID_XY(data.dx);
+ mouse_report.y = CONSTRAIN_HID_XY(data.dy);
}
return mouse_report;
@@ -274,6 +307,7 @@ const pointing_device_driver_t pointing_device_driver = {
.get_cpi = pmw3389_get_cpi
};
// clang-format on
+
#else
__attribute__((weak)) void pointing_device_driver_init(void) {}
__attribute__((weak)) report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) {
@@ -292,4 +326,5 @@ const pointing_device_driver_t pointing_device_driver = {
.set_cpi = pointing_device_driver_set_cpi
};
// clang-format on
+
#endif
diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c
index 12ee898212..20b8b9db4b 100644
--- a/quantum/process_keycode/process_steno.c
+++ b/quantum/process_keycode/process_steno.c
@@ -1,4 +1,4 @@
-/* Copyright 2017 Joseph Wasson
+/* Copyright 2017, 2022 Joseph Wasson, Vladislav Kucheriavykh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,77 +15,118 @@
*/
#include "process_steno.h"
#include "quantum_keycodes.h"
-#include "eeprom.h"
#include "keymap_steno.h"
-#include "virtser.h"
#include <string.h>
+#ifdef VIRTSER_ENABLE
+# include "virtser.h"
+#endif
+#ifdef STENO_ENABLE_ALL
+# include "eeprom.h"
+#endif
-// TxBolt Codes
-#define TXB_NUL 0
-#define TXB_S_L 0b00000001
-#define TXB_T_L 0b00000010
-#define TXB_K_L 0b00000100
-#define TXB_P_L 0b00001000
-#define TXB_W_L 0b00010000
-#define TXB_H_L 0b00100000
-#define TXB_R_L 0b01000001
-#define TXB_A_L 0b01000010
-#define TXB_O_L 0b01000100
-#define TXB_STR 0b01001000
-#define TXB_E_R 0b01010000
-#define TXB_U_R 0b01100000
-#define TXB_F_R 0b10000001
-#define TXB_R_R 0b10000010
-#define TXB_P_R 0b10000100
-#define TXB_B_R 0b10001000
-#define TXB_L_R 0b10010000
-#define TXB_G_R 0b10100000
-#define TXB_T_R 0b11000001
-#define TXB_S_R 0b11000010
-#define TXB_D_R 0b11000100
-#define TXB_Z_R 0b11001000
-#define TXB_NUM 0b11010000
-
-#define TXB_GRP0 0b00000000
-#define TXB_GRP1 0b01000000
-#define TXB_GRP2 0b10000000
-#define TXB_GRP3 0b11000000
-#define TXB_GRPMASK 0b11000000
-
-#define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6)
-
-#define BOLT_STATE_SIZE 4
-#define GEMINI_STATE_SIZE 6
-#define MAX_STATE_SIZE GEMINI_STATE_SIZE
-
-static uint8_t state[MAX_STATE_SIZE] = {0};
-static uint8_t chord[MAX_STATE_SIZE] = {0};
-static int8_t pressed = 0;
+// All steno keys that have been pressed to form this chord,
+// stored in MAX_STROKE_SIZE groups of 8-bit arrays.
+static uint8_t chord[MAX_STROKE_SIZE] = {0};
+// The number of physical keys actually being held down.
+// This is not always equal to the number of 1 bits in `chord` because it is possible to
+// simultaneously press down four keys, then release three of those four keys and then press yet
+// another key while the fourth finger is still holding down its key.
+// At the end of this scenario given as an example, `chord` would have five bits set to 1 but
+// `n_pressed_keys` would be set to 2 because there are only two keys currently being pressed down.
+static int8_t n_pressed_keys = 0;
+
+#ifdef STENO_ENABLE_ALL
static steno_mode_t mode;
-
-static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L, TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL, TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R, TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R};
-
-#ifdef STENO_COMBINEDMAP
-/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */
-static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
-static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U};
+#elif defined(STENO_ENABLE_GEMINI)
+static const steno_mode_t mode = STENO_MODE_GEMINI;
+#elif defined(STENO_ENABLE_BOLT)
+static const steno_mode_t mode = STENO_MODE_BOLT;
#endif
-static void steno_clear_state(void) {
- memset(state, 0, sizeof(state));
+static inline void steno_clear_chord(void) {
memset(chord, 0, sizeof(chord));
}
-static void send_steno_state(uint8_t size, bool send_empty) {
- for (uint8_t i = 0; i < size; ++i) {
- if (chord[i] || send_empty) {
-#ifdef VIRTSER_ENABLE
+#ifdef STENO_ENABLE_GEMINI
+
+# ifdef VIRTSER_ENABLE
+void send_steno_chord_gemini(void) {
+ // Set MSB to 1 to indicate the start of packet
+ chord[0] |= 0x80;
+ for (uint8_t i = 0; i < GEMINI_STROKE_SIZE; ++i) {
+ virtser_send(chord[i]);
+ }
+}
+# else
+# pragma message "VIRTSER_ENABLE = yes is required for Gemini PR to work properly out of the box!"
+# endif // VIRTSER_ENABLE
+
+/**
+ * @precondition: `key` is pressed
+ */
+bool add_gemini_key_to_chord(uint8_t key) {
+ // Although each group of the packet is 8 bits long, the MSB is reserved
+ // to indicate whether that byte is the first byte of the packet (MSB=1)
+ // or one of the remaining five bytes of the packet (MSB=0).
+ // As a consequence, only 7 out of the 8 bits are left to be used as a bit array
+ // for the steno keys of that group.
+ const int group_idx = key / 7;
+ const int intra_group_idx = key - group_idx * 7;
+ // The 0th steno key of the group has bit=0b01000000, the 1st has bit=0b00100000, etc.
+ const uint8_t bit = 1 << (6 - intra_group_idx);
+ chord[group_idx] |= bit;
+ return false;
+}
+#endif // STENO_ENABLE_GEMINI
+
+#ifdef STENO_ENABLE_BOLT
+
+# define TXB_GRP0 0b00000000
+# define TXB_GRP1 0b01000000
+# define TXB_GRP2 0b10000000
+# define TXB_GRP3 0b11000000
+# define TXB_GRPMASK 0b11000000
+
+# define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6)
+
+static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L, TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL, TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R, TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R};
+
+# ifdef VIRTSER_ENABLE
+static void send_steno_chord_bolt(void) {
+ for (uint8_t i = 0; i < BOLT_STROKE_SIZE; ++i) {
+ // TX Bolt uses variable length packets where each byte corresponds to a bit array of certain keys.
+ // If a user chorded the keys of the first group with keys of the last group, for example, there
+ // would be bytes of 0x00 in `chord` for the middle groups which we mustn't send.
+ if (chord[i]) {
virtser_send(chord[i]);
-#endif
}
}
+ // Sending a null packet is not always necessary, but it is simpler and more reliable
+ // to unconditionally send it every time instead of keeping track of more states and
+ // creating more branches in the execution of the program.
+ virtser_send(0);
}
+# else
+# pragma message "VIRTSER_ENABLE = yes is required for TX Bolt to work properly out of the box!"
+# endif // VIRTSER_ENABLE
+
+/**
+ * @precondition: `key` is pressed
+ */
+static bool add_bolt_key_to_chord(uint8_t key) {
+ uint8_t boltcode = pgm_read_byte(boltmap + key);
+ chord[TXB_GET_GROUP(boltcode)] |= boltcode;
+ return false;
+}
+#endif // STENO_ENABLE_BOLT
+
+#ifdef STENO_COMBINEDMAP
+/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */
+static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
+static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U};
+#endif
+#ifdef STENO_ENABLE_ALL
void steno_init() {
if (!eeconfig_is_enabled()) {
eeconfig_init();
@@ -94,19 +135,20 @@ void steno_init() {
}
void steno_set_mode(steno_mode_t new_mode) {
- steno_clear_state();
+ steno_clear_chord();
mode = new_mode;
eeprom_update_byte(EECONFIG_STENOMODE, mode);
}
+#endif // STENO_ENABLE_ALL
/* override to intercept chords right before they get sent.
* return zero to suppress normal sending behavior.
*/
-__attribute__((weak)) bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]) {
+__attribute__((weak)) bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE]) {
return true;
}
-__attribute__((weak)) bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[6], int8_t pressed) {
+__attribute__((weak)) bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE], int8_t n_pressed_keys) {
return true;
}
@@ -114,108 +156,94 @@ __attribute__((weak)) bool process_steno_user(uint16_t keycode, keyrecord_t *rec
return true;
}
-static void send_steno_chord(void) {
- if (send_steno_chord_user(mode, chord)) {
- switch (mode) {
- case STENO_MODE_BOLT:
- send_steno_state(BOLT_STATE_SIZE, false);
-#ifdef VIRTSER_ENABLE
- virtser_send(0); // terminating byte
-#endif
- break;
- case STENO_MODE_GEMINI:
- chord[0] |= 0x80; // Indicate start of packet
- send_steno_state(GEMINI_STATE_SIZE, true);
- break;
- }
+bool process_steno(uint16_t keycode, keyrecord_t *record) {
+ if (keycode < QK_STENO || keycode > QK_STENO_MAX) {
+ return true; // Not a steno key, pass it further along the chain
+ /*
+ * Clearing or sending the chord state is not necessary as we intentionally ignore whatever
+ * normal keyboard keys the user may have tapped while chording steno keys.
+ */
}
- steno_clear_state();
-}
-
-uint8_t *steno_get_state(void) {
- return &state[0];
-}
-
-uint8_t *steno_get_chord(void) {
- return &chord[0];
-}
-
-static bool update_state_bolt(uint8_t key, bool press) {
- uint8_t boltcode = pgm_read_byte(boltmap + key);
- if (press) {
- state[TXB_GET_GROUP(boltcode)] |= boltcode;
- chord[TXB_GET_GROUP(boltcode)] |= boltcode;
- } else {
- state[TXB_GET_GROUP(boltcode)] &= ~boltcode;
+ if (IS_NOEVENT(record->event)) {
+ return true;
}
- return false;
-}
-
-static bool update_state_gemini(uint8_t key, bool press) {
- int idx = key / 7;
- uint8_t bit = 1 << (6 - (key % 7));
- if (press) {
- state[idx] |= bit;
- chord[idx] |= bit;
- } else {
- state[idx] &= ~bit;
+ if (!process_steno_user(keycode, record)) {
+ return false; // User fully processed the steno key themselves
}
- return false;
-}
-
-bool process_steno(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
+#ifdef STENO_ENABLE_ALL
case QK_STENO_BOLT:
- if (!process_steno_user(keycode, record)) {
- return false;
- }
if (IS_PRESSED(record->event)) {
steno_set_mode(STENO_MODE_BOLT);
}
return false;
case QK_STENO_GEMINI:
- if (!process_steno_user(keycode, record)) {
- return false;
- }
if (IS_PRESSED(record->event)) {
steno_set_mode(STENO_MODE_GEMINI);
}
return false;
+#endif // STENO_ENABLE_ALL
#ifdef STENO_COMBINEDMAP
case QK_STENO_COMB ... QK_STENO_COMB_MAX: {
- uint8_t result;
- result = process_steno(combinedmap_first[keycode - QK_STENO_COMB], record);
- result &= process_steno(combinedmap_second[keycode - QK_STENO_COMB], record);
- return result;
+ bool first_result = process_steno(combinedmap_first[keycode - QK_STENO_COMB], record);
+ bool second_result = process_steno(combinedmap_second[keycode - QK_STENO_COMB], record);
+ return first_result && second_result;
}
-#endif
+#endif // STENO_COMBINEDMAP
case STN__MIN ... STN__MAX:
- if (!process_steno_user(keycode, record)) {
- return false;
- }
- switch (mode) {
- case STENO_MODE_BOLT:
- update_state_bolt(keycode - QK_STENO, IS_PRESSED(record->event));
- break;
- case STENO_MODE_GEMINI:
- update_state_gemini(keycode - QK_STENO, IS_PRESSED(record->event));
- break;
- }
- // allow postprocessing hooks
- if (postprocess_steno_user(keycode, record, mode, chord, pressed)) {
- if (IS_PRESSED(record->event)) {
- ++pressed;
- } else {
- --pressed;
- if (pressed <= 0) {
- pressed = 0;
- send_steno_chord();
- }
+ if (IS_PRESSED(record->event)) {
+ n_pressed_keys++;
+ switch (mode) {
+#ifdef STENO_ENABLE_BOLT
+ case STENO_MODE_BOLT:
+ add_bolt_key_to_chord(keycode - QK_STENO);
+ break;
+#endif // STENO_ENABLE_BOLT
+#ifdef STENO_ENABLE_GEMINI
+ case STENO_MODE_GEMINI:
+ add_gemini_key_to_chord(keycode - QK_STENO);
+ break;
+#endif // STENO_ENABLE_GEMINI
+ default:
+ return false;
}
+ if (!postprocess_steno_user(keycode, record, mode, chord, n_pressed_keys)) {
+ return false;
+ }
+ } else { // is released
+ n_pressed_keys--;
+ if (!postprocess_steno_user(keycode, record, mode, chord, n_pressed_keys)) {
+ return false;
+ }
+ if (n_pressed_keys > 0) {
+ // User hasn't released all keys yet,
+ // so the chord cannot be sent
+ return false;
+ }
+ n_pressed_keys = 0;
+ if (!send_steno_chord_user(mode, chord)) {
+ steno_clear_chord();
+ return false;
+ }
+ switch (mode) {
+#if defined(STENO_ENABLE_BOLT) && defined(VIRTSER_ENABLE)
+ case STENO_MODE_BOLT:
+ send_steno_chord_bolt();
+ break;
+#endif // STENO_ENABLE_BOLT && VIRTSER_ENABLE
+#if defined(STENO_ENABLE_GEMINI) && defined(VIRTSER_ENABLE)
+ case STENO_MODE_GEMINI:
+ send_steno_chord_gemini();
+ break;
+#endif // STENO_ENABLE_GEMINI && VIRTSER_ENABLE
+ default:
+ break;
+ }
+ steno_clear_chord();
}
- return false;
+ break;
}
- return true;
+ return false;
}
diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h
index d11fd40af0..68d6097b9b 100644
--- a/quantum/process_keycode/process_steno.h
+++ b/quantum/process_keycode/process_steno.h
@@ -18,10 +18,22 @@
#include "quantum.h"
-typedef enum { STENO_MODE_BOLT, STENO_MODE_GEMINI } steno_mode_t;
+#define BOLT_STROKE_SIZE 4
+#define GEMINI_STROKE_SIZE 6
-bool process_steno(uint16_t keycode, keyrecord_t *record);
-void steno_init(void);
-void steno_set_mode(steno_mode_t mode);
-uint8_t *steno_get_state(void);
-uint8_t *steno_get_chord(void);
+#ifdef STENO_ENABLE_GEMINI
+# define MAX_STROKE_SIZE GEMINI_STROKE_SIZE
+#else
+# define MAX_STROKE_SIZE BOLT_STROKE_SIZE
+#endif
+
+typedef enum {
+ STENO_MODE_GEMINI,
+ STENO_MODE_BOLT,
+} steno_mode_t;
+
+bool process_steno(uint16_t keycode, keyrecord_t *record);
+#ifdef STENO_ENABLE_ALL
+void steno_init(void);
+void steno_set_mode(steno_mode_t mode);
+#endif // STENO_ENABLE_ALL
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index db8df5f870..3270a1b000 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -15,12 +15,8 @@
*/
#include "quantum.h"
-#ifndef NO_ACTION_ONESHOT
-uint8_t get_oneshot_mods(void);
-#endif
-
-static uint16_t last_td;
-static int16_t highest_td = -1;
+static uint16_t active_td;
+static uint16_t last_tap_time;
void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data) {
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
@@ -34,18 +30,14 @@ void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data)
void qk_tap_dance_pair_finished(qk_tap_dance_state_t *state, void *user_data) {
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
- if (state->count == 1) {
- register_code16(pair->kc1);
- } else if (state->count == 2) {
- register_code16(pair->kc2);
- }
+ register_code16(pair->kc1);
}
void qk_tap_dance_pair_reset(qk_tap_dance_state_t *state, void *user_data) {
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
- wait_ms(TAP_CODE_DELAY);
if (state->count == 1) {
+ wait_ms(TAP_CODE_DELAY);
unregister_code16(pair->kc1);
} else if (state->count == 2) {
unregister_code16(pair->kc2);
@@ -87,23 +79,40 @@ static inline void _process_tap_dance_action_fn(qk_tap_dance_state_t *state, voi
}
static inline void process_tap_dance_action_on_each_tap(qk_tap_dance_action_t *action) {
+ action->state.count++;
+ action->state.weak_mods = get_mods();
+ action->state.weak_mods |= get_weak_mods();
+#ifndef NO_ACTION_ONESHOT
+ action->state.oneshot_mods = get_oneshot_mods();
+#endif
_process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_tap);
}
-static inline void process_tap_dance_action_on_dance_finished(qk_tap_dance_action_t *action) {
- if (action->state.finished) return;
- action->state.finished = true;
- add_mods(action->state.oneshot_mods);
- add_weak_mods(action->state.weak_mods);
- send_keyboard_report();
- _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_dance_finished);
-}
-
static inline void process_tap_dance_action_on_reset(qk_tap_dance_action_t *action) {
_process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_reset);
- del_mods(action->state.oneshot_mods);
del_weak_mods(action->state.weak_mods);
+#ifndef NO_ACTION_ONESHOT
+ del_mods(action->state.oneshot_mods);
+#endif
send_keyboard_report();
+ action->state = (const qk_tap_dance_state_t){0};
+}
+
+static inline void process_tap_dance_action_on_dance_finished(qk_tap_dance_action_t *action) {
+ if (!action->state.finished) {
+ action->state.finished = true;
+ add_weak_mods(action->state.weak_mods);
+#ifndef NO_ACTION_ONESHOT
+ add_mods(action->state.oneshot_mods);
+#endif
+ send_keyboard_report();
+ _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_dance_finished);
+ }
+ active_td = 0;
+ if (!action->state.pressed) {
+ // There will not be a key release event, so reset now.
+ process_tap_dance_action_on_reset(action);
+ }
}
void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
@@ -111,51 +120,33 @@ void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
if (!record->event.pressed) return;
- if (highest_td == -1) return;
-
- for (int i = 0; i <= highest_td; i++) {
- action = &tap_dance_actions[i];
- if (action->state.count) {
- if (keycode == action->state.keycode && keycode == last_td) continue;
- action->state.interrupted = true;
- action->state.interrupting_keycode = keycode;
- process_tap_dance_action_on_dance_finished(action);
- reset_tap_dance(&action->state);
-
- // Tap dance actions can leave some weak mods active (e.g., if the tap dance is mapped to a keycode with
- // modifiers), but these weak mods should not affect the keypress which interrupted the tap dance.
- clear_weak_mods();
- }
- }
+ if (!active_td || keycode == active_td) return;
+
+ action = &tap_dance_actions[TD_INDEX(active_td)];
+ action->state.interrupted = true;
+ action->state.interrupting_keycode = keycode;
+ process_tap_dance_action_on_dance_finished(action);
+
+ // Tap dance actions can leave some weak mods active (e.g., if the tap dance is mapped to a keycode with
+ // modifiers), but these weak mods should not affect the keypress which interrupted the tap dance.
+ clear_weak_mods();
}
bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
- uint16_t idx = keycode - QK_TAP_DANCE;
qk_tap_dance_action_t *action;
switch (keycode) {
case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
- if ((int16_t)idx > highest_td) highest_td = idx;
- action = &tap_dance_actions[idx];
+ action = &tap_dance_actions[TD_INDEX(keycode)];
action->state.pressed = record->event.pressed;
if (record->event.pressed) {
- action->state.keycode = keycode;
- action->state.count++;
- action->state.timer = timer_read();
-#ifndef NO_ACTION_ONESHOT
- action->state.oneshot_mods = get_oneshot_mods();
-#else
- action->state.oneshot_mods = 0;
-#endif
- action->state.weak_mods = get_mods();
- action->state.weak_mods |= get_weak_mods();
+ last_tap_time = timer_read();
process_tap_dance_action_on_each_tap(action);
-
- last_td = keycode;
+ active_td = action->state.finished ? 0 : keycode;
} else {
- if (action->state.count && action->state.finished) {
- reset_tap_dance(&action->state);
+ if (action->state.finished) {
+ process_tap_dance_action_on_reset(action);
}
}
@@ -166,35 +157,17 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
}
void tap_dance_task() {
- if (highest_td == -1) return;
- uint16_t tap_user_defined;
-
- for (uint8_t i = 0; i <= highest_td; i++) {
- qk_tap_dance_action_t *action = &tap_dance_actions[i];
- if (action->custom_tapping_term > 0) {
- tap_user_defined = action->custom_tapping_term;
- } else {
- tap_user_defined = GET_TAPPING_TERM(action->state.keycode, &(keyrecord_t){});
- }
- if (action->state.count && timer_elapsed(action->state.timer) > tap_user_defined) {
- process_tap_dance_action_on_dance_finished(action);
- reset_tap_dance(&action->state);
- }
- }
-}
-
-void reset_tap_dance(qk_tap_dance_state_t *state) {
qk_tap_dance_action_t *action;
- if (state->pressed) return;
+ if (!active_td || timer_elapsed(last_tap_time) <= GET_TAPPING_TERM(active_td, &(keyrecord_t){})) return;
- action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
-
- process_tap_dance_action_on_reset(action);
+ action = &tap_dance_actions[TD_INDEX(active_td)];
+ if (!action->state.interrupted) {
+ process_tap_dance_action_on_dance_finished(action);
+ }
+}
- state->count = 0;
- state->interrupted = false;
- state->finished = false;
- state->interrupting_keycode = 0;
- last_td = 0;
+void reset_tap_dance(qk_tap_dance_state_t *state) {
+ active_td = 0;
+ process_tap_dance_action_on_reset((qk_tap_dance_action_t *)state);
}
diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h
index d9ffb1e73d..d97900d96b 100644
--- a/quantum/process_keycode/process_tap_dance.h
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -22,30 +22,27 @@
# include <inttypes.h>
typedef struct {
+ uint16_t interrupting_keycode;
uint8_t count;
- uint8_t oneshot_mods;
uint8_t weak_mods;
- uint16_t keycode;
- uint16_t interrupting_keycode;
- uint16_t timer;
- bool interrupted;
- bool pressed;
- bool finished;
+# ifndef NO_ACTION_ONESHOT
+ uint8_t oneshot_mods;
+# endif
+ bool pressed : 1;
+ bool finished : 1;
+ bool interrupted : 1;
} qk_tap_dance_state_t;
-# define TD(n) (QK_TAP_DANCE | ((n)&0xFF))
-
typedef void (*qk_tap_dance_user_fn_t)(qk_tap_dance_state_t *state, void *user_data);
typedef struct {
+ qk_tap_dance_state_t state;
struct {
qk_tap_dance_user_fn_t on_each_tap;
qk_tap_dance_user_fn_t on_dance_finished;
qk_tap_dance_user_fn_t on_reset;
} fn;
- qk_tap_dance_state_t state;
- uint16_t custom_tapping_term;
- void * user_data;
+ void *user_data;
} qk_tap_dance_action_t;
typedef struct {
@@ -62,31 +59,31 @@ typedef struct {
# define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \
{ .fn = {qk_tap_dance_pair_on_each_tap, qk_tap_dance_pair_finished, qk_tap_dance_pair_reset}, .user_data = (void *)&((qk_tap_dance_pair_t){kc1, kc2}), }
-# define ACTION_TAP_DANCE_DUAL_ROLE(kc, layer) \
+# define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) \
{ .fn = {qk_tap_dance_dual_role_on_each_tap, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset}, .user_data = (void *)&((qk_tap_dance_dual_role_t){kc, layer, layer_move}), }
# define ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer) \
{ .fn = {NULL, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset}, .user_data = (void *)&((qk_tap_dance_dual_role_t){kc, layer, layer_invert}), }
-# define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) ACTION_TAP_DANCE_DUAL_ROLE(kc, layer)
-
# define ACTION_TAP_DANCE_FN(user_fn) \
{ .fn = {NULL, user_fn, NULL}, .user_data = NULL, }
# define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset) \
{ .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, }
-# define ACTION_TAP_DANCE_FN_ADVANCED_TIME(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, tap_specific_tapping_term) \
- { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, .custom_tapping_term = tap_specific_tapping_term, }
+# define TD(n) (QK_TAP_DANCE | TD_INDEX(n))
+# define TD_INDEX(code) ((code)&0xFF)
+# define TAP_DANCE_KEYCODE(state) TD(((qk_tap_dance_action_t *)state) - tap_dance_actions)
extern qk_tap_dance_action_t tap_dance_actions[];
+void reset_tap_dance(qk_tap_dance_state_t *state);
+
/* To be used internally */
void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record);
bool process_tap_dance(uint16_t keycode, keyrecord_t *record);
void tap_dance_task(void);
-void reset_tap_dance(qk_tap_dance_state_t *state);
void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data);
void qk_tap_dance_pair_finished(qk_tap_dance_state_t *state, void *user_data);
diff --git a/quantum/process_keycode/process_terminal.c b/quantum/process_keycode/process_terminal.c
deleted file mode 100644
index da1c4d506f..0000000000
--- a/quantum/process_keycode/process_terminal.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/* Copyright 2017 Jack Humbert
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "process_terminal.h"
-#include <string.h>
-#include "version.h"
-#include <stdio.h>
-#include <math.h>
-
-#ifndef CMD_BUFF_SIZE
-# define CMD_BUFF_SIZE 5
-#endif
-
-bool terminal_enabled = false;
-char buffer[80] = "";
-char cmd_buffer[CMD_BUFF_SIZE][80];
-bool cmd_buffer_enabled = true; // replace with ifdef?
-char newline[2] = "\n";
-char arguments[6][20];
-bool firstTime = true;
-
-short int current_cmd_buffer_pos = 0; // used for up/down arrows - keeps track of where you are in the command buffer
-
-__attribute__((weak)) const char terminal_prompt[8] = "> ";
-
-#ifdef AUDIO_ENABLE
-# ifndef TERMINAL_SONG
-# define TERMINAL_SONG SONG(TERMINAL_SOUND)
-# endif
-float terminal_song[][2] = TERMINAL_SONG;
-# define TERMINAL_BELL() PLAY_SONG(terminal_song)
-#else
-# define TERMINAL_BELL()
-#endif
-
-__attribute__((weak)) const char keycode_to_ascii_lut[58] = {0, 0, 0, 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0, 0, 0, '\t', ' ', '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',', '.', '/'};
-
-__attribute__((weak)) const char shifted_keycode_to_ascii_lut[58] = {0, 0, 0, 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', 0, 0, 0, '\t', ' ', '_', '+', '{', '}', '|', 0, ':', '\'', '~', '<', '>', '?'};
-
-struct stringcase {
- char *string;
- void (*func)(void);
-} typedef stringcase;
-
-void enable_terminal(void) {
- terminal_enabled = true;
- strcpy(buffer, "");
- memset(cmd_buffer, 0, CMD_BUFF_SIZE * 80);
- for (int i = 0; i < 6; i++)
- strcpy(arguments[i], "");
- // select all text to start over
- // SEND_STRING(SS_LCTL("a"));
- send_string(terminal_prompt);
-}
-
-void disable_terminal(void) {
- terminal_enabled = false;
- SEND_STRING("\n");
-}
-
-void push_to_cmd_buffer(void) {
- if (cmd_buffer_enabled) {
- if (cmd_buffer == NULL) {
- return;
- } else {
- if (firstTime) {
- firstTime = false;
- strcpy(cmd_buffer[0], buffer);
- return;
- }
-
- for (int i = CMD_BUFF_SIZE - 1; i > 0; --i) {
- strncpy(cmd_buffer[i], cmd_buffer[i - 1], 80);
- }
-
- strcpy(cmd_buffer[0], buffer);
-
- return;
- }
- }
-}
-
-void terminal_about(void) {
- SEND_STRING("QMK Firmware\n");
- SEND_STRING(" v");
- SEND_STRING(QMK_VERSION);
- SEND_STRING("\n" SS_TAP(X_HOME) " Built: ");
- SEND_STRING(QMK_BUILDDATE);
- send_string(newline);
-#ifdef TERMINAL_HELP
- if (strlen(arguments[1]) != 0) {
- SEND_STRING("You entered: ");
- send_string(arguments[1]);
- send_string(newline);
- }
-#endif
-}
-
-void terminal_help(void);
-
-extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
-
-void terminal_keycode(void) {
- if (strlen(arguments[1]) != 0 && strlen(arguments[2]) != 0 && strlen(arguments[3]) != 0) {
- char keycode_dec[5];
- char keycode_hex[5];
- uint16_t layer = strtol(arguments[1], (char **)NULL, 10);
- uint16_t row = strtol(arguments[2], (char **)NULL, 10);
- uint16_t col = strtol(arguments[3], (char **)NULL, 10);
- uint16_t keycode = pgm_read_word(&keymaps[layer][row][col]);
- itoa(keycode, keycode_dec, 10);
- itoa(keycode, keycode_hex, 16);
- SEND_STRING("0x");
- send_string(keycode_hex);
- SEND_STRING(" (");
- send_string(keycode_dec);
- SEND_STRING(")\n");
- } else {
-#ifdef TERMINAL_HELP
- SEND_STRING("usage: keycode <layer> <row> <col>\n");
-#endif
- }
-}
-
-void terminal_keymap(void) {
- if (strlen(arguments[1]) != 0) {
- uint16_t layer = strtol(arguments[1], (char **)NULL, 10);
- for (int r = 0; r < MATRIX_ROWS; r++) {
- for (int c = 0; c < MATRIX_COLS; c++) {
- uint16_t keycode = pgm_read_word(&keymaps[layer][r][c]);
- char keycode_s[8];
- sprintf(keycode_s, "0x%04x,", keycode);
- send_string(keycode_s);
- }
- send_string(newline);
- }
- } else {
-#ifdef TERMINAL_HELP
- SEND_STRING("usage: keymap <layer>\n");
-#endif
- }
-}
-
-void print_cmd_buff(void) {
- /* without the below wait, a race condition can occur wherein the
- buffer can be printed before it has been fully moved */
- wait_ms(250);
- for (int i = 0; i < CMD_BUFF_SIZE; i++) {
- char tmpChar = ' ';
- itoa(i, &tmpChar, 10);
- const char *tmpCnstCharStr = &tmpChar; // because sned_string wont take a normal char *
- send_string(tmpCnstCharStr);
- SEND_STRING(". ");
- send_string(cmd_buffer[i]);
- SEND_STRING("\n");
- }
-}
-
-void flush_cmd_buffer(void) {
- memset(cmd_buffer, 0, CMD_BUFF_SIZE * 80);
- SEND_STRING("Buffer Cleared!\n");
-}
-
-stringcase terminal_cases[] = {{"about", terminal_about}, {"help", terminal_help}, {"keycode", terminal_keycode}, {"keymap", terminal_keymap}, {"flush-buffer", flush_cmd_buffer}, {"print-buffer", print_cmd_buff}, {"exit", disable_terminal}};
-
-void terminal_help(void) {
- SEND_STRING("commands available:\n ");
- for (stringcase *case_p = terminal_cases; case_p != terminal_cases + sizeof(terminal_cases) / sizeof(terminal_cases[0]); case_p++) {
- send_string(case_p->string);
- SEND_STRING(" ");
- }
- send_string(newline);
-}
-
-void command_not_found(void) {
- wait_ms(50); // sometimes buffer isnt grabbed quick enough
- SEND_STRING("command \"");
- send_string(buffer);
- SEND_STRING("\" not found\n");
-}
-
-void process_terminal_command(void) {
- // we capture return bc of the order of events, so we need to manually send a newline
- send_string(newline);
-
- char * pch;
- uint8_t i = 0;
- pch = strtok(buffer, " ");
- while (pch != NULL) {
- strcpy(arguments[i], pch);
- pch = strtok(NULL, " ");
- i++;
- }
-
- bool command_found = false;
- for (stringcase *case_p = terminal_cases; case_p != terminal_cases + sizeof(terminal_cases) / sizeof(terminal_cases[0]); case_p++) {
- if (0 == strcmp(case_p->string, buffer)) {
- command_found = true;
- (*case_p->func)();
- break;
- }
- }
-
- if (!command_found) command_not_found();
-
- if (terminal_enabled) {
- strcpy(buffer, "");
- for (int i = 0; i < 6; i++)
- strcpy(arguments[i], "");
- SEND_STRING(SS_TAP(X_HOME));
- send_string(terminal_prompt);
- }
-}
-void check_pos(void) {
- if (current_cmd_buffer_pos >= CMD_BUFF_SIZE) { // if over the top, move it back down to the top of the buffer so you can climb back down...
- current_cmd_buffer_pos = CMD_BUFF_SIZE - 1;
- } else if (current_cmd_buffer_pos < 0) { //...and if you fall under the bottom of the buffer, reset back to 0 so you can climb back up
- current_cmd_buffer_pos = 0;
- }
-}
-
-bool process_terminal(uint16_t keycode, keyrecord_t *record) {
- if (keycode == TERM_ON && record->event.pressed) {
- enable_terminal();
- return false;
- }
-
- if (terminal_enabled && record->event.pressed) {
- if (keycode == TERM_OFF && record->event.pressed) {
- disable_terminal();
- return false;
- }
-
- if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
- keycode = keycode & 0xFF;
- }
-
- if (keycode < 256) {
- uint8_t str_len;
- char char_to_add;
- switch (keycode) {
- case KC_ENTER:
- case KC_KP_ENTER:
- push_to_cmd_buffer();
- current_cmd_buffer_pos = 0;
- process_terminal_command();
- return false;
- break;
- case KC_ESCAPE:
- SEND_STRING("\n");
- enable_terminal();
- return false;
- break;
- case KC_BACKSPACE:
- str_len = strlen(buffer);
- if (str_len > 0) {
- buffer[str_len - 1] = 0;
- return true;
- } else {
- TERMINAL_BELL();
- return false;
- }
- break;
- case KC_LEFT:
- return false;
- break;
- case KC_RIGHT:
- return false;
- break;
- case KC_UP: // 0 = recent
- check_pos(); // check our current buffer position is valid
- if (current_cmd_buffer_pos <= CMD_BUFF_SIZE - 1) { // once we get to the top, dont do anything
- str_len = strlen(buffer);
- for (int i = 0; i < str_len; ++i) {
- send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
- // process_terminal(KC_BACKSPACE,record);
- }
- strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 80);
-
- send_string(buffer);
- ++current_cmd_buffer_pos; // get ready to access the above cmd if up/down is pressed again
- }
- return false;
- break;
- case KC_DOWN:
- check_pos();
- if (current_cmd_buffer_pos >= 0) { // once we get to the bottom, dont do anything
- str_len = strlen(buffer);
- for (int i = 0; i < str_len; ++i) {
- send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
- // process_terminal(KC_BACKSPACE,record);
- }
- strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 79);
-
- send_string(buffer);
- --current_cmd_buffer_pos; // get ready to access the above cmd if down/up is pressed again
- }
- return false;
- break;
- default:
- if (keycode <= 58) {
- char_to_add = 0;
- if (get_mods() & (MOD_BIT(KC_LEFT_SHIFT) | MOD_BIT(KC_RIGHT_SHIFT))) {
- char_to_add = shifted_keycode_to_ascii_lut[keycode];
- } else if (get_mods() == 0) {
- char_to_add = keycode_to_ascii_lut[keycode];
- }
- if (char_to_add != 0) {
- strncat(buffer, &char_to_add, 1);
- }
- }
- break;
- }
- }
- }
- return true;
-}
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 33121f6b95..d1cfb5fbe0 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -307,9 +307,6 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef DYNAMIC_TAPPING_TERM_ENABLE
process_dynamic_tapping_term(keycode, record) &&
#endif
-#ifdef TERMINAL_ENABLE
- process_terminal(keycode, record) &&
-#endif
#ifdef SPACE_CADET_ENABLE
process_space_cadet(keycode, record) &&
#endif
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 92e1af1c40..8a7a20c706 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -141,12 +141,6 @@ extern layer_state_t layer_state;
# include "process_key_lock.h"
#endif
-#ifdef TERMINAL_ENABLE
-# include "process_terminal.h"
-#else
-# include "process_terminal_nop.h"
-#endif
-
#ifdef SPACE_CADET_ENABLE
# include "process_space_cadet.h"
#endif
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 40355d799a..869826ce19 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -473,9 +473,9 @@ enum quantum_keycodes {
// Lock Key
KC_LOCK, // 5D2B
- // Terminal
- TERM_ON, // 5D2C
- TERM_OFF, // 5D2D
+ // Unused slots
+ UNUSED_000, // 5D2C
+ UNUSED_001, // 5D2D
// Sequencer
SQ_ON, // 5D2E
diff --git a/quantum/quantum_keycodes_legacy.h b/quantum/quantum_keycodes_legacy.h
index ed9455ee74..51380d9c50 100644
--- a/quantum/quantum_keycodes_legacy.h
+++ b/quantum/quantum_keycodes_legacy.h
@@ -11,3 +11,6 @@
#define KC_GESC QK_GRAVE_ESCAPE
#define EEP_RST QK_CLEAR_EEPROM
+
+#define TERM_ON _Static_assert(false, "The Terminal feature has been removed from QMK. Please remove use of TERM_ON/TERM_OFF from your keymap.")
+#define TERM_OFF _Static_assert(false, "The Terminal feature has been removed from QMK.. Please remove use of TERM_ON/TERM_OFF from your keymap.") \ No newline at end of file
diff --git a/quantum/rgb_matrix/animations/typing_heatmap_anim.h b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
index 4b17c4c3ed..a05c07760e 100644
--- a/quantum/rgb_matrix/animations/typing_heatmap_anim.h
+++ b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
@@ -6,30 +6,41 @@ RGB_MATRIX_EFFECT(TYPING_HEATMAP)
# define RGB_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS 25
# endif
+# ifndef RGB_MATRIX_TYPING_HEATMAP_SPREAD
+# define RGB_MATRIX_TYPING_HEATMAP_SPREAD 40
+# endif
+
+# ifndef RGB_MATRIX_TYPING_HEATMAP_AREA_LIMIT
+# define RGB_MATRIX_TYPING_HEATMAP_AREA_LIMIT 16
+# endif
void process_rgb_matrix_typing_heatmap(uint8_t row, uint8_t col) {
# ifdef RGB_MATRIX_TYPING_HEATMAP_SLIM
// Limit effect to pressed keys
g_rgb_frame_buffer[row][col] = qadd8(g_rgb_frame_buffer[row][col], 32);
# else
- uint8_t m_row = row - 1;
- uint8_t p_row = row + 1;
- uint8_t m_col = col - 1;
- uint8_t p_col = col + 1;
-
- if (m_col < col) g_rgb_frame_buffer[row][m_col] = qadd8(g_rgb_frame_buffer[row][m_col], 16);
- g_rgb_frame_buffer[row][col] = qadd8(g_rgb_frame_buffer[row][col], 32);
- if (p_col < MATRIX_COLS) g_rgb_frame_buffer[row][p_col] = qadd8(g_rgb_frame_buffer[row][p_col], 16);
-
- if (p_row < MATRIX_ROWS) {
- if (m_col < col) g_rgb_frame_buffer[p_row][m_col] = qadd8(g_rgb_frame_buffer[p_row][m_col], 13);
- g_rgb_frame_buffer[p_row][col] = qadd8(g_rgb_frame_buffer[p_row][col], 16);
- if (p_col < MATRIX_COLS) g_rgb_frame_buffer[p_row][p_col] = qadd8(g_rgb_frame_buffer[p_row][p_col], 13);
+ if (g_led_config.matrix_co[row][col] == NO_LED) { // skip as pressed key doesn't have an led position
+ return;
}
-
- if (m_row < row) {
- if (m_col < col) g_rgb_frame_buffer[m_row][m_col] = qadd8(g_rgb_frame_buffer[m_row][m_col], 13);
- g_rgb_frame_buffer[m_row][col] = qadd8(g_rgb_frame_buffer[m_row][col], 16);
- if (p_col < MATRIX_COLS) g_rgb_frame_buffer[m_row][p_col] = qadd8(g_rgb_frame_buffer[m_row][p_col], 13);
+ for (uint8_t i_row = 0; i_row < MATRIX_ROWS; i_row++) {
+ for (uint8_t i_col = 0; i_col < MATRIX_COLS; i_col++) {
+ if (g_led_config.matrix_co[i_row][i_col] == NO_LED) { // skip as target key doesn't have an led position
+ continue;
+ }
+ if (i_row == row && i_col == col) {
+ g_rgb_frame_buffer[row][col] = qadd8(g_rgb_frame_buffer[row][col], 32);
+ } else {
+# define LED_DISTANCE(led_a, led_b) sqrt16(((int8_t)(led_a.x - led_b.x) * (int8_t)(led_a.x - led_b.x)) + ((int8_t)(led_a.y - led_b.y) * (int8_t)(led_a.y - led_b.y)))
+ uint8_t distance = LED_DISTANCE(g_led_config.point[g_led_config.matrix_co[row][col]], g_led_config.point[g_led_config.matrix_co[i_row][i_col]]);
+# undef LED_DISTANCE
+ if (distance <= RGB_MATRIX_TYPING_HEATMAP_SPREAD) {
+ uint8_t amount = qsub8(RGB_MATRIX_TYPING_HEATMAP_SPREAD, distance);
+ if (amount > RGB_MATRIX_TYPING_HEATMAP_AREA_LIMIT) {
+ amount = RGB_MATRIX_TYPING_HEATMAP_AREA_LIMIT;
+ }
+ g_rgb_frame_buffer[i_row][i_col] = qadd8(g_rgb_frame_buffer[i_row][i_col], amount);
+ }
+ }
+ }
}
# endif
}
@@ -40,10 +51,7 @@ static uint16_t heatmap_decrease_timer;
static bool decrease_heatmap_values;
bool TYPING_HEATMAP(effect_params_t* params) {
- // Modified version of RGB_MATRIX_USE_LIMITS to work off of matrix row / col size
- uint8_t led_min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter;
- uint8_t led_max = led_min + RGB_MATRIX_LED_PROCESS_LIMIT;
- if (led_max > sizeof(g_rgb_frame_buffer)) led_max = sizeof(g_rgb_frame_buffer);
+ RGB_MATRIX_USE_LIMITS(led_min, led_max);
if (params->init) {
rgb_matrix_set_color_all(0, 0, 0);
@@ -63,28 +71,26 @@ bool TYPING_HEATMAP(effect_params_t* params) {
}
// Render heatmap & decrease
- for (int i = led_min; i < led_max; i++) {
- uint8_t row = i % MATRIX_ROWS;
- uint8_t col = i / MATRIX_ROWS;
- uint8_t val = g_rgb_frame_buffer[row][col];
-
- // set the pixel colour
- uint8_t led[LED_HITS_TO_REMEMBER];
- uint8_t led_count = rgb_matrix_map_row_column_to_led(row, col, led);
- for (uint8_t j = 0; j < led_count; ++j) {
- if (!HAS_ANY_FLAGS(g_led_config.flags[led[j]], params->flags)) continue;
-
- HSV hsv = {170 - qsub8(val, 85), rgb_matrix_config.hsv.s, scale8((qadd8(170, val) - 170) * 3, rgb_matrix_config.hsv.v)};
- RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
- rgb_matrix_set_color(led[j], rgb.r, rgb.g, rgb.b);
- }
-
- if (decrease_heatmap_values) {
- g_rgb_frame_buffer[row][col] = qsub8(val, 1);
+ uint8_t count = 0;
+ for (uint8_t row = 0; row < MATRIX_ROWS && count < RGB_MATRIX_LED_PROCESS_LIMIT; row++) {
+ for (uint8_t col = 0; col < MATRIX_COLS && RGB_MATRIX_LED_PROCESS_LIMIT; col++) {
+ if (g_led_config.matrix_co[row][col] >= led_min && g_led_config.matrix_co[row][col] < led_max) {
+ count++;
+ uint8_t val = g_rgb_frame_buffer[row][col];
+ if (!HAS_ANY_FLAGS(g_led_config.flags[g_led_config.matrix_co[row][col]], params->flags)) continue;
+
+ HSV hsv = {170 - qsub8(val, 85), rgb_matrix_config.hsv.s, scale8((qadd8(170, val) - 170) * 3, rgb_matrix_config.hsv.v)};
+ RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
+ rgb_matrix_set_color(g_led_config.matrix_co[row][col], rgb.r, rgb.g, rgb.b);
+
+ if (decrease_heatmap_values) {
+ g_rgb_frame_buffer[row][col] = qsub8(val, 1);
+ }
+ }
}
}
- return led_max < sizeof(g_rgb_frame_buffer);
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c
index f721dfc7f2..a51e379025 100644
--- a/quantum/rgb_matrix/rgb_matrix.c
+++ b/quantum/rgb_matrix/rgb_matrix.c
@@ -249,8 +249,15 @@ void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed) {
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_TYPING_HEATMAP)
- if (rgb_matrix_config.mode == RGB_MATRIX_TYPING_HEATMAP) {
- process_rgb_matrix_typing_heatmap(row, col);
+# if defined(RGB_MATRIX_KEYRELEASES)
+ if (!pressed)
+# else
+ if (pressed)
+# endif // defined(RGB_MATRIX_KEYRELEASES)
+ {
+ if (rgb_matrix_config.mode == RGB_MATRIX_TYPING_HEATMAP) {
+ process_rgb_matrix_typing_heatmap(row, col);
+ }
}
#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_TYPING_HEATMAP)
}
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index 7d50adf758..4892b7f8d8 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -57,8 +57,9 @@ static uint8_t connection_errors = 0;
volatile bool isLeftHand = true;
#if defined(SPLIT_USB_DETECT)
+_Static_assert((SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL) <= UINT16_MAX, "Please lower SPLIT_USB_TIMEOUT and/or increase SPLIT_USB_TIMEOUT_POLL.");
static bool usbIsActive(void) {
- for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {
+ for (uint16_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {
// This will return true if a USB connection has been established
if (usb_connected_state()) {
return true;
@@ -93,7 +94,6 @@ static uint8_t peek_matrix_intersection(pin_t out_pin, pin_t in_pin) {
__attribute__((weak)) bool is_keyboard_left(void) {
#if defined(SPLIT_HAND_PIN)
// Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
- setPinInput(SPLIT_HAND_PIN);
# ifdef SPLIT_HAND_PIN_LOW_IS_LEFT
return !readPin(SPLIT_HAND_PIN);
# else
@@ -132,6 +132,14 @@ __attribute__((weak)) bool is_keyboard_master(void) {
// this code runs before the keyboard is fully initialized
void split_pre_init(void) {
+#if defined(SPLIT_HAND_PIN)
+ setPinInput(SPLIT_HAND_PIN);
+ wait_us(100);
+#elif defined(EE_HANDS)
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+#endif
isLeftHand = is_keyboard_left();
#if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT)
diff --git a/quantum/via.c b/quantum/via.c
index 320bd5546d..d2ef0862cc 100644
--- a/quantum/via.c
+++ b/quantum/via.c
@@ -64,6 +64,7 @@ void via_qmk_rgblight_get_value(uint8_t *data);
#endif
#if defined(VIA_QMK_RGB_MATRIX_ENABLE)
+# include <lib/lib8tion/lib8tion.h>
void via_qmk_rgb_matrix_set_value(uint8_t *data);
void via_qmk_rgb_matrix_get_value(uint8_t *data);
void eeconfig_update_rgb_matrix(void);
@@ -421,7 +422,7 @@ void via_qmk_backlight_get_value(uint8_t *data) {
switch (*value_id) {
case id_qmk_backlight_brightness: {
// level / BACKLIGHT_LEVELS * 255
- value_data[0] = ((uint16_t)get_backlight_level()) * 255 / BACKLIGHT_LEVELS;
+ value_data[0] = ((uint16_t)get_backlight_level() * UINT8_MAX) / BACKLIGHT_LEVELS;
break;
}
case id_qmk_backlight_effect: {
@@ -441,7 +442,7 @@ void via_qmk_backlight_set_value(uint8_t *data) {
switch (*value_id) {
case id_qmk_backlight_brightness: {
// level / 255 * BACKLIGHT_LEVELS
- backlight_level_noeeprom(((uint16_t)value_data[0]) * BACKLIGHT_LEVELS / 255);
+ backlight_level_noeeprom(((uint16_t)value_data[0] * BACKLIGHT_LEVELS) / UINT8_MAX);
break;
}
case id_qmk_backlight_effect: {
@@ -460,13 +461,16 @@ void via_qmk_backlight_set_value(uint8_t *data) {
#endif // #if defined(VIA_QMK_BACKLIGHT_ENABLE)
#if defined(VIA_QMK_RGBLIGHT_ENABLE)
+# ifndef RGBLIGHT_LIMIT_VAL
+# define RGBLIGHT_LIMIT_VAL 255
+# endif
void via_qmk_rgblight_get_value(uint8_t *data) {
uint8_t *value_id = &(data[0]);
uint8_t *value_data = &(data[1]);
switch (*value_id) {
case id_qmk_rgblight_brightness: {
- value_data[0] = rgblight_get_val();
+ value_data[0] = ((uint16_t)rgblight_get_val() * UINT8_MAX) / RGBLIGHT_LIMIT_VAL;
break;
}
case id_qmk_rgblight_effect: {
@@ -490,7 +494,7 @@ void via_qmk_rgblight_set_value(uint8_t *data) {
uint8_t *value_data = &(data[1]);
switch (*value_id) {
case id_qmk_rgblight_brightness: {
- rgblight_sethsv_noeeprom(rgblight_get_hue(), rgblight_get_sat(), value_data[0]);
+ rgblight_sethsv_noeeprom(rgblight_get_hue(), rgblight_get_sat(), ((uint16_t)value_data[0] * RGBLIGHT_LIMIT_VAL) / UINT8_MAX);
break;
}
case id_qmk_rgblight_effect: {
@@ -517,6 +521,11 @@ void via_qmk_rgblight_set_value(uint8_t *data) {
#if defined(VIA_QMK_RGB_MATRIX_ENABLE)
+# if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
+# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS
+# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
+# endif
+
// VIA supports only 4 discrete values for effect speed; map these to some
// useful speed values for RGB Matrix.
enum speed_values {
@@ -557,7 +566,7 @@ void via_qmk_rgb_matrix_get_value(uint8_t *data) {
uint8_t *value_data = &(data[1]);
switch (*value_id) {
case id_qmk_rgblight_brightness:
- value_data[0] = rgb_matrix_get_val();
+ value_data[0] = ((uint16_t)rgb_matrix_get_val() * UINT8_MAX) / RGB_MATRIX_MAXIMUM_BRIGHTNESS;
break;
case id_qmk_rgblight_effect:
value_data[0] = rgb_matrix_get_mode();
@@ -577,7 +586,7 @@ void via_qmk_rgb_matrix_set_value(uint8_t *data) {
uint8_t *value_data = &(data[1]);
switch (*value_id) {
case id_qmk_rgblight_brightness:
- rgb_matrix_sethsv_noeeprom(rgb_matrix_get_hue(), rgb_matrix_get_sat(), value_data[0]);
+ rgb_matrix_sethsv_noeeprom(rgb_matrix_get_hue(), rgb_matrix_get_sat(), scale8(value_data[0], RGB_MATRIX_MAXIMUM_BRIGHTNESS));
break;
case id_qmk_rgblight_effect:
rgb_matrix_mode_noeeprom(value_data[0]);
diff --git a/quantum/wear_leveling/tests/backing_mocks.cpp b/quantum/wear_leveling/tests/backing_mocks.cpp
new file mode 100644
index 0000000000..1dbb26f8e7
--- /dev/null
+++ b/quantum/wear_leveling/tests/backing_mocks.cpp
@@ -0,0 +1,154 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "backing_mocks.hpp"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Backing Store Mock implementation
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void MockBackingStore::reset_instance() {
+ for (auto&& e : backing_storage)
+ e.reset();
+
+ locked = true;
+
+ backing_erasure_count = 0;
+ backing_max_write_count = 0;
+ backing_total_write_count = 0;
+
+ backing_init_invoke_count = 0;
+ backing_unlock_invoke_count = 0;
+ backing_erase_invoke_count = 0;
+ backing_write_invoke_count = 0;
+ backing_lock_invoke_count = 0;
+
+ init_success_callback = [](std::uint64_t) { return true; };
+ erase_success_callback = [](std::uint64_t) { return true; };
+ unlock_success_callback = [](std::uint64_t) { return true; };
+ write_success_callback = [](std::uint64_t, std::uint32_t) { return true; };
+ lock_success_callback = [](std::uint64_t) { return true; };
+
+ write_log.clear();
+}
+
+bool MockBackingStore::init(void) {
+ ++backing_init_invoke_count;
+
+ if (init_success_callback) {
+ return init_success_callback(backing_init_invoke_count);
+ }
+ return true;
+}
+
+bool MockBackingStore::unlock(void) {
+ ++backing_unlock_invoke_count;
+
+ EXPECT_TRUE(is_locked()) << "Attempted to unlock but was not locked";
+ locked = false;
+
+ if (unlock_success_callback) {
+ return unlock_success_callback(backing_unlock_invoke_count);
+ }
+ return true;
+}
+
+bool MockBackingStore::erase(void) {
+ ++backing_erase_invoke_count;
+
+ // Erase each slot
+ for (std::size_t i = 0; i < backing_storage.size(); ++i) {
+ // Drop out of erase early with failure if we need to
+ if (erase_success_callback && !erase_success_callback(backing_erase_invoke_count)) {
+ append_log(true);
+ return false;
+ }
+
+ backing_storage[i].erase();
+ }
+
+ // Keep track of the erase in the write log so that we can verify during tests
+ append_log(true);
+
+ ++backing_erasure_count;
+ return true;
+}
+
+bool MockBackingStore::write(uint32_t address, backing_store_int_t value) {
+ ++backing_write_invoke_count;
+
+ // precondition: value's buffer size already matches BACKING_STORE_WRITE_SIZE
+ EXPECT_TRUE(address % BACKING_STORE_WRITE_SIZE == 0) << "Supplied address was not aligned with the backing store integral size";
+ EXPECT_TRUE(address + BACKING_STORE_WRITE_SIZE <= WEAR_LEVELING_BACKING_SIZE) << "Address would result of out-of-bounds access";
+ EXPECT_FALSE(is_locked()) << "Write was attempted without being unlocked first";
+
+ // Drop out of write early with failure if we need to
+ if (write_success_callback && !write_success_callback(backing_write_invoke_count, address)) {
+ return false;
+ }
+
+ // Write the complement as we're simulating flash memory -- 0xFF means 0x00
+ std::size_t index = address / BACKING_STORE_WRITE_SIZE;
+ backing_storage[index].set(~value);
+
+ // Keep track of the write log so that we can verify during tests
+ append_log(address, value);
+
+ // Keep track of the total number of writes into the backing store
+ ++backing_total_write_count;
+
+ return true;
+}
+
+bool MockBackingStore::lock(void) {
+ ++backing_lock_invoke_count;
+
+ EXPECT_FALSE(is_locked()) << "Attempted to lock but was not unlocked";
+ locked = true;
+
+ if (lock_success_callback) {
+ return lock_success_callback(backing_lock_invoke_count);
+ }
+ return true;
+}
+
+bool MockBackingStore::read(uint32_t address, backing_store_int_t& value) const {
+ // precondition: value's buffer size already matches BACKING_STORE_WRITE_SIZE
+ EXPECT_TRUE(address % BACKING_STORE_WRITE_SIZE == 0) << "Supplied address was not aligned with the backing store integral size";
+ EXPECT_TRUE(address + BACKING_STORE_WRITE_SIZE <= WEAR_LEVELING_BACKING_SIZE) << "Address would result of out-of-bounds access";
+
+ // Read and take the complement as we're simulating flash memory -- 0xFF means 0x00
+ std::size_t index = address / BACKING_STORE_WRITE_SIZE;
+ value = ~backing_storage[index].get();
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Backing Implementation
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+extern "C" bool backing_store_init(void) {
+ return MockBackingStore::Instance().init();
+}
+
+extern "C" bool backing_store_unlock(void) {
+ return MockBackingStore::Instance().unlock();
+}
+
+extern "C" bool backing_store_erase(void) {
+ return MockBackingStore::Instance().erase();
+}
+
+extern "C" bool backing_store_write(uint32_t address, backing_store_int_t value) {
+ return MockBackingStore::Instance().write(address, value);
+}
+
+extern "C" bool backing_store_lock(void) {
+ return MockBackingStore::Instance().lock();
+}
+
+extern "C" bool backing_store_read(uint32_t address, backing_store_int_t* value) {
+ return MockBackingStore::Instance().read(address, *value);
+}
diff --git a/quantum/wear_leveling/tests/backing_mocks.hpp b/quantum/wear_leveling/tests/backing_mocks.hpp
new file mode 100644
index 0000000000..e7af7895f3
--- /dev/null
+++ b/quantum/wear_leveling/tests/backing_mocks.hpp
@@ -0,0 +1,210 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+#include <algorithm>
+#include <array>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <type_traits>
+#include <vector>
+
+extern "C" {
+#include "fnv.h"
+#include "wear_leveling.h"
+#include "wear_leveling_internal.h"
+};
+
+// Maximum number of mock write log entries to keep
+using MOCK_WRITE_LOG_MAX_ENTRIES = std::integral_constant<std::size_t, 1024>;
+// Complement to the backing store integral, for emulating flash erases of all bytes=0xFF
+using BACKING_STORE_INTEGRAL_COMPLEMENT = std::integral_constant<backing_store_int_t, ((backing_store_int_t)(~(backing_store_int_t)0))>;
+// Total number of elements stored in the backing arrays
+using BACKING_STORE_ELEMENT_COUNT = std::integral_constant<std::size_t, (WEAR_LEVELING_BACKING_SIZE / sizeof(backing_store_int_t))>;
+
+class MockBackingStoreElement {
+ private:
+ backing_store_int_t value;
+ std::size_t writes;
+ std::size_t erases;
+
+ public:
+ MockBackingStoreElement() : value(BACKING_STORE_INTEGRAL_COMPLEMENT::value), writes(0), erases(0) {}
+ void reset() {
+ erase();
+ writes = 0;
+ erases = 0;
+ }
+ void erase() {
+ if (!is_erased()) {
+ ++erases;
+ }
+ value = BACKING_STORE_INTEGRAL_COMPLEMENT::value;
+ }
+ backing_store_int_t get() const {
+ return value;
+ }
+ void set(const backing_store_int_t& v) {
+ EXPECT_TRUE(is_erased()) << "Attempted write at index which isn't empty.";
+ value = v;
+ ++writes;
+ }
+ std::size_t num_writes() const {
+ return writes;
+ }
+ std::size_t num_erases() const {
+ return erases;
+ }
+ bool is_erased() const {
+ return value == BACKING_STORE_INTEGRAL_COMPLEMENT::value;
+ }
+};
+
+struct MockBackingStoreLogEntry {
+ MockBackingStoreLogEntry(uint32_t address, backing_store_int_t value) : address(address), value(value), erased(false) {}
+ MockBackingStoreLogEntry(bool erased) : address(0), value(0), erased(erased) {}
+ uint32_t address = 0; // The address of the operation
+ backing_store_int_t value = 0; // The value of the operation
+ bool erased = false; // Whether the entire backing store was erased
+};
+
+class MockBackingStore {
+ private:
+ MockBackingStore() {
+ reset_instance();
+ }
+
+ // Type containing each of the entries and the write counts
+ using storage_t = std::array<MockBackingStoreElement, BACKING_STORE_ELEMENT_COUNT::value>;
+
+ // Whether the backing store is locked
+ bool locked;
+ // The actual data stored in the emulated flash
+ storage_t backing_storage;
+ // The number of erase cycles that have occurred
+ std::uint64_t backing_erasure_count;
+ // The max number of writes to an element of the backing store
+ std::uint64_t backing_max_write_count;
+ // The total number of writes to all elements of the backing store
+ std::uint64_t backing_total_write_count;
+ // The write log for the backing store
+ std::vector<MockBackingStoreLogEntry> write_log;
+
+ // The number of times each API was invoked
+ std::uint64_t backing_init_invoke_count;
+ std::uint64_t backing_unlock_invoke_count;
+ std::uint64_t backing_erase_invoke_count;
+ std::uint64_t backing_write_invoke_count;
+ std::uint64_t backing_lock_invoke_count;
+
+ // Whether init should succeed
+ std::function<bool(std::uint64_t)> init_success_callback;
+ // Whether erase should succeed
+ std::function<bool(std::uint64_t)> erase_success_callback;
+ // Whether unlocks should succeed
+ std::function<bool(std::uint64_t)> unlock_success_callback;
+ // Whether writes should succeed
+ std::function<bool(std::uint64_t, std::uint32_t)> write_success_callback;
+ // Whether locks should succeed
+ std::function<bool(std::uint64_t)> lock_success_callback;
+
+ template <typename... Args>
+ void append_log(Args&&... args) {
+ if (write_log.size() < MOCK_WRITE_LOG_MAX_ENTRIES::value) {
+ write_log.emplace_back(std::forward<Args>(args)...);
+ }
+ }
+
+ public:
+ static MockBackingStore& Instance() {
+ static MockBackingStore instance;
+ return instance;
+ }
+
+ std::uint64_t erasure_count() const {
+ return backing_erasure_count;
+ }
+ std::uint64_t max_write_count() const {
+ return backing_max_write_count;
+ }
+ std::uint64_t total_write_count() const {
+ return backing_total_write_count;
+ }
+
+ // The number of times each API was invoked
+ std::uint64_t init_invoke_count() const {
+ return backing_init_invoke_count;
+ }
+ std::uint64_t unlock_invoke_count() const {
+ return backing_unlock_invoke_count;
+ }
+ std::uint64_t erase_invoke_count() const {
+ return backing_erase_invoke_count;
+ }
+ std::uint64_t write_invoke_count() const {
+ return backing_write_invoke_count;
+ }
+ std::uint64_t lock_invoke_count() const {
+ return backing_lock_invoke_count;
+ }
+
+ // Clear out the internal data for the next run
+ void reset_instance();
+
+ bool is_locked() const {
+ return locked;
+ }
+
+ // APIs for the backing store
+ bool init();
+ bool unlock();
+ bool erase();
+ bool write(std::uint32_t address, backing_store_int_t value);
+ bool lock();
+ bool read(std::uint32_t address, backing_store_int_t& value) const;
+
+ // Control over when init/writes/erases should succeed
+ void set_init_callback(std::function<bool(std::uint64_t)> callback) {
+ init_success_callback = callback;
+ }
+ void set_erase_callback(std::function<bool(std::uint64_t)> callback) {
+ erase_success_callback = callback;
+ }
+ void set_unlock_callback(std::function<bool(std::uint64_t)> callback) {
+ unlock_success_callback = callback;
+ }
+ void set_write_callback(std::function<bool(std::uint64_t, std::uint32_t)> callback) {
+ write_success_callback = callback;
+ }
+ void set_lock_callback(std::function<bool(std::uint64_t)> callback) {
+ lock_success_callback = callback;
+ }
+
+ auto storage_begin() const -> decltype(backing_storage.begin()) {
+ return backing_storage.begin();
+ }
+ auto storage_end() const -> decltype(backing_storage.end()) {
+ return backing_storage.end();
+ }
+
+ auto storage_begin() -> decltype(backing_storage.begin()) {
+ return backing_storage.begin();
+ }
+ auto storage_end() -> decltype(backing_storage.end()) {
+ return backing_storage.end();
+ }
+
+ auto log_begin() -> decltype(write_log.begin()) {
+ return write_log.begin();
+ }
+ auto log_end() -> decltype(write_log.end()) {
+ return write_log.end();
+ }
+
+ auto log_begin() const -> decltype(write_log.begin()) {
+ return write_log.begin();
+ }
+ auto log_end() const -> decltype(write_log.end()) {
+ return write_log.end();
+ }
+};
diff --git a/quantum/wear_leveling/tests/rules.mk b/quantum/wear_leveling/tests/rules.mk
new file mode 100644
index 0000000000..4d7a964049
--- /dev/null
+++ b/quantum/wear_leveling/tests/rules.mk
@@ -0,0 +1,66 @@
+wear_leveling_common_DEFS := \
+ -DWEAR_LEVELING_TESTS
+wear_leveling_common_SRC := \
+ $(LIB_PATH)/fnv/qmk_fnv_type_validation.c \
+ $(LIB_PATH)/fnv/hash_32a.c \
+ $(LIB_PATH)/fnv/hash_64a.c \
+ $(QUANTUM_PATH)/wear_leveling/wear_leveling.c \
+ $(QUANTUM_PATH)/wear_leveling/tests/backing_mocks.cpp
+wear_leveling_common_INC := \
+ $(LIB_PATH)/fnv \
+ $(QUANTUM_PATH)/wear_leveling
+
+wear_leveling_general_DEFS := \
+ $(wear_leveling_common_DEFS) \
+ -DBACKING_STORE_WRITE_SIZE=2 \
+ -DWEAR_LEVELING_BACKING_SIZE=48 \
+ -DWEAR_LEVELING_LOGICAL_SIZE=16
+wear_leveling_general_SRC := \
+ $(wear_leveling_common_SRC) \
+ $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_general.cpp
+wear_leveling_general_INC := \
+ $(wear_leveling_common_INC)
+
+wear_leveling_2byte_optimized_writes_DEFS := \
+ $(wear_leveling_common_DEFS) \
+ -DBACKING_STORE_WRITE_SIZE=2 \
+ -DWEAR_LEVELING_BACKING_SIZE=65536 \
+ -DWEAR_LEVELING_LOGICAL_SIZE=32768
+wear_leveling_2byte_optimized_writes_SRC := \
+ $(wear_leveling_common_SRC) \
+ $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp
+wear_leveling_2byte_optimized_writes_INC := \
+ $(wear_leveling_common_INC)
+
+wear_leveling_2byte_DEFS := \
+ $(wear_leveling_common_DEFS) \
+ -DBACKING_STORE_WRITE_SIZE=2 \
+ -DWEAR_LEVELING_BACKING_SIZE=48 \
+ -DWEAR_LEVELING_LOGICAL_SIZE=16
+wear_leveling_2byte_SRC := \
+ $(wear_leveling_common_SRC) \
+ $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_2byte.cpp
+wear_leveling_2byte_INC := \
+ $(wear_leveling_common_INC)
+
+wear_leveling_4byte_DEFS := \
+ $(wear_leveling_common_DEFS) \
+ -DBACKING_STORE_WRITE_SIZE=4 \
+ -DWEAR_LEVELING_BACKING_SIZE=48 \
+ -DWEAR_LEVELING_LOGICAL_SIZE=16
+wear_leveling_4byte_SRC := \
+ $(wear_leveling_common_SRC) \
+ $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_4byte.cpp
+wear_leveling_4byte_INC := \
+ $(wear_leveling_common_INC)
+
+wear_leveling_8byte_DEFS := \
+ $(wear_leveling_common_DEFS) \
+ -DBACKING_STORE_WRITE_SIZE=8 \
+ -DWEAR_LEVELING_BACKING_SIZE=48 \
+ -DWEAR_LEVELING_LOGICAL_SIZE=16
+wear_leveling_8byte_SRC := \
+ $(wear_leveling_common_SRC) \
+ $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_8byte.cpp
+wear_leveling_8byte_INC := \
+ $(wear_leveling_common_INC) \ No newline at end of file
diff --git a/quantum/wear_leveling/tests/testlist.mk b/quantum/wear_leveling/tests/testlist.mk
new file mode 100644
index 0000000000..32cfc178b4
--- /dev/null
+++ b/quantum/wear_leveling/tests/testlist.mk
@@ -0,0 +1,6 @@
+TEST_LIST += \
+ wear_leveling_general \
+ wear_leveling_2byte_optimized_writes \
+ wear_leveling_2byte \
+ wear_leveling_4byte \
+ wear_leveling_8byte
diff --git a/quantum/wear_leveling/tests/wear_leveling_2byte.cpp b/quantum/wear_leveling/tests/wear_leveling_2byte.cpp
new file mode 100644
index 0000000000..b749c32b04
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_2byte.cpp
@@ -0,0 +1,228 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <numeric>
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "backing_mocks.hpp"
+
+class WearLeveling2Byte : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ MockBackingStore::Instance().reset_instance();
+ wear_leveling_init();
+ }
+};
+
+static std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> verify_data;
+
+static wear_leveling_status_t test_write(const uint32_t address, const void* value, size_t length) {
+ memcpy(&verify_data[address], value, length);
+ return wear_leveling_write(address, value, length);
+}
+
+/**
+ * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location.
+ */
+TEST_F(WearLeveling2Byte, FirstWriteOccursAfterHash) {
+ auto& inst = MockBackingStore::Instance();
+ uint8_t test_value = 0x15;
+ test_write(0x02, &test_value, sizeof(test_value));
+ EXPECT_EQ(inst.log_begin()->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
+}
+
+/**
+ * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location, after an erase has occurred.
+ */
+TEST_F(WearLeveling2Byte, FirstWriteOccursAfterHash_AfterErase) {
+ auto& inst = MockBackingStore::Instance();
+ uint8_t test_value = 0x15;
+ wear_leveling_erase();
+ test_write(0x02, &test_value, sizeof(test_value));
+ EXPECT_EQ((inst.log_begin() + 1)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
+}
+
+/**
+ * This test forces consolidation by writing enough to the write log that it overflows, consolidating the data into the
+ * base logical area.
+ */
+TEST_F(WearLeveling2Byte, ConsolidationOverflow) {
+ auto& inst = MockBackingStore::Instance();
+
+ // Generate a test block of data which forces OPTIMIZED_64 writes
+ std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> testvalue;
+
+ // Write the data
+ std::iota(testvalue.begin(), testvalue.end(), 0x20);
+ EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_CONSOLIDATED) << "Write returned incorrect status";
+ uint8_t dummy = 0x40;
+ EXPECT_EQ(test_write(0x04, &dummy, sizeof(dummy)), WEAR_LEVELING_SUCCESS) << "Write returned incorrect status";
+
+ // All writes are at address<64, so each logical byte written will generate 1 write log entry, thus 1 backing store write.
+ // Expected log:
+ // [0..11]: optimised64, backing address 0x18, logical address 0x00
+ // [12]: erase
+ // [13..20]: consolidated data, backing address 0x00, logical address 0x00
+ // [21..24]: FNV1a_64 result, backing address 0x10
+ // [25]: optimised64, backing address 0x18, logical address 0x04
+ EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), 26);
+
+ // Verify the backing store writes for the write log
+ std::size_t index;
+ write_log_entry_t e;
+ for (index = 0; index < 12; ++index) {
+ auto write_iter = inst.log_begin() + index;
+ EXPECT_EQ(write_iter->address, WEAR_LEVELING_LOGICAL_SIZE + 8 + (index * BACKING_STORE_WRITE_SIZE)) << "Invalid write log address";
+ e.raw16[0] = write_iter->value;
+ EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_OPTIMIZED_64) << "Invalid write log entry type";
+ }
+
+ // Verify the backing store erase
+ {
+ index = 12;
+ auto write_iter = inst.log_begin() + index;
+ e.raw16[0] = write_iter->value;
+ EXPECT_TRUE(write_iter->erased) << "Backing store erase did not occur as required";
+ }
+
+ // Verify the backing store writes for consolidation
+ for (index = 13; index < 21; ++index) {
+ auto write_iter = inst.log_begin() + index;
+ EXPECT_EQ(write_iter->address, (index - 13) * BACKING_STORE_WRITE_SIZE) << "Invalid write log entry address";
+ }
+
+ // Verify the FNV1a_64 write
+ {
+ EXPECT_EQ((inst.log_begin() + 21)->address, WEAR_LEVELING_LOGICAL_SIZE) << "Invalid write log address";
+ e.raw16[0] = (inst.log_begin() + 21)->value;
+ e.raw16[1] = (inst.log_begin() + 22)->value;
+ e.raw16[2] = (inst.log_begin() + 23)->value;
+ e.raw16[3] = (inst.log_begin() + 24)->value;
+ EXPECT_EQ(e.raw64, fnv_64a_buf(testvalue.data(), testvalue.size(), FNV1A_64_INIT)) << "Invalid checksum"; // Note that checksum is based on testvalue, as we overwrote one byte and need to consult the consolidated data, not the current
+ }
+
+ // Verify the final write
+ EXPECT_EQ((inst.log_begin() + 25)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid write log address";
+
+ // Verify the data is what we expected
+ std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
+
+ // Re-init and re-read, verifying the reload capability
+ EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
+}
+
+/**
+ * This test verifies multibyte readback gets canceled with an out-of-bounds address.
+ */
+TEST_F(WearLeveling2Byte, PlaybackReadbackMultibyte_OOB) {
+ auto& inst = MockBackingStore::Instance();
+ auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
+
+ // Invalid FNV1a_64 hash
+ (logstart + 0)->set(0);
+ (logstart + 1)->set(0);
+ (logstart + 2)->set(0);
+ (logstart + 3)->set(0);
+
+ // Set up a 2-byte logical write of [0x11,0x12] at logical offset 0x01
+ auto entry0 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
+ entry0.raw8[3] = 0x11;
+ entry0.raw8[4] = 0x12;
+ (logstart + 4)->set(~entry0.raw16[0]);
+ (logstart + 5)->set(~entry0.raw16[1]);
+ (logstart + 6)->set(~entry0.raw16[2]);
+
+ // Set up a 2-byte logical write of [0x13,0x14] at logical offset 0x1000 (out of bounds)
+ auto entry1 = LOG_ENTRY_MAKE_MULTIBYTE(0x1000, 2);
+ entry1.raw8[3] = 0x13;
+ entry1.raw8[4] = 0x14;
+ (logstart + 7)->set(~entry1.raw16[0]);
+ (logstart + 8)->set(~entry1.raw16[1]);
+ (logstart + 9)->set(~entry1.raw16[2]);
+
+ // Set up a 2-byte logical write of [0x15,0x16] at logical offset 0x01
+ auto entry2 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
+ entry2.raw8[3] = 0x15;
+ entry2.raw8[4] = 0x16;
+ (logstart + 10)->set(~entry2.raw16[0]);
+ (logstart + 11)->set(~entry2.raw16[1]);
+ (logstart + 12)->set(~entry2.raw16[2]);
+
+ EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
+ EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
+ EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
+
+ uint8_t buf[2];
+ wear_leveling_read(0x01, buf, sizeof(buf));
+ EXPECT_EQ(buf[0], 0x11) << "Readback should have maintained the previous pre-failure value from the write log";
+ EXPECT_EQ(buf[1], 0x12) << "Readback should have maintained the previous pre-failure value from the write log";
+}
+
+/**
+ * This test verifies optimized 64 readback gets canceled with an out-of-bounds address.
+ */
+TEST_F(WearLeveling2Byte, PlaybackReadbackOptimized64_OOB) {
+ auto& inst = MockBackingStore::Instance();
+ auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
+
+ // Invalid FNV1a_64 hash
+ (logstart + 0)->set(0);
+ (logstart + 1)->set(0);
+ (logstart + 2)->set(0);
+ (logstart + 3)->set(0);
+
+ // Set up a 1-byte logical write of 0x11 at logical offset 0x01
+ auto entry0 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x01, 0x11);
+ (logstart + 4)->set(~entry0.raw16[0]);
+
+ // Set up a 1-byte logical write of 0x11 at logical offset 0x30 (out of bounds)
+ auto entry1 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x30, 0x11);
+ (logstart + 5)->set(~entry1.raw16[0]);
+
+ // Set up a 1-byte logical write of 0x12 at logical offset 0x01
+ auto entry2 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x01, 0x12);
+ (logstart + 6)->set(~entry2.raw16[0]);
+
+ EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
+ EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
+ EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
+ uint8_t tmp;
+ wear_leveling_read(0x01, &tmp, sizeof(tmp));
+ EXPECT_EQ(tmp, 0x11) << "Readback should have maintained the previous pre-failure value from the write log";
+}
+
+/**
+ * This test verifies word 0/1 readback gets canceled with an out-of-bounds address.
+ */
+TEST_F(WearLeveling2Byte, PlaybackReadbackWord01_OOB) {
+ auto& inst = MockBackingStore::Instance();
+ auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
+
+ // Invalid FNV1a_64 hash
+ (logstart + 0)->set(0);
+ (logstart + 1)->set(0);
+ (logstart + 2)->set(0);
+ (logstart + 3)->set(0);
+
+ // Set up a 1-byte logical write of 1 at logical offset 0x02
+ auto entry0 = LOG_ENTRY_MAKE_WORD_01(0x02, 1);
+ (logstart + 4)->set(~entry0.raw16[0]);
+
+ // Set up a 1-byte logical write of 1 at logical offset 0x1000 (out of bounds)
+ auto entry1 = LOG_ENTRY_MAKE_WORD_01(0x1000, 1);
+ (logstart + 5)->set(~entry1.raw16[0]);
+
+ // Set up a 1-byte logical write of 0 at logical offset 0x02
+ auto entry2 = LOG_ENTRY_MAKE_WORD_01(0x02, 0);
+ (logstart + 6)->set(~entry2.raw16[0]);
+
+ EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
+ EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
+ EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
+ uint8_t tmp;
+ wear_leveling_read(0x02, &tmp, sizeof(tmp));
+ EXPECT_EQ(tmp, 1) << "Readback should have maintained the previous pre-failure value from the write log";
+}
diff --git a/quantum/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp b/quantum/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp
new file mode 100644
index 0000000000..0b03113c89
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp
@@ -0,0 +1,295 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <numeric>
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "backing_mocks.hpp"
+
+class WearLeveling2ByteOptimizedWrites : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ MockBackingStore::Instance().reset_instance();
+ wear_leveling_init();
+ }
+};
+
+static std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> verify_data;
+
+static wear_leveling_status_t test_write(const uint32_t address, const void* value, size_t length) {
+ memcpy(&verify_data[address], value, length);
+ return wear_leveling_write(address, value, length);
+}
+
+/**
+ * This test ensures the correct number of backing store writes occurs with a multibyte write, given the input buffer size.
+ */
+TEST_F(WearLeveling2ByteOptimizedWrites, MultibyteBackingStoreWriteCounts) {
+ auto& inst = MockBackingStore::Instance();
+
+ for (std::size_t length = 1; length <= 5; ++length) {
+ // Clear things out
+ std::fill(verify_data.begin(), verify_data.end(), 0);
+ inst.reset_instance();
+ wear_leveling_init();
+
+ // Generate a test block of data
+ std::vector<std::uint8_t> testvalue(length);
+ std::iota(testvalue.begin(), testvalue.end(), 0x20);
+
+ // Write the data
+ EXPECT_EQ(test_write(2000, testvalue.data(), testvalue.size()), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
+
+ std::size_t expected;
+ if (length > 3) {
+ expected = 4;
+ } else if (length > 1) {
+ expected = 3;
+ } else {
+ expected = 2;
+ }
+
+ // Check that we got the expected number of write log entries
+ EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), expected);
+ }
+}
+
+/**
+ * This test runs through writing U16 values of `0` or `1` over the entire logical address range, to even addresses only.
+ * - Addresses <16384 will result in a single optimised backing write
+ * - Higher addresses will result in a multibyte write of 3 backing writes
+ */
+TEST_F(WearLeveling2ByteOptimizedWrites, WriteOneThenZeroToEvenAddresses) {
+ auto& inst = MockBackingStore::Instance();
+
+ // Only attempt writes for each address up to a limit that would NOT force a consolidated data write.
+ std::size_t writes_per_loop = (MOCK_WRITE_LOG_MAX_ENTRIES::value / 6) - 1; // Worst case is 6 writes for each pair of writes of 0/1
+ std::size_t final_address;
+ for (uint32_t address = 0; address < WEAR_LEVELING_LOGICAL_SIZE; address += (writes_per_loop * 2)) {
+ // Clear things out
+ std::fill(verify_data.begin(), verify_data.end(), 0);
+ inst.reset_instance();
+ wear_leveling_init();
+
+ // Loop through all the addresses in this range
+ std::size_t expected = 0;
+ for (uint32_t offset = 0; offset < (writes_per_loop * 2); offset += 2) {
+ // If we're about to exceed the limit of the logical store, skip the writes
+ if (address + offset + 2 > WEAR_LEVELING_LOGICAL_SIZE) {
+ break;
+ }
+
+ // The default erased value of the wear-leveling cache is zero, so we write a one first, then a zero, to ensure a backing store write occurs.
+ uint16_t val = 1;
+ EXPECT_EQ(test_write(address + offset, &val, sizeof(val)), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
+ val = 0;
+ EXPECT_EQ(test_write(address + offset, &val, sizeof(val)), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
+
+ std::size_t backing_store_writes_expected = 0;
+ if (address + offset < 16384) {
+ // A U16 value of 0/1 at an even address <16384 will result in 1 backing write each, so we need 2 backing writes for 2 logical writes
+ backing_store_writes_expected = 2;
+ } else {
+ // All other addresses result in a multibyte write (3 backing store writes) to write two local bytes of data
+ backing_store_writes_expected = 6;
+ }
+
+ // Keep track of the total number of expected writes to the backing store
+ expected += backing_store_writes_expected;
+
+ // Verify we're at the correct number of writes
+ EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), expected) << "Write log doesn't match required number of backing store writes for address " << (address + offset);
+
+ // Verify that the write log entries we expect are actually present
+ std::size_t write_index = expected - backing_store_writes_expected;
+ auto write_iter = inst.log_begin() + write_index;
+ write_log_entry_t e;
+ if (address + offset < 16384) {
+ // A U16 value of 0/1 at an even address <16384 will result in 1 backing write each, so we need 2 backing writes for 2 logical writes
+ for (std::size_t i = 0; i < 2; ++i) {
+ e.raw16[0] = write_iter->value;
+ EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_WORD_01) << "Invalid write log entry type at " << (address + offset);
+ ++write_iter;
+ }
+ } else {
+ // Multibyte write
+ e.raw16[0] = write_iter->value;
+ EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type at " << (address + offset);
+ EXPECT_EQ(LOG_ENTRY_MULTIBYTE_GET_LENGTH(e), 2) << "Invalid write log entry length at " << (address + offset);
+ ++write_iter;
+ }
+
+ // Keep track of the final address written, so we can verify the entire logical range was handled
+ final_address = address + offset;
+ }
+
+ // Verify the number of writes that occurred to the backing store
+ size_t backing_write_count = std::distance(inst.log_begin(), inst.log_end());
+ EXPECT_EQ(backing_write_count, expected) << "Invalid write count at address " << address;
+
+ // Verify the data is what we expected
+ std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback for address " << address << " did not match";
+
+ // Re-init and re-read, testing the reload capability
+ EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback for address " << address << " did not match";
+ }
+
+ // Verify the full range of the logical area got written
+ EXPECT_EQ(final_address, WEAR_LEVELING_LOGICAL_SIZE - 2) << "Invalid final write address";
+}
+
+/**
+ * This test runs through writing U16 values of `0` or `1` over the entire logical address range, to odd addresses only.
+ * - Addresses <63 will result in 2 optimised backing writes
+ * - Address 63 results in a single optimised backing write for the first logical byte, and a multibyte write of 2 backing writes for the second logical byte
+ * - Higher addresses will result in a multibyte write of 3 backing writes
+ */
+TEST_F(WearLeveling2ByteOptimizedWrites, WriteOneThenZeroToOddAddresses) {
+ auto& inst = MockBackingStore::Instance();
+
+ // Only attempt writes for each address up to a limit that would NOT force a consolidated data write.
+ std::size_t writes_per_loop = (MOCK_WRITE_LOG_MAX_ENTRIES::value / 6) - 1; // Worst case is 6 writes for each pair of writes of 0/1
+ std::size_t final_address;
+ for (uint32_t address = 1; address < WEAR_LEVELING_LOGICAL_SIZE; address += (writes_per_loop * 2)) {
+ // Clear things out
+ std::fill(verify_data.begin(), verify_data.end(), 0);
+ inst.reset_instance();
+ wear_leveling_init();
+
+ // Loop through all the addresses in this range
+ std::size_t expected = 0;
+ for (uint32_t offset = 0; offset < (writes_per_loop * 2); offset += 2) {
+ // If we're about to exceed the limit of the logical store, skip the writes
+ if (address + offset + 2 > WEAR_LEVELING_LOGICAL_SIZE) {
+ break;
+ }
+
+ // The default erased value of the wear-leveling cache is zero, so we write a one first, then a zero, to ensure a backing store write occurs.
+ uint16_t val = 1;
+ EXPECT_EQ(test_write(address + offset, &val, sizeof(val)), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
+ val = 0;
+ EXPECT_EQ(test_write(address + offset, &val, sizeof(val)), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
+
+ std::size_t backing_store_writes_expected = 0;
+ if (address + offset < 63) {
+ // A U16 value of 0/1 at an odd address <64 will result in 2 backing writes each, so we need 4 backing writes for 2 logical writes
+ backing_store_writes_expected = 4;
+ } else if (address + offset == 63) {
+ // If we're straddling the boundary for optimised bytes (addr==64), then the first logical byte is written using the optimised write (1 backing
+ // store write), and the second logical byte uses a multibyte write (2 backing store writes)
+ backing_store_writes_expected = 2 // First logical bytes written using optimised log entries
+ + 4; // Second logical bytes written using multibyte log entries
+ } else {
+ // All other addresses result in a multibyte write (3 backing store writes) to write two local bytes of data
+ backing_store_writes_expected = 6;
+ }
+
+ // Keep track of the total number of expected writes to the backing store
+ expected += backing_store_writes_expected;
+
+ // Verify we're at the correct number of writes
+ EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), expected) << "Write log doesn't match required number of backing store writes for address " << (address + offset);
+
+ // Verify that the write log entries we expect are actually present
+ std::size_t write_index = expected - backing_store_writes_expected;
+ auto write_iter = inst.log_begin() + write_index;
+ write_log_entry_t e;
+ if (address + offset < 63) {
+ // A U16 value of 0/1 at an odd address <64 will result in 2 backing writes each, so we need 4 backing writes for 2 logical writes
+ for (std::size_t i = 0; i < 4; ++i) {
+ e.raw16[0] = write_iter->value;
+ EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_OPTIMIZED_64) << "Invalid write log entry type";
+ ++write_iter;
+ }
+ } else if (address + offset == 63) {
+ // First log entry is the 64-addr optimised one
+ e.raw16[0] = write_iter->value;
+ EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_OPTIMIZED_64) << "Invalid write log entry type";
+ ++write_iter;
+
+ // Second log entry is the multibyte entry for the second logical byte
+ e.raw16[0] = write_iter->value;
+ EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type";
+ EXPECT_EQ(LOG_ENTRY_MULTIBYTE_GET_LENGTH(e), 1) << "Invalid write log entry length";
+ ++write_iter;
+ } else {
+ // Multibyte write
+ e.raw16[0] = write_iter->value;
+ EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type";
+ EXPECT_EQ(LOG_ENTRY_MULTIBYTE_GET_LENGTH(e), 2) << "Invalid write log entry length";
+ ++write_iter;
+ }
+
+ // Keep track of the final address written, so we can verify the entire logical range was handled
+ final_address = address + offset;
+ }
+
+ // Verify the number of writes that occurred to the backing store
+ size_t backing_write_count = std::distance(inst.log_begin(), inst.log_end());
+ EXPECT_EQ(backing_write_count, expected) << "Invalid write count at address " << address;
+
+ // Verify the data is what we expected
+ std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback for address " << address << " did not match";
+
+ // Re-init and re-read, testing the reload capability
+ EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback for address " << address << " did not match";
+ }
+
+ // Verify the full range of the logical area got written
+ EXPECT_EQ(final_address, WEAR_LEVELING_LOGICAL_SIZE - 3) << "Invalid final write address";
+}
+
+/**
+ * This test verifies readback after playback of the write log, simulating power loss and reboot.
+ */
+TEST_F(WearLeveling2ByteOptimizedWrites, PlaybackReadbackOptimized64_Success) {
+ auto& inst = MockBackingStore::Instance();
+ auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
+
+ // Invalid FNV1a_64 hash
+ (logstart + 0)->set(0);
+ (logstart + 1)->set(0);
+ (logstart + 2)->set(0);
+ (logstart + 3)->set(0);
+
+ // Set up a 1-byte logical write of 0x11 at logical offset 0x01
+ auto entry0 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x01, 0x11);
+ (logstart + 4)->set(~entry0.raw16[0]); // start at offset 4 to skip FNV1a_64 result
+
+ wear_leveling_init();
+ uint8_t tmp;
+
+ wear_leveling_read(0x01, &tmp, sizeof(tmp));
+ EXPECT_EQ(tmp, 0x11) << "Failed to read back the seeded data";
+}
+
+/**
+ * This test verifies readback after playback of the write log, simulating power loss and reboot.
+ */
+TEST_F(WearLeveling2ByteOptimizedWrites, PlaybackReadbackWord01_Success) {
+ auto& inst = MockBackingStore::Instance();
+ auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
+
+ // Invalid FNV1a_64 hash
+ (logstart + 0)->set(0);
+ (logstart + 1)->set(0);
+ (logstart + 2)->set(0);
+ (logstart + 3)->set(0);
+
+ // Set up a 1-byte logical write of 1 at logical offset 0x02
+ auto entry0 = LOG_ENTRY_MAKE_WORD_01(0x02, 1);
+ (logstart + 4)->set(~entry0.raw16[0]); // start at offset 4 to skip FNV1a_64 result
+
+ wear_leveling_init();
+ uint8_t tmp;
+
+ wear_leveling_read(0x02, &tmp, sizeof(tmp));
+ EXPECT_EQ(tmp, 1) << "Failed to read back the seeded data";
+}
diff --git a/quantum/wear_leveling/tests/wear_leveling_4byte.cpp b/quantum/wear_leveling/tests/wear_leveling_4byte.cpp
new file mode 100644
index 0000000000..54482c5fe7
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_4byte.cpp
@@ -0,0 +1,193 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <numeric>
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "backing_mocks.hpp"
+
+class WearLeveling4Byte : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ MockBackingStore::Instance().reset_instance();
+ wear_leveling_init();
+ }
+};
+
+static std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> verify_data;
+
+static wear_leveling_status_t test_write(const uint32_t address, const void* value, size_t length) {
+ memcpy(&verify_data[address], value, length);
+ return wear_leveling_write(address, value, length);
+}
+
+/**
+ * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location.
+ */
+TEST_F(WearLeveling4Byte, FirstWriteOccursAfterHash) {
+ auto& inst = MockBackingStore::Instance();
+ uint8_t test_value = 0x15;
+ test_write(0x02, &test_value, sizeof(test_value));
+ EXPECT_EQ(inst.log_begin()->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
+}
+
+/**
+ * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location, after an erase has occurred.
+ */
+TEST_F(WearLeveling4Byte, FirstWriteOccursAfterHash_AfterErase) {
+ auto& inst = MockBackingStore::Instance();
+ uint8_t test_value = 0x15;
+ wear_leveling_erase();
+ test_write(0x02, &test_value, sizeof(test_value));
+ EXPECT_EQ((inst.log_begin() + 1)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
+}
+
+/**
+ * This test ensures the correct number of backing store writes occurs with a multibyte write, given the input buffer size.
+ */
+TEST_F(WearLeveling4Byte, MultibyteBackingStoreWriteCounts) {
+ auto& inst = MockBackingStore::Instance();
+
+ for (std::size_t length = 1; length <= 5; ++length) {
+ // Clear things out
+ std::fill(verify_data.begin(), verify_data.end(), 0);
+ inst.reset_instance();
+ wear_leveling_init();
+
+ // Generate a test block of data
+ std::vector<std::uint8_t> testvalue(length);
+ std::iota(testvalue.begin(), testvalue.end(), 0x20);
+
+ // Write the data
+ EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
+
+ std::size_t expected;
+ if (length > 1) {
+ expected = 2;
+ } else {
+ expected = 1;
+ }
+
+ // Check that we got the expected number of write log entries
+ EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), expected);
+ }
+}
+
+/**
+ * This test forces consolidation by writing enough to the write log that it overflows, consolidating the data into the
+ * base logical area.
+ */
+TEST_F(WearLeveling4Byte, ConsolidationOverflow) {
+ auto& inst = MockBackingStore::Instance();
+
+ // Generate a test block of data
+ std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> testvalue;
+
+ // Write the data
+ std::iota(testvalue.begin(), testvalue.end(), 0x20);
+ EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_CONSOLIDATED) << "Write returned incorrect status";
+ uint8_t dummy = 0x40;
+ EXPECT_EQ(test_write(0x04, &dummy, sizeof(dummy)), WEAR_LEVELING_SUCCESS) << "Write returned incorrect status";
+
+ // Expected log:
+ // [0,1]: multibyte, 5 bytes, backing address 0x18, logical address 0x00
+ // [2,3]: multibyte, 5 bytes, backing address 0x20, logical address 0x05
+ // [4,5]: multibyte, 5 bytes, backing address 0x28, logical address 0x0A, triggers consolidation
+ // [6]: erase
+ // [7,8]: consolidated data, backing address 0x00, logical address 0x00
+ // [9,10]: consolidated data, backing address 0x08, logical address 0x08
+ // [11,12]: FNV1a_64 result, backing address 0x10
+ // [13]: multibyte, 1 byte, backing address 0x18, logical address 0x04
+ EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), 14);
+
+ // Verify the backing store writes for the write log
+ std::size_t index;
+ write_log_entry_t e;
+ for (index = 0; index < 6; ++index) {
+ auto write_iter = inst.log_begin() + index;
+ EXPECT_EQ(write_iter->address, WEAR_LEVELING_LOGICAL_SIZE + 8 + (index * BACKING_STORE_WRITE_SIZE)) << "Invalid write log address";
+
+ // If this is the backing store write that contains the metadata, verify it
+ if (index % 2 == 0) {
+ write_log_entry_t e;
+ e.raw64 = write_iter->value;
+ EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type";
+ }
+ }
+
+ // Verify the backing store erase
+ {
+ index = 6;
+ auto write_iter = inst.log_begin() + index;
+ e.raw64 = write_iter->value;
+ EXPECT_TRUE(write_iter->erased) << "Backing store erase did not occur as required";
+ }
+
+ // Verify the backing store writes for consolidation
+ for (index = 7; index < 11; ++index) {
+ auto write_iter = inst.log_begin() + index;
+ EXPECT_EQ(write_iter->address, (index - 7) * BACKING_STORE_WRITE_SIZE) << "Invalid write log entry address";
+ }
+
+ // Verify the FNV1a_64 write
+ {
+ EXPECT_EQ((inst.log_begin() + 11)->address, WEAR_LEVELING_LOGICAL_SIZE) << "Invalid write log address";
+ e.raw32[0] = (inst.log_begin() + 11)->value;
+ e.raw32[1] = (inst.log_begin() + 12)->value;
+ EXPECT_EQ(e.raw64, fnv_64a_buf(testvalue.data(), testvalue.size(), FNV1A_64_INIT)) << "Invalid checksum"; // Note that checksum is based on testvalue, as we overwrote one byte and need to consult the consolidated data, not the current
+ }
+
+ // Verify the final write
+ EXPECT_EQ((inst.log_begin() + 13)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid write log address";
+
+ // Verify the data is what we expected
+ std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
+
+ // Re-init and re-read, verifying the reload capability
+ EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
+}
+
+/**
+ * This test verifies multibyte readback gets canceled with an out-of-bounds address.
+ */
+TEST_F(WearLeveling4Byte, PlaybackReadbackMultibyte_OOB) {
+ auto& inst = MockBackingStore::Instance();
+ auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
+
+ // Invalid FNV1a_64 hash
+ (logstart + 0)->set(0);
+ (logstart + 1)->set(0);
+
+ // Set up a 2-byte logical write of [0x11,0x12] at logical offset 0x01
+ auto entry0 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
+ entry0.raw8[3] = 0x11;
+ entry0.raw8[4] = 0x12;
+ (logstart + 2)->set(~entry0.raw32[0]);
+ (logstart + 3)->set(~entry0.raw32[1]);
+
+ // Set up a 2-byte logical write of [0x13,0x14] at logical offset 0x1000 (out of bounds)
+ auto entry1 = LOG_ENTRY_MAKE_MULTIBYTE(0x1000, 2);
+ entry1.raw8[3] = 0x13;
+ entry1.raw8[4] = 0x14;
+ (logstart + 4)->set(~entry1.raw32[0]);
+ (logstart + 5)->set(~entry1.raw32[1]);
+
+ // Set up a 2-byte logical write of [0x15,0x16] at logical offset 0x10
+ auto entry2 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
+ entry2.raw8[3] = 0x15;
+ entry2.raw8[4] = 0x16;
+ (logstart + 6)->set(~entry2.raw32[0]);
+ (logstart + 7)->set(~entry2.raw32[1]);
+
+ EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
+ EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
+ EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
+
+ uint8_t buf[2];
+ wear_leveling_read(0x01, buf, sizeof(buf));
+ EXPECT_EQ(buf[0], 0x11) << "Readback should have maintained the previous pre-failure value from the write log";
+ EXPECT_EQ(buf[1], 0x12) << "Readback should have maintained the previous pre-failure value from the write log";
+}
diff --git a/quantum/wear_leveling/tests/wear_leveling_8byte.cpp b/quantum/wear_leveling/tests/wear_leveling_8byte.cpp
new file mode 100644
index 0000000000..c27c21d034
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_8byte.cpp
@@ -0,0 +1,178 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <numeric>
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "backing_mocks.hpp"
+
+class WearLeveling8Byte : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ MockBackingStore::Instance().reset_instance();
+ wear_leveling_init();
+ }
+};
+
+static std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> verify_data;
+
+static wear_leveling_status_t test_write(const uint32_t address, const void* value, size_t length) {
+ memcpy(&verify_data[address], value, length);
+ return wear_leveling_write(address, value, length);
+}
+
+/**
+ * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location.
+ */
+TEST_F(WearLeveling8Byte, FirstWriteOccursAfterHash) {
+ auto& inst = MockBackingStore::Instance();
+ uint8_t test_value = 0x15;
+ test_write(0x02, &test_value, sizeof(test_value));
+ EXPECT_EQ(inst.log_begin()->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
+}
+
+/**
+ * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location, after an erase has occurred.
+ */
+TEST_F(WearLeveling8Byte, FirstWriteOccursAfterHash_AfterErase) {
+ auto& inst = MockBackingStore::Instance();
+ uint8_t test_value = 0x15;
+ wear_leveling_erase();
+ test_write(0x02, &test_value, sizeof(test_value));
+ EXPECT_EQ((inst.log_begin() + 1)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
+}
+
+/**
+ * This test ensures the correct number of backing store writes occurs with a multibyte write, given the input buffer size.
+ */
+TEST_F(WearLeveling8Byte, MultibyteBackingStoreWriteCounts) {
+ auto& inst = MockBackingStore::Instance();
+
+ for (std::size_t length = 1; length <= 5; ++length) {
+ // Clear things out
+ std::fill(verify_data.begin(), verify_data.end(), 0);
+ inst.reset_instance();
+ wear_leveling_init();
+
+ // Generate a test block of data
+ std::vector<std::uint8_t> testvalue(length);
+ std::iota(testvalue.begin(), testvalue.end(), 0x20);
+
+ // Write the data
+ EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
+
+ // Check that we got the expected number of write log entries
+ EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), 1);
+ }
+}
+
+/**
+ * This test forces consolidation by writing enough to the write log that it overflows, consolidating the data into the
+ * base logical area.
+ */
+TEST_F(WearLeveling8Byte, ConsolidationOverflow) {
+ auto& inst = MockBackingStore::Instance();
+
+ // Generate a test block of data
+ std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> testvalue;
+
+ // Write the data
+ std::iota(testvalue.begin(), testvalue.end(), 0x20);
+ EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_CONSOLIDATED) << "Write returned incorrect status";
+ uint8_t dummy = 0x40;
+ EXPECT_EQ(test_write(0x04, &dummy, sizeof(dummy)), WEAR_LEVELING_SUCCESS) << "Write returned incorrect status";
+
+ // Expected log:
+ // [0]: multibyte, 5 bytes, backing address 0x18, logical address 0x00
+ // [1]: multibyte, 5 bytes, backing address 0x20, logical address 0x05
+ // [2]: multibyte, 5 bytes, backing address 0x28, logical address 0x0A, triggers consolidation
+ // [3]: erase
+ // [4]: consolidated data, backing address 0x00, logical address 0x00
+ // [5]: consolidated data, backing address 0x08, logical address 0x08
+ // [6]: FNV1a_64 result, backing address 0x10
+ // [7]: multibyte, 1 byte, backing address 0x18, logical address 0x04
+ EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), 8);
+
+ // Verify the backing store writes for the write log
+ std::size_t index;
+ write_log_entry_t e;
+ for (index = 0; index < 3; ++index) {
+ auto write_iter = inst.log_begin() + index;
+ EXPECT_EQ(write_iter->address, WEAR_LEVELING_LOGICAL_SIZE + 8 + (index * BACKING_STORE_WRITE_SIZE)) << "Invalid write log address";
+
+ write_log_entry_t e;
+ e.raw64 = write_iter->value;
+ EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type";
+ }
+
+ // Verify the backing store erase
+ {
+ index = 3;
+ auto write_iter = inst.log_begin() + index;
+ e.raw64 = write_iter->value;
+ EXPECT_TRUE(write_iter->erased) << "Backing store erase did not occur as required";
+ }
+
+ // Verify the backing store writes for consolidation
+ for (index = 4; index < 6; ++index) {
+ auto write_iter = inst.log_begin() + index;
+ EXPECT_EQ(write_iter->address, (index - 4) * BACKING_STORE_WRITE_SIZE) << "Invalid write log entry address";
+ }
+
+ // Verify the FNV1a_64 write
+ {
+ EXPECT_EQ((inst.log_begin() + 6)->address, WEAR_LEVELING_LOGICAL_SIZE) << "Invalid write log address";
+ e.raw64 = (inst.log_begin() + 6)->value;
+ EXPECT_EQ(e.raw64, fnv_64a_buf(testvalue.data(), testvalue.size(), FNV1A_64_INIT)) << "Invalid checksum"; // Note that checksum is based on testvalue, as we overwrote one byte and need to consult the consolidated data, not the current
+ }
+
+ // Verify the final write
+ EXPECT_EQ((inst.log_begin() + 7)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid write log address";
+
+ // Verify the data is what we expected
+ std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
+
+ // Re-init and re-read, verifying the reload capability
+ EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
+ EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
+ EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
+}
+
+/**
+ * This test verifies multibyte readback gets canceled with an out-of-bounds address.
+ */
+TEST_F(WearLeveling8Byte, PlaybackReadbackMultibyte_OOB) {
+ auto& inst = MockBackingStore::Instance();
+ auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
+
+ // Invalid FNV1a_64 hash
+ (logstart + 0)->set(0);
+
+ // Set up a 2-byte logical write of [0x11,0x12] at logical offset 0x01
+ auto entry0 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
+ entry0.raw8[3] = 0x11;
+ entry0.raw8[4] = 0x12;
+ (logstart + 1)->set(~entry0.raw64);
+
+ // Set up a 2-byte logical write of [0x13,0x14] at logical offset 0x1000 (out of bounds)
+ auto entry1 = LOG_ENTRY_MAKE_MULTIBYTE(0x1000, 2);
+ entry1.raw8[3] = 0x13;
+ entry1.raw8[4] = 0x14;
+ (logstart + 2)->set(~entry1.raw64);
+
+ // Set up a 2-byte logical write of [0x15,0x16] at logical offset 0x10
+ auto entry2 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
+ entry2.raw8[3] = 0x15;
+ entry2.raw8[4] = 0x16;
+ (logstart + 3)->set(~entry2.raw64);
+
+ EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
+ EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
+ EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
+
+ uint8_t buf[2];
+ wear_leveling_read(0x01, buf, sizeof(buf));
+ EXPECT_EQ(buf[0], 0x11) << "Readback should have maintained the previous pre-failure value from the write log";
+ EXPECT_EQ(buf[1], 0x12) << "Readback should have maintained the previous pre-failure value from the write log";
+}
diff --git a/quantum/wear_leveling/tests/wear_leveling_general.cpp b/quantum/wear_leveling/tests/wear_leveling_general.cpp
new file mode 100644
index 0000000000..76a4bf7bf3
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_general.cpp
@@ -0,0 +1,204 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <numeric>
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "backing_mocks.hpp"
+
+class WearLevelingGeneral : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ MockBackingStore::Instance().reset_instance();
+ wear_leveling_init();
+ }
+};
+
+/**
+ * This test verifies that even if there is consolidated data present, if the checksum doesn't match then the cache is zero'd after reading the consolidated area, but before write log is played back.
+ */
+TEST_F(WearLevelingGeneral, InvalidChecksum_ConsolidatedDataIgnored) {
+ auto& inst = MockBackingStore::Instance();
+ auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
+
+ // Generate a test block of data
+ std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> testvalue;
+ std::iota(testvalue.begin(), testvalue.end(), 0x20);
+
+ // Write the data
+ EXPECT_EQ(wear_leveling_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_CONSOLIDATED) << "Write returned incorrect status";
+
+ // Invalidate the checksum
+ (logstart + 0)->erase();
+ (logstart + 1)->erase();
+ (logstart + 2)->erase();
+ (logstart + 3)->erase();
+
+ // Set up a 1-byte logical write of [0x11] at logical offset 0x01
+ auto entry0 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x01, 0x11);
+ (logstart + 4)->set(~entry0.raw16[0]);
+
+ // Re-init
+ EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_SUCCESS) << "Init returned incorrect status";
+ EXPECT_EQ(wear_leveling_read(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_SUCCESS) << "Failed to read";
+ for (int i = 0; i < WEAR_LEVELING_LOGICAL_SIZE; ++i) {
+ EXPECT_EQ(testvalue[i], i == 0x01 ? 0x11 : 0x00) << "Invalid readback";
+ }
+}
+
+/**
+ * This test verifies that writing the same data multiple times does not result in subsequent writes to the backing store.
+ */
+TEST_F(WearLevelingGeneral, SameValue_SingleBackingWrite) {
+ auto& inst = MockBackingStore::Instance();
+
+ uint8_t test_val = 0x14;
+ EXPECT_EQ(wear_leveling_write(0x02, &test_val, sizeof(test_val)), WEAR_LEVELING_SUCCESS) << "First overall write operation should have succeeded";
+
+ uint64_t invoke_count = inst.unlock_invoke_count();
+ uint64_t erase_count = inst.erase_invoke_count();
+ uint64_t write_count = inst.write_invoke_count();
+ uint64_t lock_count = inst.lock_invoke_count();
+
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_EQ(wear_leveling_write(0x02, &test_val, sizeof(test_val)), WEAR_LEVELING_SUCCESS) << "Subsequent overall write operation should have succeeded";
+
+ EXPECT_EQ(inst.unlock_invoke_count(), invoke_count) << "Unlock count should match";
+ EXPECT_EQ(inst.erase_invoke_count(), erase_count) << "Erase count should match";
+ EXPECT_EQ(inst.write_invoke_count(), write_count) << "Write count should match";
+ EXPECT_EQ(inst.lock_invoke_count(), lock_count) << "Lock count should match";
+ }
+}
+
+/**
+ * This test verifies that no other invocations occur if `backing_store_init()` fails.
+ */
+TEST_F(WearLevelingGeneral, InitFailure) {
+ auto& inst = MockBackingStore::Instance();
+ inst.reset_instance(); // make sure the counters are all zero
+ inst.set_init_callback([](std::uint64_t count) { return false; });
+
+ EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
+ EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Init should have failed";
+ EXPECT_EQ(inst.erasure_count(), 0) << "Invalid final erase count";
+
+ EXPECT_EQ(inst.init_invoke_count(), 1) << "Init should have been invoked once";
+ EXPECT_EQ(inst.unlock_invoke_count(), 0) << "Unlock should not have been invoked";
+ EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
+ EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
+ EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
+}
+
+/**
+ * This test verifies that no invocations occur if the supplied address is out of range while writing.
+ */
+TEST_F(WearLevelingGeneral, WriteFailure_OOB) {
+ auto& inst = MockBackingStore::Instance();
+
+ uint8_t test_val = 0x14;
+ EXPECT_EQ(wear_leveling_write(0x21349830, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall write operation should have failed";
+
+ EXPECT_EQ(inst.unlock_invoke_count(), 0) << "Unlock should not have been invoked";
+ EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
+ EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
+ EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
+}
+
+/**
+ * This test verifies that a single write occurs if the supplied address and data length hits the edge of the logical area.
+ */
+TEST_F(WearLevelingGeneral, WriteSuccess_BoundaryOK) {
+ auto& inst = MockBackingStore::Instance();
+
+ uint16_t test_val = 0x14;
+ EXPECT_EQ(wear_leveling_write(WEAR_LEVELING_LOGICAL_SIZE - sizeof(test_val), &test_val, sizeof(test_val)), WEAR_LEVELING_SUCCESS) << "Overall write operation should have succeeded";
+
+ EXPECT_EQ(inst.unlock_invoke_count(), 1) << "Unlock should have been invoked once";
+ EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
+ EXPECT_EQ(inst.write_invoke_count(), 2) << "Write should have been invoked twice";
+ EXPECT_EQ(inst.lock_invoke_count(), 1) << "Lock should have been invoked once";
+}
+
+/**
+ * This test verifies that no invocations occur if the supplied address and length would generate writes outside the logical range.
+ */
+TEST_F(WearLevelingGeneral, WriteFailure_BoundaryOverflow) {
+ auto& inst = MockBackingStore::Instance();
+
+ uint16_t test_val = 0x14;
+ EXPECT_EQ(wear_leveling_write(WEAR_LEVELING_LOGICAL_SIZE - sizeof(test_val) + 1, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall write operation should have failed";
+
+ EXPECT_EQ(inst.unlock_invoke_count(), 0) << "Unlock should not have been invoked";
+ EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
+ EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
+ EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
+}
+
+/**
+ * This test verifies that no invocations occur if the supplied address is out of range while reading.
+ */
+TEST_F(WearLevelingGeneral, ReadFailure_OOB) {
+ auto& inst = MockBackingStore::Instance();
+
+ uint8_t test_val = 0;
+ EXPECT_EQ(wear_leveling_read(0x21349830, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall read operation should have failed";
+
+ EXPECT_EQ(inst.unlock_invoke_count(), 0) << "Unlock should not have been invoked";
+ EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
+ EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
+ EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
+}
+
+/**
+ * This test verifies that no write invocations occur if `backing_store_unlock()` fails.
+ */
+TEST_F(WearLevelingGeneral, UnlockFailure_NoWrite) {
+ auto& inst = MockBackingStore::Instance();
+ inst.set_unlock_callback([](std::uint64_t count) { return false; });
+
+ uint8_t test_val = 0x14;
+ EXPECT_EQ(wear_leveling_write(0x04, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall write operation should have failed";
+
+ EXPECT_EQ(inst.unlock_invoke_count(), 1) << "Unlock should have been invoked once";
+ EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
+ EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
+ EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
+
+ test_val = 0;
+ wear_leveling_read(0x04, &test_val, sizeof(test_val));
+ EXPECT_EQ(test_val, 0x14) << "Readback should come from cache regardless of unlock failure";
+}
+
+/**
+ * This test verifies that no erase invocations occur if `backing_store_unlock()` fails.
+ */
+TEST_F(WearLevelingGeneral, UnlockFailure_NoErase) {
+ auto& inst = MockBackingStore::Instance();
+ inst.set_unlock_callback([](std::uint64_t count) { return false; });
+
+ EXPECT_EQ(wear_leveling_erase(), WEAR_LEVELING_FAILED) << "Overall erase operation should have failed";
+
+ EXPECT_EQ(inst.unlock_invoke_count(), 1) << "Unlock should have been invoked once";
+ EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
+ EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
+ EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
+}
+
+/**
+ * This test verifies that only one write invocation occurs if `backing_store_write()` fails.
+ */
+TEST_F(WearLevelingGeneral, WriteFailure_NoSubsequentWrites) {
+ auto& inst = MockBackingStore::Instance();
+ inst.set_write_callback([](std::uint64_t count, std::uint32_t address) { return false; });
+
+ uint8_t test_val = 0x14;
+ EXPECT_EQ(wear_leveling_write(0x04, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall write operation should have failed";
+
+ EXPECT_EQ(inst.unlock_invoke_count(), 1) << "Unlock should have been invoked once";
+ EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
+ EXPECT_EQ(inst.write_invoke_count(), 1) << "Write should have been invoked once";
+ EXPECT_EQ(inst.lock_invoke_count(), 1) << "Lock should have been invoked once";
+
+ test_val = 0;
+ wear_leveling_read(0x04, &test_val, sizeof(test_val));
+ EXPECT_EQ(test_val, 0x14) << "Readback should come from cache regardless of unlock failure";
+}
diff --git a/quantum/wear_leveling/wear_leveling.c b/quantum/wear_leveling/wear_leveling.c
new file mode 100644
index 0000000000..429df45df5
--- /dev/null
+++ b/quantum/wear_leveling/wear_leveling.c
@@ -0,0 +1,768 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <stdbool.h>
+#include "fnv.h"
+#include "wear_leveling.h"
+#include "wear_leveling_internal.h"
+
+/*
+ This wear leveling algorithm is adapted from algorithms from previous
+ implementations in QMK, namely:
+ - Artur F. (http://engsta.com/stm32-flash-memory-eeprom-emulator/)
+ - Yiancar -- QMK's base implementation for STM32F303
+ - Ilya Zhuravlev -- initial wear leveling algorithm
+ - Don Kjer -- increased flash density algorithm
+ - Nick Brassel (@tzarc) -- decoupled for use on other peripherals
+
+ At this layer, it is assumed that any reads/writes from the backing store
+ have a "reset state" after erasure of zero.
+ It is up to the backing store to perform translation of values, such as
+ taking the complement in order to deal with flash memory's reset value.
+
+ Terminology:
+
+ - Backing store: this is the storage area used by the wear leveling
+ algorithm.
+
+ - Backing size: this is the amount of storage provided by the backing
+ store for use by the wear leveling algorithm.
+
+ - Backing write size: this is the minimum number of bytes the backing
+ store can write in a single operation.
+
+ - Logical data: this is the externally-visible "emulated EEPROM" that
+ external subsystems "see" when performing reads/writes.
+
+ - Logical size: this is the amount of storage available for use
+ externally. Effectively, the "size of the EEPROM".
+
+ - Write log: this is a section of the backing store used to keep track
+ of modifications without overwriting existing data. This log is
+ "played back" on startup such that any subsequent reads are capable
+ of returning the latest data.
+
+ - Consolidated data: this is a section of the backing store reserved for
+ use for the latest copy of logical data. This is only ever written
+ when the write log is full -- the latest values for the logical data
+ are written here and the write log is cleared.
+
+ Configurables:
+
+ - BACKING_STORE_WRITE_SIZE: The number of bytes requires for a write
+ operation. This is defined by the capabilities of the backing store.
+
+ - WEAR_LEVELING_BACKING_SIZE: The number of bytes provided by the
+ backing store for use by the wear leveling algorithm. This is
+ defined by the capabilities of the backing store. This value must
+ also be at least twice the size of the logical size, as well as a
+ multiple of the logical size.
+
+ - WEAR_LEVELING_LOGICAL_SIZE: The number of bytes externally visible
+ to other subsystems performing reads/writes. This must be a multiple
+ of the write size.
+
+ General algorithm:
+
+ During initialization:
+ * The contents of the consolidated data section are read into cache.
+ * The contents of the write log are "played back" and update the
+ cache accordingly.
+
+ During reads:
+ * Logical data is served from the cache.
+
+ During writes:
+ * The cache is updated with the new data.
+ * A new write log entry is appended to the log.
+ * If the log's full, data is consolidated and the write log cleared.
+
+ Write log structure:
+
+ The first 8 bytes of the write log are a FNV1a_64 hash of the contents
+ of the consolidated data area, in an attempt to detect and guard against
+ any data corruption.
+
+ The write log follows the hash:
+
+ Given that the algorithm needs to cater for 2-, 4-, and 8-byte writes,
+ a variable-length write log entry is used such that the minimal amount
+ of storage is used based off the backing store write size.
+
+ Firstly, an empty log entry is expected to be all zeros. If the backing
+ store uses 0xFF for cleared bytes, it should return the complement, such
+ that this wear-leveling algorithm "receives" zeros.
+
+ For multi-byte writes, up to 8 bytes will be used for each log entry,
+ depending on the size of backing store writes:
+
+ â•” Multi-byte Log Entry (2, 4-byte) â•â•—
+ â•‘00XXXYYYâ•‘YYYYYYYYâ•‘YYYYYYYYâ•‘AAAAAAAAâ•‘
+ ║ └┬┘└┬┘║└──┬───┘║└──┬───┘║└──┬───┘║
+ â•‘ LenAddâ•‘ Addressâ•‘ Addressâ•‘Value[0]â•‘
+ â•šâ•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•
+ â•” Multi-byte Log Entry (2-byte) â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•—
+ â•‘00XXXYYYâ•‘YYYYYYYYâ•‘YYYYYYYYâ•‘AAAAAAAAâ•‘BBBBBBBBâ•‘CCCCCCCCâ•‘
+ ║ └┬┘└┬┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║
+ â•‘ LenAddâ•‘ Addressâ•‘ Addressâ•‘Value[0]â•‘Value[1]â•‘Value[2]â•‘
+ â•šâ•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•
+ â•” Multi-byte Log Entry (2, 4, 8-byte) â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•—
+ â•‘00XXXYYYâ•‘YYYYYYYYâ•‘YYYYYYYYâ•‘AAAAAAAAâ•‘BBBBBBBBâ•‘CCCCCCCCâ•‘DDDDDDDDâ•‘EEEEEEEEâ•‘
+ ║ └┬┘└┬┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║
+ â•‘ LenAddâ•‘ Addressâ•‘ Addressâ•‘Value[0]â•‘Value[1]â•‘Value[2]â•‘Value[3]â•‘Value[4]â•‘
+ â•šâ•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•©â•â•â•â•â•â•â•â•â•
+
+ 19 bits are used for the address, which allows for a max logical size of
+ 512kB. Up to 5 bytes can be included in a single log entry.
+
+ For 2-byte backing store writes, the last two bytes are optional
+ depending on the length of data to be written. Accordingly, either 3
+ or 4 backing store write operations will occur.
+ For 4-byte backing store writes, either one or two write operations
+ occur, depending on the length.
+ For 8-byte backing store writes, one write operation occur.
+
+ 2-byte backing store optimizations:
+
+ For single byte writes, addresses between 0...63 are encoded in a single
+ backing store write operation. 4- and 8-byte backing stores do not have
+ this optimization as it does not minimize the number of bytes written.
+
+ â•” Byte-Entry â•â•â•â•â•—
+ â•‘01XXXXXXYYYYYYYYâ•‘
+ ║ └─┬──┘└──┬───┘║
+ â•‘ Address Value â•‘
+ â•šâ•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
+ 0 <= Address < 0x40 (64)
+
+ A second optimization takes into account uint16_t writes of 0 or 1,
+ specifically catering for KC_NO and KC_TRANSPARENT in the dynamic keymap
+ subsystem. This is valid only for the first 16kB of logical data --
+ addresses outside this range will use the multi-byte encoding above.
+
+ â•” U16-Encoded 0 â•â•—
+ â•‘100XXXXXXXXXXXXXâ•‘
+ ║ │└─────┬─────┘║
+ ║ │Address >> 1 ║
+ ║ └── Value: 0 ║
+ â•šâ•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
+ 0 <= Address <= 0x3FFE (16382)
+
+ â•” U16-Encoded 1 â•â•—
+ â•‘101XXXXXXXXXXXXXâ•‘
+ ║ │└─────┬─────┘║
+ ║ │Address >> 1 ║
+ ║ └── Value: 1 ║
+ â•šâ•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
+ 0 <= Address <= 0x3FFE (16382) */
+
+/**
+ * Storage area for the wear-leveling cache.
+ */
+static struct __attribute__((__aligned__(BACKING_STORE_WRITE_SIZE))) {
+ __attribute__((__aligned__(BACKING_STORE_WRITE_SIZE))) uint8_t cache[(WEAR_LEVELING_LOGICAL_SIZE)];
+ uint32_t write_address;
+ bool unlocked;
+} wear_leveling;
+
+/**
+ * Locking helper: status
+ */
+typedef enum backing_store_lock_status_t { STATUS_FAILURE = 0, STATUS_SUCCESS, STATUS_UNCHANGED } backing_store_lock_status_t;
+
+/**
+ * Locking helper: unlock
+ */
+static inline backing_store_lock_status_t wear_leveling_unlock(void) {
+ if (wear_leveling.unlocked) {
+ return STATUS_UNCHANGED;
+ }
+ if (!backing_store_unlock()) {
+ return STATUS_FAILURE;
+ }
+ wear_leveling.unlocked = true;
+ return STATUS_SUCCESS;
+}
+
+/**
+ * Locking helper: lock
+ */
+static inline backing_store_lock_status_t wear_leveling_lock(void) {
+ if (!wear_leveling.unlocked) {
+ return STATUS_UNCHANGED;
+ }
+ if (!backing_store_lock()) {
+ return STATUS_FAILURE;
+ }
+ wear_leveling.unlocked = false;
+ return STATUS_SUCCESS;
+}
+
+/**
+ * Resets the cache, ensuring the write address is correctly initialised.
+ */
+static void wear_leveling_clear_cache(void) {
+ memset(wear_leveling.cache, 0, (WEAR_LEVELING_LOGICAL_SIZE));
+ wear_leveling.write_address = (WEAR_LEVELING_LOGICAL_SIZE) + 8; // +8 is due to the FNV1a_64 of the consolidated buffer
+}
+
+/**
+ * Reads the consolidated data from the backing store into the cache.
+ * Does not consider the write log.
+ */
+static wear_leveling_status_t wear_leveling_read_consolidated(void) {
+ wl_dprintf("Reading consolidated data\n");
+
+ wear_leveling_status_t status = WEAR_LEVELING_SUCCESS;
+ if (!backing_store_read_bulk(0, (backing_store_int_t *)wear_leveling.cache, sizeof(wear_leveling.cache) / sizeof(backing_store_int_t))) {
+ wl_dprintf("Failed to read from backing store\n");
+ status = WEAR_LEVELING_FAILED;
+ }
+
+ // Verify the FNV1a_64 result
+ if (status != WEAR_LEVELING_FAILED) {
+ uint64_t expected = fnv_64a_buf(wear_leveling.cache, (WEAR_LEVELING_LOGICAL_SIZE), FNV1A_64_INIT);
+ write_log_entry_t entry;
+ wl_dprintf("Reading checksum\n");
+#if BACKING_STORE_WRITE_SIZE == 2
+ backing_store_read_bulk((WEAR_LEVELING_LOGICAL_SIZE), entry.raw16, 4);
+#elif BACKING_STORE_WRITE_SIZE == 4
+ backing_store_read_bulk((WEAR_LEVELING_LOGICAL_SIZE), entry.raw32, 2);
+#elif BACKING_STORE_WRITE_SIZE == 8
+ backing_store_read((WEAR_LEVELING_LOGICAL_SIZE) + 0, &entry.raw64);
+#endif
+ // If we have a mismatch, clear the cache but do not flag a failure,
+ // which will cater for the completely clean MCU case.
+ if (entry.raw64 == expected) {
+ wl_dprintf("Checksum matches, consolidated data is correct\n");
+ } else {
+ wl_dprintf("Checksum mismatch, clearing cache\n");
+ wear_leveling_clear_cache();
+ }
+ }
+
+ // If we failed for any reason, then clear the cache
+ if (status == WEAR_LEVELING_FAILED) {
+ wear_leveling_clear_cache();
+ }
+
+ return status;
+}
+
+/**
+ * Writes the current cache to consolidated data at the beginning of the backing store.
+ * Does not clear the write log.
+ * Pre-condition: this is just after an erase, so we can write directly without reading.
+ */
+static wear_leveling_status_t wear_leveling_write_consolidated(void) {
+ wl_dprintf("Writing consolidated data\n");
+
+ backing_store_lock_status_t lock_status = wear_leveling_unlock();
+ wear_leveling_status_t status = WEAR_LEVELING_CONSOLIDATED;
+ if (!backing_store_write_bulk(0, (backing_store_int_t *)wear_leveling.cache, sizeof(wear_leveling.cache) / sizeof(backing_store_int_t))) {
+ wl_dprintf("Failed to write to backing store\n");
+ status = WEAR_LEVELING_FAILED;
+ }
+
+ if (status != WEAR_LEVELING_FAILED) {
+ // Write out the FNV1a_64 result of the consolidated data
+ write_log_entry_t entry;
+ entry.raw64 = fnv_64a_buf(wear_leveling.cache, (WEAR_LEVELING_LOGICAL_SIZE), FNV1A_64_INIT);
+ wl_dprintf("Writing checksum\n");
+ do {
+#if BACKING_STORE_WRITE_SIZE == 2
+ if (!backing_store_write_bulk((WEAR_LEVELING_LOGICAL_SIZE), entry.raw16, 4)) {
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+#elif BACKING_STORE_WRITE_SIZE == 4
+ if (!backing_store_write_bulk((WEAR_LEVELING_LOGICAL_SIZE), entry.raw32, 2)) {
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+#elif BACKING_STORE_WRITE_SIZE == 8
+ if (!backing_store_write((WEAR_LEVELING_LOGICAL_SIZE), entry.raw64)) {
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+#endif
+ } while (0);
+ }
+
+ if (lock_status == STATUS_SUCCESS) {
+ wear_leveling_lock();
+ }
+ return status;
+}
+
+/**
+ * Forces a write of the current cache.
+ * Erases the backing store, including the write log.
+ * During this operation, there is the potential for data loss if a power loss occurs.
+ */
+static wear_leveling_status_t wear_leveling_consolidate_force(void) {
+ wl_dprintf("Erasing backing store\n");
+
+ // Erase the backing store. Expectation is that any un-written values that are read back after this call come back as zero.
+ bool ok = backing_store_erase();
+ if (!ok) {
+ wl_dprintf("Failed to erase backing store\n");
+ return WEAR_LEVELING_FAILED;
+ }
+
+ // Write the cache to the first section of the backing store.
+ wear_leveling_status_t status = wear_leveling_write_consolidated();
+ if (status == WEAR_LEVELING_FAILED) {
+ wl_dprintf("Failed to write consolidated data\n");
+ }
+
+ // Next write of the log occurs after the consolidated values at the start of the backing store.
+ wear_leveling.write_address = (WEAR_LEVELING_LOGICAL_SIZE) + 8; // +8 due to the FNV1a_64 of the consolidated area
+
+ return status;
+}
+
+/**
+ * Potential write of the current cache to the backing store.
+ * Skipped if the current write log position is not at the end of the backing store.
+ * During this operation, there is the potential for data loss if a power loss occurs.
+ *
+ * @return true if consolidation occurred
+ */
+static wear_leveling_status_t wear_leveling_consolidate_if_needed(void) {
+ if (wear_leveling.write_address >= (WEAR_LEVELING_BACKING_SIZE)) {
+ return wear_leveling_consolidate_force();
+ }
+
+ return WEAR_LEVELING_SUCCESS;
+}
+
+/**
+ * Appends the supplied fixed-width entry to the write log, optionally consolidating if the log is full.
+ *
+ * @return true if consolidation occurred
+ */
+static wear_leveling_status_t wear_leveling_append_raw(backing_store_int_t value) {
+ bool ok = backing_store_write(wear_leveling.write_address, value);
+ if (!ok) {
+ wl_dprintf("Failed to write to backing store\n");
+ return WEAR_LEVELING_FAILED;
+ }
+ wear_leveling.write_address += (BACKING_STORE_WRITE_SIZE);
+ return wear_leveling_consolidate_if_needed();
+}
+
+/**
+ * Handles writing multi_byte-encoded data to the backing store.
+ *
+ * @return true if consolidation occurred
+ */
+static wear_leveling_status_t wear_leveling_write_raw_multibyte(uint32_t address, const void *value, size_t length) {
+ const uint8_t * p = value;
+ write_log_entry_t log = LOG_ENTRY_MAKE_MULTIBYTE(address, length);
+ for (size_t i = 0; i < length; ++i) {
+ log.raw8[3 + i] = p[i];
+ }
+
+ // Write to the backing store. See the multi-byte log format in the documentation header at the top of the file.
+ wear_leveling_status_t status;
+#if BACKING_STORE_WRITE_SIZE == 2
+ status = wear_leveling_append_raw(log.raw16[0]);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ return status;
+ }
+
+ status = wear_leveling_append_raw(log.raw16[1]);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ return status;
+ }
+
+ if (length > 1) {
+ status = wear_leveling_append_raw(log.raw16[2]);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ return status;
+ }
+ }
+
+ if (length > 3) {
+ status = wear_leveling_append_raw(log.raw16[3]);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ return status;
+ }
+ }
+#elif BACKING_STORE_WRITE_SIZE == 4
+ status = wear_leveling_append_raw(log.raw32[0]);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ return status;
+ }
+
+ if (length > 1) {
+ status = wear_leveling_append_raw(log.raw32[1]);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ return status;
+ }
+ }
+#elif BACKING_STORE_WRITE_SIZE == 8
+ status = wear_leveling_append_raw(log.raw64);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ return status;
+ }
+#endif
+ return status;
+}
+
+/**
+ * Handles the actual writing of logical data into the write log section of the backing store.
+ */
+static wear_leveling_status_t wear_leveling_write_raw(uint32_t address, const void *value, size_t length) {
+ const uint8_t * p = value;
+ size_t remaining = length;
+ wear_leveling_status_t status = WEAR_LEVELING_SUCCESS;
+ while (remaining > 0) {
+#if BACKING_STORE_WRITE_SIZE == 2
+ // Small-write optimizations - uint16_t, 0 or 1, address is even, address <16384:
+ if (remaining >= 2 && address % 2 == 0 && address < 16384) {
+ const uint16_t v = ((uint16_t)p[1]) << 8 | p[0]; // don't just dereference a uint16_t here -- if unaligned it generates faults on some MCUs
+ if (v == 0 || v == 1) {
+ const write_log_entry_t log = LOG_ENTRY_MAKE_WORD_01(address, v);
+ status = wear_leveling_append_raw(log.raw16[0]);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ // If consolidation occurred, then the cache has already been written to the consolidated area. No need to continue.
+ // If a failure occurred, pass it on.
+ return status;
+ }
+
+ remaining -= 2;
+ address += 2;
+ p += 2;
+ continue;
+ }
+ }
+
+ // Small-write optimizations - address<64:
+ if (address < 64) {
+ const write_log_entry_t log = LOG_ENTRY_MAKE_OPTIMIZED_64(address, *p);
+ status = wear_leveling_append_raw(log.raw16[0]);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ // If consolidation occurred, then the cache has already been written to the consolidated area. No need to continue.
+ // If a failure occurred, pass it on.
+ return status;
+ }
+
+ remaining--;
+ address++;
+ p++;
+ continue;
+ }
+#endif // BACKING_STORE_WRITE_SIZE == 2
+ const size_t this_length = remaining >= LOG_ENTRY_MULTIBYTE_MAX_BYTES ? LOG_ENTRY_MULTIBYTE_MAX_BYTES : remaining;
+ status = wear_leveling_write_raw_multibyte(address, p, this_length);
+ if (status != WEAR_LEVELING_SUCCESS) {
+ // If consolidation occurred, then the cache has already been written to the consolidated area. No need to continue.
+ // If a failure occurred, pass it on.
+ return status;
+ }
+ remaining -= this_length;
+ address += (uint32_t)this_length;
+ p += this_length;
+ }
+
+ return status;
+}
+
+/**
+ * "Replays" the write log from the backing store, updating the local cache with updated values.
+ */
+static wear_leveling_status_t wear_leveling_playback_log(void) {
+ wl_dprintf("Playback write log\n");
+
+ wear_leveling_status_t status = WEAR_LEVELING_SUCCESS;
+ bool cancel_playback = false;
+ uint32_t address = (WEAR_LEVELING_LOGICAL_SIZE) + 8; // +8 due to the FNV1a_64 of the consolidated area
+ while (!cancel_playback && address < (WEAR_LEVELING_BACKING_SIZE)) {
+ backing_store_int_t value;
+ bool ok = backing_store_read(address, &value);
+ if (!ok) {
+ wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
+ cancel_playback = true;
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+ if (value == 0) {
+ wl_dprintf("Found empty slot, no more log entries\n");
+ cancel_playback = true;
+ break;
+ }
+
+ // If we got a nonzero value, then we need to increment the address to ensure next write occurs at next location
+ address += (BACKING_STORE_WRITE_SIZE);
+
+ // Read from the write log
+ write_log_entry_t log;
+#if BACKING_STORE_WRITE_SIZE == 2
+ log.raw16[0] = value;
+#elif BACKING_STORE_WRITE_SIZE == 4
+ log.raw32[0] = value;
+#elif BACKING_STORE_WRITE_SIZE == 8
+ log.raw64 = value;
+#endif
+
+ switch (LOG_ENTRY_GET_TYPE(log)) {
+ case LOG_ENTRY_TYPE_MULTIBYTE: {
+#if BACKING_STORE_WRITE_SIZE == 2
+ ok = backing_store_read(address, &log.raw16[1]);
+ if (!ok) {
+ wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
+ cancel_playback = true;
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+ address += (BACKING_STORE_WRITE_SIZE);
+#endif // BACKING_STORE_WRITE_SIZE == 2
+ const uint32_t a = LOG_ENTRY_MULTIBYTE_GET_ADDRESS(log);
+ const uint8_t l = LOG_ENTRY_MULTIBYTE_GET_LENGTH(log);
+
+ if (a + l > (WEAR_LEVELING_LOGICAL_SIZE)) {
+ cancel_playback = true;
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+
+#if BACKING_STORE_WRITE_SIZE == 2
+ if (l > 1) {
+ ok = backing_store_read(address, &log.raw16[2]);
+ if (!ok) {
+ wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
+ cancel_playback = true;
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+ address += (BACKING_STORE_WRITE_SIZE);
+ }
+ if (l > 3) {
+ ok = backing_store_read(address, &log.raw16[3]);
+ if (!ok) {
+ wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
+ cancel_playback = true;
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+ address += (BACKING_STORE_WRITE_SIZE);
+ }
+#elif BACKING_STORE_WRITE_SIZE == 4
+ if (l > 1) {
+ ok = backing_store_read(address, &log.raw32[1]);
+ if (!ok) {
+ wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
+ cancel_playback = true;
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+ address += (BACKING_STORE_WRITE_SIZE);
+ }
+#endif
+
+ memcpy(&wear_leveling.cache[a], &log.raw8[3], l);
+ } break;
+#if BACKING_STORE_WRITE_SIZE == 2
+ case LOG_ENTRY_TYPE_OPTIMIZED_64: {
+ const uint32_t a = LOG_ENTRY_OPTIMIZED_64_GET_ADDRESS(log);
+ const uint8_t v = LOG_ENTRY_OPTIMIZED_64_GET_VALUE(log);
+
+ if (a >= (WEAR_LEVELING_LOGICAL_SIZE)) {
+ cancel_playback = true;
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+
+ wear_leveling.cache[a] = v;
+ } break;
+ case LOG_ENTRY_TYPE_WORD_01: {
+ const uint32_t a = LOG_ENTRY_WORD_01_GET_ADDRESS(log);
+ const uint8_t v = LOG_ENTRY_WORD_01_GET_VALUE(log);
+
+ if (a + 1 >= (WEAR_LEVELING_LOGICAL_SIZE)) {
+ cancel_playback = true;
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+
+ wear_leveling.cache[a + 0] = v;
+ wear_leveling.cache[a + 1] = 0;
+ } break;
+#endif // BACKING_STORE_WRITE_SIZE == 2
+ default: {
+ cancel_playback = true;
+ status = WEAR_LEVELING_FAILED;
+ } break;
+ }
+ }
+
+ // We've reached the end of the log, so we're at the new write location
+ wear_leveling.write_address = address;
+
+ if (status == WEAR_LEVELING_FAILED) {
+ // If we had a failure during readback, assume we're corrupted -- force a consolidation with the data we already have
+ status = wear_leveling_consolidate_force();
+ } else {
+ // Consolidate the cache + write log if required
+ status = wear_leveling_consolidate_if_needed();
+ }
+
+ return status;
+}
+
+/**
+ * Wear-leveling initialization
+ */
+wear_leveling_status_t wear_leveling_init(void) {
+ wl_dprintf("Init\n");
+
+ // Reset the cache
+ wear_leveling_clear_cache();
+
+ // Initialise the backing store
+ if (!backing_store_init()) {
+ // If it failed, clear the cache and return with failure
+ wear_leveling_clear_cache();
+ return WEAR_LEVELING_FAILED;
+ }
+
+ // Read the previous consolidated values, then replay the existing write log so that the cache has the "live" values
+ wear_leveling_status_t status = wear_leveling_read_consolidated();
+ if (status == WEAR_LEVELING_FAILED) {
+ // If it failed, clear the cache and return with failure
+ wear_leveling_clear_cache();
+ return status;
+ }
+
+ status = wear_leveling_playback_log();
+ if (status == WEAR_LEVELING_FAILED) {
+ // If it failed, clear the cache and return with failure
+ wear_leveling_clear_cache();
+ return status;
+ }
+
+ return status;
+}
+
+/**
+ * Wear-leveling erase.
+ * Post-condition: any reads from the backing store directly after an erase operation must come back as zero.
+ */
+wear_leveling_status_t wear_leveling_erase(void) {
+ wl_dprintf("Erase\n");
+
+ // Unlock the backing store
+ backing_store_lock_status_t lock_status = wear_leveling_unlock();
+ if (lock_status == STATUS_FAILURE) {
+ wear_leveling_lock();
+ return WEAR_LEVELING_FAILED;
+ }
+
+ // Perform the erase
+ bool ret = backing_store_erase();
+ wear_leveling_clear_cache();
+
+ // Lock the backing store if we acquired the lock successfully
+ if (lock_status == STATUS_SUCCESS) {
+ ret &= (wear_leveling_lock() != STATUS_FAILURE);
+ }
+
+ return ret ? WEAR_LEVELING_SUCCESS : WEAR_LEVELING_FAILED;
+}
+
+/**
+ * Writes logical data into the backing store. Skips writes if there are no changes to values.
+ */
+wear_leveling_status_t wear_leveling_write(const uint32_t address, const void *value, size_t length) {
+ wl_assert(address + length <= (WEAR_LEVELING_LOGICAL_SIZE));
+ if (address + length > (WEAR_LEVELING_LOGICAL_SIZE)) {
+ return WEAR_LEVELING_FAILED;
+ }
+
+ wl_dprintf("Write ");
+ wl_dump(address, value, length);
+
+ // Skip write if there's no change compared to the current cached value
+ if (memcmp(value, &wear_leveling.cache[address], length) == 0) {
+ return true;
+ }
+
+ // Update the cache before writing to the backing store -- if we hit the end of the backing store during writes to the log then we'll force a consolidation in-line
+ memcpy(&wear_leveling.cache[address], value, length);
+
+ // Unlock the backing store
+ backing_store_lock_status_t lock_status = wear_leveling_unlock();
+ if (lock_status == STATUS_FAILURE) {
+ wear_leveling_lock();
+ return WEAR_LEVELING_FAILED;
+ }
+
+ // Perform the actual write
+ wear_leveling_status_t status = wear_leveling_write_raw(address, value, length);
+ switch (status) {
+ case WEAR_LEVELING_CONSOLIDATED:
+ case WEAR_LEVELING_FAILED:
+ // If the write triggered consolidation, or the write failed, then nothing else needs to occur.
+ break;
+
+ case WEAR_LEVELING_SUCCESS:
+ // Consolidate the cache + write log if required
+ status = wear_leveling_consolidate_if_needed();
+ break;
+
+ default:
+ // Unsure how we'd get here...
+ status = WEAR_LEVELING_FAILED;
+ break;
+ }
+
+ if (lock_status == STATUS_SUCCESS) {
+ if (wear_leveling_lock() == STATUS_FAILURE) {
+ status = WEAR_LEVELING_FAILED;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * Reads logical data from the cache.
+ */
+wear_leveling_status_t wear_leveling_read(const uint32_t address, void *value, size_t length) {
+ wl_assert(address + length <= (WEAR_LEVELING_LOGICAL_SIZE));
+ if (address + length > (WEAR_LEVELING_LOGICAL_SIZE)) {
+ return WEAR_LEVELING_FAILED;
+ }
+
+ // Only need to copy from the cache
+ memcpy(value, &wear_leveling.cache[address], length);
+
+ wl_dprintf("Read ");
+ wl_dump(address, value, length);
+ return WEAR_LEVELING_SUCCESS;
+}
+
+/**
+ * Weak implementation of bulk read, drivers can implement more optimised implementations.
+ */
+__attribute__((weak)) bool backing_store_read_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
+ for (size_t i = 0; i < item_count; ++i) {
+ if (!backing_store_read(address + (i * BACKING_STORE_WRITE_SIZE), &values[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * Weak implementation of bulk write, drivers can implement more optimised implementations.
+ */
+__attribute__((weak)) bool backing_store_write_bulk(uint32_t address, backing_store_int_t *values, size_t item_count) {
+ for (size_t i = 0; i < item_count; ++i) {
+ if (!backing_store_write(address + (i * BACKING_STORE_WRITE_SIZE), values[i])) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/quantum/wear_leveling/wear_leveling.h b/quantum/wear_leveling/wear_leveling.h
new file mode 100644
index 0000000000..6641bc49b3
--- /dev/null
+++ b/quantum/wear_leveling/wear_leveling.h
@@ -0,0 +1,54 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+#include <stdint.h>
+#include <stdlib.h>
+
+/**
+ * @typedef Status returned from any wear-leveling API.
+ */
+typedef enum wear_leveling_status_t {
+ WEAR_LEVELING_FAILED, //< Invocation failed
+ WEAR_LEVELING_SUCCESS, //< Invocation succeeded
+ WEAR_LEVELING_CONSOLIDATED //< Invocation succeeded, consolidation occurred
+} wear_leveling_status_t;
+
+/**
+ * Wear-leveling initialization
+ *
+ * @return Status of the request
+ */
+wear_leveling_status_t wear_leveling_init(void);
+
+/**
+ * Wear-leveling erasure.
+ *
+ * Clears the wear-leveling area, with the definition that the "reset state" of all data is zero.
+ *
+ * @return Status of the request
+ */
+wear_leveling_status_t wear_leveling_erase(void);
+
+/**
+ * Writes logical data into the backing store.
+ *
+ * Skips writes if there are no changes to written values. The entire written block is considered when attempting to
+ * determine if an overwrite should occur -- if there is any data mismatch the entire block will be written to the log,
+ * not just the changed bytes.
+ *
+ * @param address[in] the logical address to write data
+ * @param value[in] pointer to the source buffer
+ * @param length[in] length of the data
+ * @return Status of the request
+ */
+wear_leveling_status_t wear_leveling_write(uint32_t address, const void* value, size_t length);
+
+/**
+ * Reads logical data from the cache.
+ *
+ * @param address[in] the logical address to read data
+ * @param value[out] pointer to the destination buffer
+ * @param length[in] length of the data
+ * @return Status of the request
+ */
+wear_leveling_status_t wear_leveling_read(uint32_t address, void* value, size_t length);
diff --git a/quantum/wear_leveling/wear_leveling_internal.h b/quantum/wear_leveling/wear_leveling_internal.h
new file mode 100644
index 0000000000..e83f9b22ea
--- /dev/null
+++ b/quantum/wear_leveling/wear_leveling_internal.h
@@ -0,0 +1,151 @@
+// Copyright 2022 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+#pragma once
+
+#ifdef __cplusplus
+# define _Static_assert static_assert
+#endif
+
+#include <stdint.h>
+#include <string.h>
+
+#if BACKING_STORE_WRITE_SIZE == 2
+typedef uint16_t backing_store_int_t;
+#elif BACKING_STORE_WRITE_SIZE == 4
+typedef uint32_t backing_store_int_t;
+#elif BACKING_STORE_WRITE_SIZE == 8
+typedef uint64_t backing_store_int_t;
+#else
+# error Invalid BACKING_STORE_WRITE_SIZE, needs to be 2/4/8.
+#endif
+
+#ifndef WEAR_LEVELING_BACKING_SIZE
+# error WEAR_LEVELING_BACKING_SIZE was not set.
+#endif
+
+#ifndef WEAR_LEVELING_LOGICAL_SIZE
+# error WEAR_LEVELING_LOGICAL_SIZE was not set.
+#endif
+
+#ifdef WEAR_LEVELING_DEBUG_OUTPUT
+# include <debug.h>
+# define bs_dprintf(...) dprintf("Backing store: " __VA_ARGS__)
+# define wl_dprintf(...) dprintf("Wear leveling: " __VA_ARGS__)
+# define wl_dump(address, value, length) \
+ do { \
+ dprintf("[0x%04X]: ", (int)(address)); \
+ const uint8_t* p = (const uint8_t*)(value); \
+ for (int i = 0; i < (length); ++i) { \
+ dprintf(" %02X", (int)p[i]); \
+ } \
+ dprintf("\n"); \
+ } while (0)
+#else
+# define wl_dprintf(...) \
+ do { \
+ } while (0)
+# define bs_dprintf(...) \
+ do { \
+ } while (0)
+# define wl_dump(...) \
+ do { \
+ } while (0)
+#endif // WEAR_LEVELING_DEBUG_OUTPUT
+
+#ifdef WEAR_LEVELING_ASSERTS
+# include <assert.h>
+# define wl_assert(...) assert(__VA_ARGS__)
+#else
+# define wl_assert(...) \
+ do { \
+ } while (0)
+#endif // WEAR_LEVELING_ASSERTS
+
+// Compile-time validation of configurable options
+_Static_assert(WEAR_LEVELING_BACKING_SIZE >= (WEAR_LEVELING_LOGICAL_SIZE * 2), "Total backing size must be at least twice the size of the logical size");
+_Static_assert(WEAR_LEVELING_LOGICAL_SIZE % BACKING_STORE_WRITE_SIZE == 0, "Logical size must be a multiple of write size");
+_Static_assert(WEAR_LEVELING_BACKING_SIZE % WEAR_LEVELING_LOGICAL_SIZE == 0, "Backing size must be a multiple of logical size");
+
+// Backing Store API, to be implemented elsewhere by flash driver etc.
+bool backing_store_init(void);
+bool backing_store_unlock(void);
+bool backing_store_erase(void);
+bool backing_store_write(uint32_t address, backing_store_int_t value);
+bool backing_store_write_bulk(uint32_t address, backing_store_int_t* values, size_t item_count); // weak implementation already provided, optimized implementation can be implemented by driver
+bool backing_store_lock(void);
+bool backing_store_read(uint32_t address, backing_store_int_t* value);
+bool backing_store_read_bulk(uint32_t address, backing_store_int_t* values, size_t item_count); // weak implementation already provided, optimized implementation can be implemented by driver
+
+/**
+ * Helper type used to contain a write log entry.
+ */
+typedef union write_log_entry_t {
+ uint64_t raw64;
+ uint32_t raw32[2];
+ uint16_t raw16[4];
+ uint8_t raw8[8];
+} write_log_entry_t;
+
+_Static_assert(sizeof(write_log_entry_t) == 8, "Wear leveling write log entry size was not 8");
+
+/**
+ * Log entry type discriminator.
+ */
+enum {
+ // 0x00 -- Multi-byte storage type
+ LOG_ENTRY_TYPE_MULTIBYTE,
+
+ // 0x01 -- 2-byte backing store write optimization: address < 64
+ LOG_ENTRY_TYPE_OPTIMIZED_64,
+
+ // 0x02 -- 2-byte backing store write optimization: word-encoded 0/1 values
+ LOG_ENTRY_TYPE_WORD_01,
+
+ LOG_ENTRY_TYPES
+};
+
+_Static_assert(LOG_ENTRY_TYPES <= (1 << 2), "Too many log entry types to fit into 2 bits of storage");
+
+#define BITMASK_FOR_BITCOUNT(n) ((1 << (n)) - 1)
+
+#define LOG_ENTRY_GET_TYPE(entry) (((entry).raw8[0] >> 6) & BITMASK_FOR_BITCOUNT(2))
+
+#define LOG_ENTRY_MULTIBYTE_MAX_BYTES 5
+#define LOG_ENTRY_MULTIBYTE_GET_ADDRESS(entry) (((((uint32_t)((entry).raw8[0])) & BITMASK_FOR_BITCOUNT(3)) << 16) | (((uint32_t)((entry).raw8[1])) << 8) | (entry).raw8[2])
+#define LOG_ENTRY_MULTIBYTE_GET_LENGTH(entry) ((uint8_t)(((entry).raw8[0] >> 3) & BITMASK_FOR_BITCOUNT(3)))
+#define LOG_ENTRY_MAKE_MULTIBYTE(address, length) \
+ (write_log_entry_t) { \
+ .raw8 = { \
+ [0] = (((((uint8_t)LOG_ENTRY_TYPE_MULTIBYTE) & BITMASK_FOR_BITCOUNT(2)) << 6) /* type */ \
+ | ((((uint8_t)(length)) & BITMASK_FOR_BITCOUNT(3)) << 3) /* length */ \
+ | ((((uint8_t)((address) >> 16))) & BITMASK_FOR_BITCOUNT(3)) /* address */ \
+ ), \
+ [1] = (((uint8_t)((address) >> 8)) & BITMASK_FOR_BITCOUNT(8)), /* address */ \
+ [2] = (((uint8_t)(address)) & BITMASK_FOR_BITCOUNT(8)), /* address */ \
+ } \
+ }
+
+#define LOG_ENTRY_OPTIMIZED_64_GET_ADDRESS(entry) ((uint32_t)((entry).raw8[0] & BITMASK_FOR_BITCOUNT(6)))
+#define LOG_ENTRY_OPTIMIZED_64_GET_VALUE(entry) ((entry).raw8[1])
+#define LOG_ENTRY_MAKE_OPTIMIZED_64(address, value) \
+ (write_log_entry_t) { \
+ .raw8 = { \
+ [0] = (((((uint8_t)LOG_ENTRY_TYPE_OPTIMIZED_64) & BITMASK_FOR_BITCOUNT(2)) << 6) /* type */ \
+ | ((((uint8_t)(address))) & BITMASK_FOR_BITCOUNT(6)) /* address */ \
+ ), \
+ [1] = ((uint8_t)(value)), /* value */ \
+ } \
+ }
+
+#define LOG_ENTRY_WORD_01_GET_ADDRESS(entry) ((((uint32_t)(((entry).raw8[0]) & BITMASK_FOR_BITCOUNT(5))) << 9) | (((uint32_t)((entry).raw8[1])) << 1))
+#define LOG_ENTRY_WORD_01_GET_VALUE(entry) ((uint8_t)((entry).raw8[0] >> 5) & BITMASK_FOR_BITCOUNT(1))
+#define LOG_ENTRY_MAKE_WORD_01(address, value) \
+ (write_log_entry_t) { \
+ .raw8 = { \
+ [0] = (((((uint8_t)LOG_ENTRY_TYPE_WORD_01) & BITMASK_FOR_BITCOUNT(2)) << 6) /* type */ \
+ | (((((uint8_t)((value) ? 1 : 0))) & BITMASK_FOR_BITCOUNT(1)) << 5) /* value */ \
+ | ((((uint8_t)((address) >> 9))) & BITMASK_FOR_BITCOUNT(5)) /* address */ \
+ ), \
+ [1] = (uint8_t)((address) >> 1), /* address */ \
+ } \
+ }
diff --git a/readme.md b/readme.md
index 5649ddfa09..63b483c744 100644
--- a/readme.md
+++ b/readme.md
@@ -1,3 +1,7 @@
+# This is the `develop` branch!
+
+See the [Breaking Changes](https://docs.qmk.fm/#/breaking_changes) document for more information.
+
# Quantum Mechanical Keyboard Firmware
[![Current Version](https://img.shields.io/github/tag/qmk/qmk_firmware.svg)](https://github.com/qmk/qmk_firmware/tags)
diff --git a/quantum/process_keycode/process_terminal_nop.h b/tests/tap_dance/config.h
index 36e25320c5..6aada3efd3 100644
--- a/quantum/process_keycode/process_terminal_nop.h
+++ b/tests/tap_dance/config.h
@@ -1,4 +1,4 @@
-/* Copyright 2017 Jack Humbert
+/* Copyright 2022 Jouke Witteveen
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,7 +16,4 @@
#pragma once
-#include "quantum.h"
-
-#define TERM_ON KC_NO
-#define TERM_OFF KC_NO
+#include "test_common.h"
diff --git a/tests/tap_dance/examples.c b/tests/tap_dance/examples.c
new file mode 100644
index 0000000000..4a5be41b08
--- /dev/null
+++ b/tests/tap_dance/examples.c
@@ -0,0 +1,199 @@
+/* Copyright 2022 Jouke Witteveen
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "quantum.h"
+#include "examples.h"
+
+// Example code from the tap dance documentation, adapted for testing
+
+// clang-format off
+
+// Example 1
+
+void dance_egg(qk_tap_dance_state_t *state, void *user_data) {
+ if (state->count >= 100) {
+ // SEND_STRING("Safety dance!");
+ tap_code(KC_C);
+ reset_tap_dance(state);
+ }
+}
+
+
+// Example 2
+
+void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) {
+ switch (state->count) {
+ case 1:
+ register_code(KC_3);
+ break;
+ case 2:
+ register_code(KC_2);
+ break;
+ case 3:
+ register_code(KC_1);
+ break;
+ case 4:
+ unregister_code(KC_3);
+ // wait_ms(50);
+ unregister_code(KC_2);
+ // wait_ms(50);
+ unregister_code(KC_1);
+ }
+}
+
+void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) {
+ if (state->count >= 4) {
+ // reset_keyboard();
+ tap_code(KC_R);
+ }
+}
+
+void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
+ unregister_code(KC_1);
+ // wait_ms(50);
+ unregister_code(KC_2);
+ // wait_ms(50);
+ unregister_code(KC_3);
+}
+
+
+// Example 3
+
+typedef struct {
+ uint16_t tap;
+ uint16_t hold;
+ uint16_t held;
+} tap_dance_tap_hold_t;
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ qk_tap_dance_action_t *action;
+
+ switch (keycode) {
+ case TD(CT_CLN):
+ action = &tap_dance_actions[TD_INDEX(keycode)];
+ if (!record->event.pressed && action->state.count && !action->state.finished) {
+ tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
+ tap_code16(tap_hold->tap);
+ }
+ }
+ return true;
+}
+
+void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) {
+ tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
+
+ if (state->pressed) {
+ if (state->count == 1
+#ifndef PERMISSIVE_HOLD
+ && !state->interrupted
+#endif
+ ) {
+ register_code16(tap_hold->hold);
+ tap_hold->held = tap_hold->hold;
+ } else {
+ register_code16(tap_hold->tap);
+ tap_hold->held = tap_hold->tap;
+ }
+ }
+}
+
+void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) {
+ tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
+
+ if (tap_hold->held) {
+ unregister_code16(tap_hold->held);
+ tap_hold->held = 0;
+ }
+}
+
+#define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \
+ { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), }
+
+
+// Example 4
+
+typedef enum {
+ TD_NONE,
+ TD_UNKNOWN,
+ TD_SINGLE_TAP,
+ TD_SINGLE_HOLD,
+ TD_DOUBLE_TAP,
+ TD_DOUBLE_HOLD,
+ TD_DOUBLE_SINGLE_TAP,
+ TD_TRIPLE_TAP,
+ TD_TRIPLE_HOLD
+} td_state_t;
+
+typedef struct {
+ bool is_press_action;
+ td_state_t state;
+} td_tap_t;
+
+td_state_t cur_dance(qk_tap_dance_state_t *state) {
+ if (state->count == 1) {
+ if (state->interrupted || !state->pressed) return TD_SINGLE_TAP;
+ else return TD_SINGLE_HOLD;
+ } else if (state->count == 2) {
+ if (state->interrupted) return TD_DOUBLE_SINGLE_TAP;
+ else if (state->pressed) return TD_DOUBLE_HOLD;
+ else return TD_DOUBLE_TAP;
+ }
+
+ if (state->count == 3) {
+ if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP;
+ else return TD_TRIPLE_HOLD;
+ } else return TD_UNKNOWN;
+}
+
+static td_tap_t xtap_state = {
+ .is_press_action = true,
+ .state = TD_NONE
+};
+
+void x_finished(qk_tap_dance_state_t *state, void *user_data) {
+ xtap_state.state = cur_dance(state);
+ switch (xtap_state.state) {
+ case TD_SINGLE_TAP: register_code(KC_X); break;
+ case TD_SINGLE_HOLD: register_code(KC_LCTL); break;
+ case TD_DOUBLE_TAP: register_code(KC_ESC); break;
+ case TD_DOUBLE_HOLD: register_code(KC_LALT); break;
+ case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X);
+ default: break; // Not present in documentation
+ }
+}
+
+void x_reset(qk_tap_dance_state_t *state, void *user_data) {
+ switch (xtap_state.state) {
+ case TD_SINGLE_TAP: unregister_code(KC_X); break;
+ case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break;
+ case TD_DOUBLE_TAP: unregister_code(KC_ESC); break;
+ case TD_DOUBLE_HOLD: unregister_code(KC_LALT);
+ case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X);
+ default: break; // Not present in documentation
+ }
+ xtap_state.state = TD_NONE;
+}
+
+
+qk_tap_dance_action_t tap_dance_actions[] = {
+ [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
+ [CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg),
+ [CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset),
+ [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN),
+ [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset)
+};
+
+// clang-format on
diff --git a/quantum/process_keycode/process_terminal.h b/tests/tap_dance/examples.h
index 0159131e5b..2622af6b2f 100644
--- a/quantum/process_keycode/process_terminal.h
+++ b/tests/tap_dance/examples.h
@@ -1,4 +1,4 @@
-/* Copyright 2017 Jack Humbert
+/* Copyright 2022 Jouke Witteveen
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,9 +16,18 @@
#pragma once
-#include "quantum.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
-extern const char keycode_to_ascii_lut[58];
-extern const char shifted_keycode_to_ascii_lut[58];
-extern const char terminal_prompt[8];
-bool process_terminal(uint16_t keycode, keyrecord_t *record);
+enum {
+ TD_ESC_CAPS,
+ CT_EGG,
+ CT_FLSH,
+ CT_CLN,
+ X_CTL,
+};
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tests/tap_dance/test.mk b/tests/tap_dance/test.mk
new file mode 100644
index 0000000000..041d9b4dc9
--- /dev/null
+++ b/tests/tap_dance/test.mk
@@ -0,0 +1,22 @@
+# Copyright 2022 Jouke Witteveen
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+TAP_DANCE_ENABLE = yes
+
+SRC += examples.c
diff --git a/tests/tap_dance/test_examples.cpp b/tests/tap_dance/test_examples.cpp
new file mode 100644
index 0000000000..e67e6cb907
--- /dev/null
+++ b/tests/tap_dance/test_examples.cpp
@@ -0,0 +1,319 @@
+/* Copyright 2022 Jouke Witteveen
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "action_tapping.h"
+#include "test_keymap_key.hpp"
+#include "examples.h"
+
+using testing::_;
+using testing::InSequence;
+
+class TapDance : public TestFixture {};
+
+TEST_F(TapDance, DoubleTap) {
+ TestDriver driver;
+ InSequence s;
+ auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)};
+
+ set_keymap({key_esc_caps});
+
+ /* The tap dance key does nothing on the first press */
+ key_esc_caps.press();
+ run_one_scan_loop();
+ key_esc_caps.release();
+ EXPECT_NO_REPORT(driver);
+
+ /* We get the key press and the release on timeout */
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_ESC));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double tap gets us the second key */
+ tap_key(key_esc_caps);
+ EXPECT_NO_REPORT(driver);
+ key_esc_caps.press();
+ EXPECT_REPORT(driver, (KC_CAPS));
+ run_one_scan_loop();
+ key_esc_caps.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, DoubleTapWithMod) {
+ TestDriver driver;
+ InSequence s;
+ auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)};
+ auto key_shift = KeymapKey{0, 2, 0, KC_LSFT};
+
+ set_keymap({key_esc_caps, key_shift});
+
+ /* The tap dance key does nothing on the first press */
+ key_shift.press();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ run_one_scan_loop();
+ key_esc_caps.press();
+ run_one_scan_loop();
+
+ key_esc_caps.release();
+ key_shift.release();
+ EXPECT_EMPTY_REPORT(driver);
+
+ /* We get the key press and the release */
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_ESC));
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double tap gets us the second key */
+ key_shift.press();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ run_one_scan_loop();
+ tap_key(key_esc_caps);
+ EXPECT_NO_REPORT(driver);
+ key_shift.release();
+ key_esc_caps.press();
+ EXPECT_REPORT(driver, (KC_LSFT, KC_CAPS));
+ run_one_scan_loop();
+ key_esc_caps.release();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ run_one_scan_loop();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, DoubleTapInterrupted) {
+ TestDriver driver;
+ InSequence s;
+ auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)};
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({key_esc_caps, regular_key});
+
+ /* Interrupted double tap */
+ tap_key(key_esc_caps);
+ regular_key.press();
+ /* Immediate tap of the first key */
+ EXPECT_REPORT(driver, (KC_ESC));
+ EXPECT_EMPTY_REPORT(driver);
+ /* Followed by the interrupting key */
+ EXPECT_REPORT(driver, (KC_A));
+ run_one_scan_loop();
+ regular_key.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Second tap after being interrupted acts as a single tap */
+ key_esc_caps.press();
+ run_one_scan_loop();
+ key_esc_caps.release();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_ESC));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, DanceFn) {
+ TestDriver driver;
+ InSequence s;
+ auto key_egg = KeymapKey(0, 1, 0, TD(CT_EGG));
+
+ set_keymap({key_egg});
+
+ /* 99 taps do nothing */
+ for (int i = 0; i < 99; i++) {
+ run_one_scan_loop();
+ key_egg.press();
+ run_one_scan_loop();
+ key_egg.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_NO_REPORT(driver);
+ run_one_scan_loop();
+
+ /* 100 taps trigger the action */
+ for (int i = 0; i < 100; i++) {
+ run_one_scan_loop();
+ key_egg.press();
+ run_one_scan_loop();
+ key_egg.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_C));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* 250 taps act the same as 100 taps */
+ /* Taps are counted in an uint8_t, so the count overflows after 255 taps */
+ for (int i = 0; i < 250; i++) {
+ run_one_scan_loop();
+ key_egg.press();
+ run_one_scan_loop();
+ key_egg.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_C));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, DanceFnAdvanced) {
+ TestDriver driver;
+ InSequence s;
+ auto key_flsh = KeymapKey(0, 1, 0, TD(CT_FLSH));
+
+ set_keymap({key_flsh});
+
+ /* Three taps don't trigger a reset */
+ EXPECT_REPORT(driver, (KC_3));
+ EXPECT_REPORT(driver, (KC_3, KC_2));
+ EXPECT_REPORT(driver, (KC_3, KC_2, KC_1));
+ for (int i = 0; i < 3; i++) {
+ run_one_scan_loop();
+ key_flsh.press();
+ run_one_scan_loop();
+ key_flsh.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_3, KC_2));
+ EXPECT_REPORT(driver, (KC_3));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Four taps trigger a reset */
+ EXPECT_REPORT(driver, (KC_3));
+ EXPECT_REPORT(driver, (KC_3, KC_2));
+ EXPECT_REPORT(driver, (KC_3, KC_2, KC_1));
+ EXPECT_REPORT(driver, (KC_2, KC_1));
+ EXPECT_REPORT(driver, (KC_1));
+ EXPECT_EMPTY_REPORT(driver);
+ for (int i = 0; i < 4; i++) {
+ run_one_scan_loop();
+ key_flsh.press();
+ run_one_scan_loop();
+ key_flsh.release();
+ }
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_R));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, TapHold) {
+ TestDriver driver;
+ InSequence s;
+ auto key_cln = KeymapKey{0, 1, 0, TD(CT_CLN)};
+
+ set_keymap({key_cln});
+
+ /* Short taps fire on release */
+ key_cln.press();
+ run_one_scan_loop();
+ key_cln.release();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN));
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Holds immediate following a tap apply to the tap key */
+ key_cln.press();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN));
+ idle_for(TAPPING_TERM * 2);
+ key_cln.release();
+ EXPECT_REPORT(driver, (KC_LSFT));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Holds trigger the hold key */
+ key_cln.press();
+ idle_for(TAPPING_TERM);
+ run_one_scan_loop();
+ EXPECT_REPORT(driver, (KC_SCLN));
+ run_one_scan_loop();
+ key_cln.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
+
+TEST_F(TapDance, QuadFunction) {
+ TestDriver driver;
+ InSequence s;
+ auto key_quad = KeymapKey{0, 1, 0, TD(X_CTL)};
+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
+
+ set_keymap({key_quad, regular_key});
+
+ /* Single tap */
+ key_quad.press();
+ run_one_scan_loop();
+ key_quad.release();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_X));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Single hold */
+ key_quad.press();
+ run_one_scan_loop();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_LCTL));
+ run_one_scan_loop();
+ key_quad.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double tap */
+ tap_key(key_quad);
+ key_quad.press();
+ run_one_scan_loop();
+ key_quad.release();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_ESC));
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double tap and hold */
+ tap_key(key_quad);
+ key_quad.press();
+ run_one_scan_loop();
+ idle_for(TAPPING_TERM);
+ EXPECT_REPORT(driver, (KC_LALT));
+ run_one_scan_loop();
+ key_quad.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+
+ /* Double single tap */
+ tap_key(key_quad);
+ tap_key(key_quad);
+ regular_key.press();
+ EXPECT_REPORT(driver, (KC_X));
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_X));
+ EXPECT_EMPTY_REPORT(driver);
+ EXPECT_REPORT(driver, (KC_A));
+ run_one_scan_loop();
+ regular_key.release();
+ EXPECT_EMPTY_REPORT(driver);
+ run_one_scan_loop();
+}
diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c
index 3ed83a44a6..52fe86d297 100644
--- a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c
+++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c
@@ -450,7 +450,7 @@ static void md_rgb_matrix_config_override(int i) {
float bo = 0;
float po;
- uint8_t highest_active_layer = biton32(layer_state);
+ uint8_t highest_active_layer = get_highest_layer(layer_state);
if (led_animation_circular) {
// TODO: should use min/max values from LED configuration instead of
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index 19e2e858fc..4bb6949b4f 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -32,6 +32,7 @@
#include "usb_main.h"
#include "host.h"
+#include "chibios_config.h"
#include "debug.h"
#include "suspend.h"
#ifdef SLEEP_LED_ENABLE
@@ -91,6 +92,13 @@ uint8_t extra_report_blank[3] = {0};
* ---------------------------------------------------------
*/
+/* USB Low Level driver specific endpoint fields */
+#if !defined(usb_lld_endpoint_fields)
+# define usb_lld_endpoint_fields \
+ 2, /* IN multiplier */ \
+ NULL, /* SETUP buffer (not a SETUP endpoint) */
+#endif
+
/* HID specific constants */
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
@@ -121,16 +129,15 @@ static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype
static USBInEndpointState kbd_ep_state;
/* keyboard endpoint initialization structure (IN) - see USBEndpointConfig comment at top of file */
static const USBEndpointConfig kbd_ep_config = {
- USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
- NULL, /* SETUP packet notification callback */
- kbd_in_cb, /* IN notification callback */
- NULL, /* OUT notification callback */
- KEYBOARD_EPSIZE, /* IN maximum packet size */
- 0, /* OUT maximum packet size */
- &kbd_ep_state, /* IN Endpoint state */
- NULL, /* OUT endpoint state */
- 2, /* IN multiplier */
- NULL /* SETUP buffer (not a SETUP endpoint) */
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ kbd_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ KEYBOARD_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &kbd_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ usb_lld_endpoint_fields /* USB driver specific endpoint fields */
};
#endif
@@ -140,16 +147,15 @@ static USBInEndpointState mouse_ep_state;
/* mouse endpoint initialization structure (IN) - see USBEndpointConfig comment at top of file */
static const USBEndpointConfig mouse_ep_config = {
- USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
- NULL, /* SETUP packet notification callback */
- mouse_in_cb, /* IN notification callback */
- NULL, /* OUT notification callback */
- MOUSE_EPSIZE, /* IN maximum packet size */
- 0, /* OUT maximum packet size */
- &mouse_ep_state, /* IN Endpoint state */
- NULL, /* OUT endpoint state */
- 2, /* IN multiplier */
- NULL /* SETUP buffer (not a SETUP endpoint) */
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ mouse_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ MOUSE_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &mouse_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ usb_lld_endpoint_fields /* USB driver specific endpoint fields */
};
#endif
@@ -159,16 +165,15 @@ static USBInEndpointState shared_ep_state;
/* shared endpoint initialization structure (IN) - see USBEndpointConfig comment at top of file */
static const USBEndpointConfig shared_ep_config = {
- USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
- NULL, /* SETUP packet notification callback */
- shared_in_cb, /* IN notification callback */
- NULL, /* OUT notification callback */
- SHARED_EPSIZE, /* IN maximum packet size */
- 0, /* OUT maximum packet size */
- &shared_ep_state, /* IN Endpoint state */
- NULL, /* OUT endpoint state */
- 2, /* IN multiplier */
- NULL /* SETUP buffer (not a SETUP endpoint) */
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ shared_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ SHARED_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &shared_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ usb_lld_endpoint_fields /* USB driver specific endpoint fields */
};
#endif
@@ -251,29 +256,27 @@ typedef struct {
.queue_capacity_in = stream##_IN_CAPACITY, .queue_capacity_out = stream##_OUT_CAPACITY, \
.in_ep_config = \
{ \
- stream##_IN_MODE, /* Interrupt EP */ \
- NULL, /* SETUP packet notification callback */ \
- qmkusbDataTransmitted, /* IN notification callback */ \
- NULL, /* OUT notification callback */ \
- stream##_EPSIZE, /* IN maximum packet size */ \
- 0, /* OUT maximum packet size */ \
- NULL, /* IN Endpoint state */ \
- NULL, /* OUT endpoint state */ \
- 2, /* IN multiplier */ \
- NULL /* SETUP buffer (not a SETUP endpoint) */ \
+ stream##_IN_MODE, /* Interrupt EP */ \
+ NULL, /* SETUP packet notification callback */ \
+ qmkusbDataTransmitted, /* IN notification callback */ \
+ NULL, /* OUT notification callback */ \
+ stream##_EPSIZE, /* IN maximum packet size */ \
+ 0, /* OUT maximum packet size */ \
+ NULL, /* IN Endpoint state */ \
+ NULL, /* OUT endpoint state */ \
+ usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \
}, \
.out_ep_config = \
{ \
- stream##_OUT_MODE, /* Interrupt EP */ \
- NULL, /* SETUP packet notification callback */ \
- NULL, /* IN notification callback */ \
- qmkusbDataReceived, /* OUT notification callback */ \
- 0, /* IN maximum packet size */ \
- stream##_EPSIZE, /* OUT maximum packet size */ \
- NULL, /* IN Endpoint state */ \
- NULL, /* OUT endpoint state */ \
- 2, /* IN multiplier */ \
- NULL, /* SETUP buffer (not a SETUP endpoint) */ \
+ stream##_OUT_MODE, /* Interrupt EP */ \
+ NULL, /* SETUP packet notification callback */ \
+ NULL, /* IN notification callback */ \
+ qmkusbDataReceived, /* OUT notification callback */ \
+ 0, /* IN maximum packet size */ \
+ stream##_EPSIZE, /* OUT maximum packet size */ \
+ NULL, /* IN Endpoint state */ \
+ NULL, /* OUT endpoint state */ \
+ usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \
}, \
.int_ep_config = \
{ \
@@ -285,8 +288,7 @@ typedef struct {
0, /* OUT maximum packet size */ \
NULL, /* IN Endpoint state */ \
NULL, /* OUT endpoint state */ \
- 2, /* IN multiplier */ \
- NULL, /* SETUP buffer (not a SETUP endpoint) */ \
+ usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \
}, \
.config = { \
.usbp = &USB_DRIVER, \
diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c
index 053d2b79e3..3d8604d541 100644
--- a/tmk_core/protocol/host.c
+++ b/tmk_core/protocol/host.c
@@ -94,6 +94,11 @@ void host_mouse_send(report_mouse_t *report) {
#ifdef MOUSE_SHARED_EP
report->report_id = REPORT_ID_MOUSE;
#endif
+#ifdef MOUSE_EXTENDED_REPORT
+ // clip and copy to Boot protocol XY
+ report->boot_x = (report->x > 127) ? 127 : ((report->x < -127) ? -127 : report->x);
+ report->boot_y = (report->y > 127) ? 127 : ((report->y < -127) ? -127 : report->y);
+#endif
(*driver->send_mouse)(report);
}
diff --git a/tmk_core/protocol/report.h b/tmk_core/protocol/report.h
index 7bbeb78af7..735ccdb4a1 100644
--- a/tmk_core/protocol/report.h
+++ b/tmk_core/protocol/report.h
@@ -201,15 +201,25 @@ typedef struct {
uint32_t usage;
} __attribute__((packed)) report_programmable_button_t;
+#ifdef MOUSE_EXTENDED_REPORT
+typedef int16_t mouse_xy_report_t;
+#else
+typedef int8_t mouse_xy_report_t;
+#endif
+
typedef struct {
#ifdef MOUSE_SHARED_EP
uint8_t report_id;
#endif
uint8_t buttons;
- int8_t x;
- int8_t y;
- int8_t v;
- int8_t h;
+#ifdef MOUSE_EXTENDED_REPORT
+ int8_t boot_x;
+ int8_t boot_y;
+#endif
+ mouse_xy_report_t x;
+ mouse_xy_report_t y;
+ int8_t v;
+ int8_t h;
} __attribute__((packed)) report_mouse_t;
typedef struct {
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index 063bd2c3f1..52e3276d35 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -126,14 +126,27 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
- // X/Y position (2 bytes)
+# ifdef MOUSE_EXTENDED_REPORT
+ // Boot protocol XY ignored in Report protocol
+ HID_RI_REPORT_COUNT(8, 0x02),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_INPUT(8, HID_IOF_CONSTANT),
+# endif
+ // X/Y position (2 or 4 bytes)
HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
HID_RI_USAGE(8, 0x30), // X
HID_RI_USAGE(8, 0x31), // Y
+# ifndef MOUSE_EXTENDED_REPORT
HID_RI_LOGICAL_MINIMUM(8, -127),
HID_RI_LOGICAL_MAXIMUM(8, 127),
HID_RI_REPORT_COUNT(8, 0x02),
HID_RI_REPORT_SIZE(8, 0x08),
+# else
+ HID_RI_LOGICAL_MINIMUM(16, -32767),
+ HID_RI_LOGICAL_MAXIMUM(16, 32767),
+ HID_RI_REPORT_COUNT(8, 0x02),
+ HID_RI_REPORT_SIZE(8, 0x10),
+# endif
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
// Vertical wheel (1 byte)
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index ebde955d3b..d07cc0d27e 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -482,14 +482,28 @@ const PROGMEM uchar shared_hid_report[] = {
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data, Variable, Absolute)
- // X/Y position (2 bytes)
+# ifdef MOUSE_EXTENDED_REPORT
+ // Boot protocol XY ignored in Report protocol
+ 0x95, 0x02, // Report Count (2)
+ 0x75, 0x08, // Report Size (8)
+ 0x81, 0x03, // Input (Constant)
+# endif
+
+ // X/Y position (2 or 4 bytes)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
+# ifndef MOUSE_EXTENDED_REPORT
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x95, 0x02, // Report Count (2)
0x75, 0x08, // Report Size (8)
+# else
+ 0x16, 0x01, 0x80, // Logical Minimum (-32767)
+ 0x26, 0xFF, 0x7F, // Logical Maximum (32767)
+ 0x95, 0x02, // Report Count (2)
+ 0x75, 0x10, // Report Size (16)
+# endif
0x81, 0x06, // Input (Data, Variable, Relative)
// Vertical wheel (1 byte)
diff --git a/users/333fred/333fred.c b/users/333fred/333fred.c
index 99f4e01685..ea7b904403 100644
--- a/users/333fred/333fred.c
+++ b/users/333fred/333fred.c
@@ -115,7 +115,7 @@ void tap_dance_process_keycode(uint16_t keycode) {
}
__attribute__ ((weak))
-void layer_state_set_rgb(uint32_t state) {}
+void layer_state_set_rgb(layer_state_t state) {}
layer_state_t layer_state_set_user(layer_state_t state) {
layer_state_set_rgb(state);
diff --git a/users/333fred/rgb.c b/users/333fred/rgb.c
index d287143302..ae21702030 100644
--- a/users/333fred/rgb.c
+++ b/users/333fred/rgb.c
@@ -23,8 +23,8 @@
#include "quantum.h"
#include "333fred.h"
-void layer_state_set_rgb(uint32_t state) {
- switch (biton32(state)) {
+void layer_state_set_rgb(layer_state_t state) {
+ switch (get_highest_layer(state)) {
case BASE:
// purple
rgblight_sethsv_noeeprom(210, 255, 20);
diff --git a/users/bbaserdem/bbaserdem.c b/users/bbaserdem/bbaserdem.c
index cdacda12ee..e0cf3d81d1 100644
--- a/users/bbaserdem/bbaserdem.c
+++ b/users/bbaserdem/bbaserdem.c
@@ -59,7 +59,7 @@ __attribute__ ((weak)) void matrix_scan_keymap(void) { }
__attribute__ ((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
return true;
}
-__attribute__ ((weak)) uint32_t layer_state_set_keymap (uint32_t state) {
+__attribute__ ((weak)) layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
__attribute__ ((weak)) void led_set_keymap(uint8_t usb_led) { }
@@ -627,7 +627,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
state = layer_state_set_keymap (state);
#ifdef RGBLIGHT_ENABLE
// Change RGB lighting depending on the last layer activated
- rgblight_change( biton32(state) );
+ rgblight_change( get_highest_layer(state) );
#endif
return state;
}
diff --git a/users/bcat/rules.mk b/users/bcat/rules.mk
index 1ad2ee0aa8..090f7474eb 100644
--- a/users/bcat/rules.mk
+++ b/users/bcat/rules.mk
@@ -47,7 +47,6 @@ endif
COMMAND_ENABLE = no
CONSOLE_ENABLE = no
MOUSEKEY_ENABLE = no
-TERMINAL_ENABLE = no
# Disable unwanted hardware options on all keyboards. (Some keyboards turn
# these features on by default even though they aren't actually required.)
diff --git a/users/billypython/billypython.c b/users/billypython/billypython.c
index 180b478d7a..f165d2e260 100644
--- a/users/billypython/billypython.c
+++ b/users/billypython/billypython.c
@@ -23,7 +23,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
__attribute__((weak))
-uint32_t layer_state_set_keymap(uint32_t state) {
+layer_state_t layer_state_set_keymap(layer_state_t state) {
return state;
}
diff --git a/users/billypython/billypython.h b/users/billypython/billypython.h
index 4a444e9787..cdf5121f2f 100644
--- a/users/billypython/billypython.h
+++ b/users/billypython/billypython.h
@@ -31,4 +31,4 @@ enum layers_user {
};
bool process_record_keymap(uint16_t keycode, keyrecord_t *record);
-uint32_t layer_state_set_keymap(uint32_t state);
+layer_state_t layer_state_set_keymap(layer_state_t state);
diff --git a/users/dhertz/dhertz.c b/users/dhertz/dhertz.c
index 163b1cb644..1a2b6e38f1 100644
--- a/users/dhertz/dhertz.c
+++ b/users/dhertz/dhertz.c
@@ -18,7 +18,7 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
return true;
}
__attribute__ ((weak))
-uint32_t layer_state_set_keymap (uint32_t state) {
+layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
__attribute__ ((weak))
@@ -107,4 +107,3 @@ layer_state_t layer_state_set_user (layer_state_t state) {
void led_set_user(uint8_t usb_led) {
led_set_keymap(usb_led);
}
-
diff --git a/users/doogle999/doogle999.c b/users/doogle999/doogle999.c
index 320de7cff8..c9ee125741 100644
--- a/users/doogle999/doogle999.c
+++ b/users/doogle999/doogle999.c
@@ -382,7 +382,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t* record)
static char text[CALC_BUFFER_SIZE + 1]; // Used to store input and then output when ready to print
static char backspaceText[CALC_BUFFER_SIZE + 1]; // Pretty dumb waste of memory because only backspace characters, used with send_string to backspace and remove input
- if((biton32(layer_state) == CALC_LAYER && CALC_FORCE_NUM_LOCK_INSIDE_CALC) || (biton32(layer_state) != CALC_LAYER && CALC_FORCE_NUM_LOCK_OUTSIDE_CALC))
+ if((get_highest_layer(layer_state) == CALC_LAYER && CALC_FORCE_NUM_LOCK_INSIDE_CALC) || (get_highest_layer(layer_state) != CALC_LAYER && CALC_FORCE_NUM_LOCK_OUTSIDE_CALC))
{
bool numpadKeyPressed = record->event.pressed &&
!(get_mods() & MODS_SHIFT_MASK) &&
@@ -397,7 +397,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t* record)
}
}
- if(biton32(layer_state) != CALC_LAYER) { return true; }
+ if(get_highest_layer(layer_state) != CALC_LAYER) { return true; }
int action = process_input(keycode, get_mods(), record->event);
switch(action)
@@ -457,4 +457,4 @@ bool process_record_user(uint16_t keycode, keyrecord_t* record)
send_string(characterToSend);
}
return false;
-} \ No newline at end of file
+}
diff --git a/users/edvorakjp/edvorakjp.c b/users/edvorakjp/edvorakjp.c
index c44d8bb440..c95b03d981 100644
--- a/users/edvorakjp/edvorakjp.c
+++ b/users/edvorakjp/edvorakjp.c
@@ -12,7 +12,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
return layer_state_set_keymap(state);
}
-__attribute__((weak)) uint32_t layer_state_set_keymap(uint32_t state) { return state; }
+__attribute__((weak)) layer_state_t layer_state_set_keymap(layer_state_t state) { return state; }
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
bool process_record_user_result = process_record_keymap(keycode, record) && process_record_edvorakjp_swap_scln(keycode, record) && process_record_edvorakjp_config(keycode, record) && process_record_layer(keycode, record) && process_record_ime(keycode, record);
diff --git a/users/edvorakjp/edvorakjp.h b/users/edvorakjp/edvorakjp.h
index 93cd9851b7..a878f71ca8 100644
--- a/users/edvorakjp/edvorakjp.h
+++ b/users/edvorakjp/edvorakjp.h
@@ -68,7 +68,7 @@ enum tap_dance_code {
void matrix_init_user(void);
void matrix_init_keymap(void);
layer_state_t layer_state_set_user(layer_state_t state);
-uint32_t layer_state_set_keymap(uint32_t state);
+layer_state_t layer_state_set_keymap(layer_state_t state);
bool process_record_user(uint16_t keycode, keyrecord_t *record);
bool process_record_keymap(uint16_t keycode, keyrecord_t *record);
diff --git a/users/edvorakjp/edvorakjp_tap_dance.c b/users/edvorakjp/edvorakjp_tap_dance.c
index cee10de693..69fcbac1ca 100644
--- a/users/edvorakjp/edvorakjp_tap_dance.c
+++ b/users/edvorakjp/edvorakjp_tap_dance.c
@@ -64,6 +64,15 @@ void td_raise_reset(qk_tap_dance_state_t *state, void *user_data) {
}
qk_tap_dance_action_t tap_dance_actions[] = {
- [TD_EDVORAKJP_LOWER] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, td_lower_finished, td_lower_reset, 150),
- [TD_EDVORAKJP_RAISE] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, td_raise_finished, td_raise_reset, 150),
+ [TD_EDVORAKJP_LOWER] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, td_lower_finished, td_lower_reset),
+ [TD_EDVORAKJP_RAISE] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, td_raise_finished, td_raise_reset),
};
+
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
+ return 150;
+ default:
+ return TAPPING_TERM;
+ }
+}
diff --git a/users/ericgebhart/ericgebhart.c b/users/ericgebhart/ericgebhart.c
index 2a34110ae2..a071fb8c2e 100755
--- a/users/ericgebhart/ericgebhart.c
+++ b/users/ericgebhart/ericgebhart.c
@@ -40,7 +40,7 @@ __attribute__ ((weak))
void matrix_scan_keymap(void) {}
__attribute__ ((weak))
-uint32_t layer_state_set_keymap (uint32_t state) {
+layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
diff --git a/users/ericgebhart/tap_dances.c b/users/ericgebhart/tap_dances.c
index 9f344986aa..8f9503a261 100755
--- a/users/ericgebhart/tap_dances.c
+++ b/users/ericgebhart/tap_dances.c
@@ -47,7 +47,7 @@ void tap_dance_mouse_btns (qk_tap_dance_state_t *state, void *user_data) {
// counting on all the qwerty layers to be less than dvorak_on_bepo
int on_qwerty(){
- uint8_t deflayer = (biton32(default_layer_state));
+ uint8_t deflayer = (get_highest_layer(default_layer_state));
return (deflayer < _DVORAK_BP);
}
@@ -58,7 +58,7 @@ static void switch_default_layer(uint8_t layer) {
// so the keyboard remembers which layer it's in after power disconnect.
/*
- uint32_t default_layer_state_set_kb(uint32_t state) {
+ layer_state_t default_layer_state_set_kb(layer_state_t state) {
eeconfig_update_default_layer(state);
return state;
}
diff --git a/users/gourdo1/gourdo1.c b/users/gourdo1/gourdo1.c
index b964729be9..4e741ccc91 100644
--- a/users/gourdo1/gourdo1.c
+++ b/users/gourdo1/gourdo1.c
@@ -45,7 +45,7 @@ qk_tap_dance_action_t tap_dance_actions[] = {
[TD_LSFT_CAPSLOCK] = ACTION_TAP_DANCE_DOUBLE(KC_LSFT, KC_CAPS),
[TD_LSFT_CAPS_WIN] = ACTION_TAP_DANCE_FN_ADVANCED(dance_LSFT_each_tap, NULL, dance_LSFT_reset),
// Tap once for Escape, twice to reset to base layer
- [TD_ESC_BASELYR] = ACTION_TAP_DANCE_DUAL_ROLE(KC_ESC, _BASE),
+ [TD_ESC_BASELYR] = ACTION_TAP_DANCE_LAYER_MOVE(KC_ESC, _BASE),
};
#endif // TD_LSFT_CAPSLOCK_ENABLE
diff --git a/users/hvp/config.h b/users/hvp/config.h
index 68dd8b4828..b7d0443bbc 100644
--- a/users/hvp/config.h
+++ b/users/hvp/config.h
@@ -15,4 +15,5 @@
*/
#pragma once
-#define LONG_TAPPING_TERM 1000 \ No newline at end of file
+#define LONG_TAPPING_TERM 1000
+#define PERMISSIVE_HOLD
diff --git a/users/kuchosauronad0/kuchosauronad0.c b/users/kuchosauronad0/kuchosauronad0.c
index a8f17b08ee..820d84daad 100644
--- a/users/kuchosauronad0/kuchosauronad0.c
+++ b/users/kuchosauronad0/kuchosauronad0.c
@@ -117,7 +117,7 @@ void matrix_scan_user(void){
}
__attribute__ ((weak))
-uint32_t layer_state_set_keymap (uint32_t state) {
+layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
@@ -133,12 +133,12 @@ layer_state_t layer_state_set_user(layer_state_t state) {
__attribute__ ((weak))
-uint32_t default_layer_state_set_keymap (uint32_t state) {
+layer_state_t default_layer_state_set_keymap (layer_state_t state) {
return state;
}
// Runs state check and changes underglow color and animation
-uint32_t default_layer_state_set_user(uint32_t state) {
+layer_state_t default_layer_state_set_user(layer_state_t state) {
state = default_layer_state_set_keymap(state);
#if 0
#ifdef RGBLIGHT_ENABLE
diff --git a/users/kuchosauronad0/kuchosauronad0.h b/users/kuchosauronad0/kuchosauronad0.h
index da996457c6..5cbd517d67 100644
--- a/users/kuchosauronad0/kuchosauronad0.h
+++ b/users/kuchosauronad0/kuchosauronad0.h
@@ -65,8 +65,8 @@ void shutdown_keymap(void);
void suspend_power_down_keymap(void);
void suspend_wakeup_init_keymap(void);
void matrix_scan_keymap(void);
-uint32_t layer_state_set_keymap (uint32_t state);
-uint32_t default_layer_state_set_keymap (uint32_t state);
+layer_state_t layer_state_set_keymap (layer_state_t state);
+layer_state_t default_layer_state_set_keymap (layer_state_t state);
void led_set_keymap(uint8_t usb_led);
void eeconfig_init_keymap(void);
diff --git a/users/kuchosauronad0/rgblight_user.c b/users/kuchosauronad0/rgblight_user.c
index 63e412c557..feea0c412f 100644
--- a/users/kuchosauronad0/rgblight_user.c
+++ b/users/kuchosauronad0/rgblight_user.c
@@ -84,7 +84,7 @@ void matrix_scan_rgb(void) {
layer_state_t layer_state_set_rgb(layer_state_t state) {
# ifdef RGBLIGHT_ENABLE
if (userspace_config.rgb_layer_change) {
- switch (biton32(state)) { // _RAISE, _LOWER and _ADJUST use a custom color and the breathing effect
+ switch (get_highest_layer(state)) { // _RAISE, _LOWER and _ADJUST use a custom color and the breathing effect
case _RAISE:
rgblight_sethsv_noeeprom_green();
rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3);
@@ -98,7 +98,7 @@ layer_state_t layer_state_set_rgb(layer_state_t state) {
rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 2);
break;
default: // Use a solid color for normal layers
- switch (biton32(default_layer_state)) {
+ switch (get_highest_layer(default_layer_state)) {
case _QWERTY:
rgblight_sethsv_noeeprom_magenta();
break;
@@ -118,7 +118,7 @@ layer_state_t layer_state_set_rgb(layer_state_t state) {
rgblight_sethsv_noeeprom_white();
break;
}
- biton32(state) == _MODS ? rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING) : rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT); // if _MODS layer is on, then breath to denote it
+ get_highest_layer(state) == _MODS ? rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING) : rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT); // if _MODS layer is on, then breath to denote it
break;
}
}
@@ -135,7 +135,7 @@ void matrix_scan_indicator(void) {
#endif // !INDICATOR_LIGHTS
void rgblight_fade_helper(bool direction){
- // true: increase val = fade in
+ // true: increase val = fade in
// false: decrease val = fade out
for (uint8_t index = 0; index < RGBLIGHT_VAL_STEP ; index++) {
direction ? rgblight_increase_val() : rgblight_decrease_val();
@@ -147,10 +147,10 @@ void fadeflash_leds(uint8_t hue, uint8_t sat, uint8_t val){
// fade out, set new hue and saturation, fade in, fade out, set old color, fade in
// this is used in leader.c
// TODO: come up with a better name maybe
- rgblight_fade_helper(false);
- rgblight_sethsv_noeeprom(hue, sat, 0);
- rgblight_fade_helper(true);
- rgblight_fade_helper(false);
- rgblight_sethsv_noeeprom(base_hue, base_sat, 0);
- rgblight_fade_helper(true);
+ rgblight_fade_helper(false);
+ rgblight_sethsv_noeeprom(hue, sat, 0);
+ rgblight_fade_helper(true);
+ rgblight_fade_helper(false);
+ rgblight_sethsv_noeeprom(base_hue, base_sat, 0);
+ rgblight_fade_helper(true);
}
diff --git a/users/kuchosauronad0/template.c b/users/kuchosauronad0/template.c
index 475e45d391..76cc572be3 100644
--- a/users/kuchosauronad0/template.c
+++ b/users/kuchosauronad0/template.c
@@ -63,11 +63,11 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
__attribute__ ((weak))
-uint32_t layer_state_set_keymap (uint32_t state) {
+layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
-uint32_t layer_state_set_user (uint32_t state) {
+layer_state_t layer_state_set_user (layer_state_t state) {
return layer_state_set_keymap (state);
}
diff --git a/users/mnil/config.h b/users/mnil/config.h
index 3547785ff7..b471b9a818 100644
--- a/users/mnil/config.h
+++ b/users/mnil/config.h
@@ -19,3 +19,4 @@
#define MK_3_SPEED
#define MK_MOMENTARY_ACCEL
#define PERMISSIVE_HOLD
+#define TAPPING_TERM 250
diff --git a/users/mnil/mnil.c b/users/mnil/mnil.c
index d5bd0ef0bb..00da6086ef 100644
--- a/users/mnil/mnil.c
+++ b/users/mnil/mnil.c
@@ -140,7 +140,7 @@ void aa_reset(qk_tap_dance_state_t *state, void *user_data) {
// clang-format off
qk_tap_dance_action_t tap_dance_actions[] = {
- [AAE] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, ae_finished, ae_reset, 250),
- [OAA] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, aa_finished, aa_reset, 250)
+ [AAE] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ae_finished, ae_reset),
+ [OAA] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, aa_finished, aa_reset)
};
// clang-format on
diff --git a/users/mtdjr/mtdjr.c b/users/mtdjr/mtdjr.c
index 9c6c26bc86..cd67bf3b5f 100644
--- a/users/mtdjr/mtdjr.c
+++ b/users/mtdjr/mtdjr.c
@@ -137,7 +137,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
};
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _RAISE:
#ifdef RGBLIGHT_ENABLE
rgblight_sethsv_noeeprom (240, 255, 255);
diff --git a/users/ninjonas/config.h b/users/ninjonas/config.h
index 025dbb541a..565e40e841 100644
--- a/users/ninjonas/config.h
+++ b/users/ninjonas/config.h
@@ -2,6 +2,7 @@
#undef TAPPING_TERM
#define TAPPING_TERM 200
#endif
+#define TAPPING_TERM_PER_KEY
// Mouse Settings: Smoothing out mouse movement on keypress
#ifndef MOUSEKEY_INTERVAL
@@ -18,4 +19,4 @@
#undef COMBO_TERM
#define COMBO_COUNT 5
#define COMBO_TERM 60
-#endif \ No newline at end of file
+#endif
diff --git a/users/ninjonas/oled.c b/users/ninjonas/oled.c
index 55eaf88ccb..463c6dfebb 100644
--- a/users/ninjonas/oled.c
+++ b/users/ninjonas/oled.c
@@ -23,7 +23,7 @@ bool process_record_oled(uint16_t keycode, keyrecord_t *record) {
void render_layout_state(void) {
oled_write_P(PSTR("Layout: "), false);
- switch (biton32(default_layer_state)) {
+ switch (get_highest_layer(default_layer_state)) {
case _COLEMAK:
oled_write_P(PSTR("Colemak"), false);
break;
diff --git a/users/ninjonas/tap_dances.c b/users/ninjonas/tap_dances.c
index 63e4d3ba47..3e4cec9133 100644
--- a/users/ninjonas/tap_dances.c
+++ b/users/ninjonas/tap_dances.c
@@ -107,6 +107,16 @@ qk_tap_dance_action_t tap_dance_actions[] = {
[TD_GUI_GUISPC] = ACTION_TAP_DANCE_DOUBLE(KC_LGUI, LGUI(KC_SPC)),
// Advanced Tap Dances
- [TD_COPY_PASTE_APP] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, copy_paste_app_finished, copy_paste_app_reset, 300),
- [TD_Y_NUMPAD] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, y_numpad_finished, y_numpad_reset, 300),
-}; \ No newline at end of file
+ [TD_COPY_PASTE_APP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, copy_paste_app_finished, copy_paste_app_reset),
+ [TD_Y_NUMPAD] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, y_numpad_finished, y_numpad_reset),
+};
+
+uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case TD(TD_COPY_PASTE_APP):
+ case TD(TD_Y_NUMPAD):
+ return 300;
+ default:
+ return TAPPING_TERM;
+ }
+}
diff --git a/users/pvinis/pvinis.c b/users/pvinis/pvinis.c
index 71f9210aec..96b01bb461 100644
--- a/users/pvinis/pvinis.c
+++ b/users/pvinis/pvinis.c
@@ -95,4 +95,4 @@ void keyboard_post_init_user(void) {
// Default functions.
__attribute__((weak)) void keyboard_post_init_user_keymap(void) {}
-__attribute__((weak)) uint32_t layer_state_set_user_keymap(uint32_t state) { return state; }
+__attribute__((weak)) layer_state_t layer_state_set_user_keymap(layer_state_t state) { return state; }
diff --git a/users/pvinis/pvinis.h b/users/pvinis/pvinis.h
index c50033a440..5a11a6cb6f 100644
--- a/users/pvinis/pvinis.h
+++ b/users/pvinis/pvinis.h
@@ -169,4 +169,4 @@ enum {
// Extra stuff that might be needed.
void keyboard_post_init_user_keymap(void);
-uint32_t layer_state_set_user_keymap(uint32_t state);
+layer_state_t layer_state_set_user_keymap(layer_state_t state);
diff --git a/users/romus/romus.c b/users/romus/romus.c
index f707bb8843..a41a6df578 100644
--- a/users/romus/romus.c
+++ b/users/romus/romus.c
@@ -59,7 +59,7 @@ __attribute__ ((weak)) void matrix_scan_keymap(void) { }
__attribute__ ((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
return true;
}
-__attribute__ ((weak)) uint32_t layer_state_set_keymap (uint32_t state) {
+__attribute__ ((weak)) layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
__attribute__ ((weak)) void led_set_keymap(uint8_t usb_led) { }
@@ -551,7 +551,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
state = layer_state_set_keymap (state);
#ifdef RGBLIGHT_ENABLE
// Change RGB lighting depending on the last layer activated
- rgblight_change( biton32(state) );
+ rgblight_change( get_highest_layer(state) );
#endif
return state;
}
diff --git a/users/sigma/sigma.c b/users/sigma/sigma.c
index 527925a63f..8470060a53 100644
--- a/users/sigma/sigma.c
+++ b/users/sigma/sigma.c
@@ -49,12 +49,12 @@ bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
__attribute__ ((weak))
-uint32_t layer_state_set_keymap (uint32_t state) {
+layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
__attribute__ ((weak))
-uint32_t default_layer_state_set_keymap (uint32_t state) {
+layer_state_t default_layer_state_set_keymap (layer_state_t state) {
return state;
}
diff --git a/users/stanrc85/layer_rgb.c b/users/stanrc85/layer_rgb.c
index 6d57198f3b..ad30c2ee65 100644
--- a/users/stanrc85/layer_rgb.c
+++ b/users/stanrc85/layer_rgb.c
@@ -5,7 +5,7 @@ void matrix_init_user(void) {
};
layer_state_t layer_state_set_user(layer_state_t state) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case 0:
rgblight_setrgb (0xFF, 0x00, 0x00);
break;
diff --git a/users/talljoe/talljoe.c b/users/talljoe/talljoe.c
index 517f712ec8..6655170d4a 100644
--- a/users/talljoe/talljoe.c
+++ b/users/talljoe/talljoe.c
@@ -138,7 +138,7 @@ void matrix_init_user(void) {
}
}
-uint32_t default_layer_state_set_kb(uint32_t state) {
+layer_state_t default_layer_state_set_kb(layer_state_t state) {
// persist changes to default layers
eeconfig_update_default_layer(state);
return state;
diff --git a/users/tominabox1/tominabox1.c b/users/tominabox1/tominabox1.c
index 7322ead0dc..b4ec224d07 100644
--- a/users/tominabox1/tominabox1.c
+++ b/users/tominabox1/tominabox1.c
@@ -128,7 +128,7 @@ layer_state_t layer_state_set_keymap (layer_state_t state) {
layer_state_t layer_state_set_user(layer_state_t state) {
state = update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _LOWER:
break;
case _RAISE:
@@ -231,7 +231,7 @@ void render_status_main(void) {
// Host Keyboard Layer Status
oled_write_P(PSTR("Layer: "), false);
- switch (biton32(layer_state)) {
+ switch (get_highest_layer(layer_state)) {
case _BASE:
oled_write_P(PSTR("Colemak\n"), false);
break;
diff --git a/users/turbomech/backupturbomech.c b/users/turbomech/backupturbomech.c
index aaea05df96..3671d27ab4 100644
--- a/users/turbomech/backupturbomech.c
+++ b/users/turbomech/backupturbomech.c
@@ -31,7 +31,7 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
return true;
}
__attribute__ ((weak))
-uint32_t layer_state_set_keymap (uint32_t state) {
+layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
__attribute__ ((weak))
@@ -300,7 +300,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
#ifdef RGBLIGHT_ENABLE
uint8_t default_layer = eeconfig_read_default_layer();
if (rgb_layer_change) {
- switch (biton32(state)) {
+ switch (get_highest_layer(state)) {
case _FUNCTION:
rgblight_set_blue;
rgblight_mode(1);
@@ -377,7 +377,7 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
return true;
}
__attribute__ ((weak))
-uint32_t layer_state_set_keymap (uint32_t state) {
+layer_state_t layer_state_set_keymap (layer_state_t state) {
return state;
}
__attribute__ ((weak))
diff --git a/users/xulkal/custom_oled.c b/users/xulkal/custom_oled.c
index 7fe8040927..fd03033ad6 100644
--- a/users/xulkal/custom_oled.c
+++ b/users/xulkal/custom_oled.c
@@ -37,7 +37,7 @@ static void render_icon(void)
static void render_layer(void)
{
- uint8_t layer = layer_state ? biton(layer_state) : biton32(default_layer_state);
+ uint8_t layer = layer_state ? get_highest_layer(layer_state) : get_highest_layer(default_layer_state);
#ifdef OLED_90ROTATION
oled_write_P(PSTR("Layer"), false);
#else
diff --git a/users/zer09/zer09.c b/users/zer09/zer09.c
index a6768f0a1a..78433b4c20 100644
--- a/users/zer09/zer09.c
+++ b/users/zer09/zer09.c
@@ -43,7 +43,7 @@ void matrix_init_user(void) {
void matrix_scan_user(void) {
static uint8_t is_leds_changes = 1;
- c_lyr = biton32(layer_state);
+ c_lyr = get_highest_layer(layer_state);
is_leds_changes = is_leds_changes << set_layer_led(c_lyr);
is_leds_changes = is_leds_changes << shifted_layer();
diff --git a/util/uf2conv.py b/util/uf2conv.py
index df94b5ac99..7f5645414a 100755
--- a/util/uf2conv.py
+++ b/util/uf2conv.py
@@ -219,6 +219,9 @@ def get_drives():
tmp = rootpath + "/" + os.environ["USER"]
if os.path.isdir(tmp):
rootpath = tmp
+ tmp = "/run" + rootpath + "/" + os.environ["USER"]
+ if os.path.isdir(tmp):
+ rootpath = tmp
for d in os.listdir(rootpath):
drives.append(os.path.join(rootpath, d))
diff --git a/util/update_chibios_mirror.sh b/util/update_chibios_mirror.sh
index e6666c55c9..bd4c5c1529 100755
--- a/util/update_chibios_mirror.sh
+++ b/util/update_chibios_mirror.sh
@@ -7,7 +7,7 @@
chibios_branches="trunk stable_20.3.x stable_21.11.x"
# The ChibiOS tags to mirror
-chibios_tags="ver20.3.1 ver20.3.2 ver20.3.3 ver20.3.4 ver21.11.1"
+chibios_tags="ver20.3.1 ver20.3.2 ver20.3.3 ver20.3.4 ver21.11.1 ver21.11.2"
# The ChibiOS-Contrib branches to mirror
contrib_branches="chibios-20.3.x chibios-21.11.x"