diff options
author | Drashna Jaelre <drashna@live.com> | 2019-03-18 14:22:02 -0700 |
---|---|---|
committer | MechMerlin <30334081+mechmerlin@users.noreply.github.com> | 2019-03-18 14:22:02 -0700 |
commit | c534a4c775098f2b6cc8e7f36d35cf642f4323a5 (patch) | |
tree | f025c6ade37e4fc6bc930e05fe9a734dd273c974 /docs | |
parent | 28e182bc8a2976562e0d76a1332527e0a4be81ea (diff) |
[Docs] Smallish overhaul of the docs (#5281)
* Fix up Common functions doc
* Add to extra commands to flashing doc
* Rearrange and touch up Macros
* Expand Newbs Flashing guide
* Update process_record documentation
* Add git to best practices name in sidebar
* Expand FAQ for build/flashing
* Add deprecated info to functions
* Update docs/feature_macros.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/feature_macros.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/flashing.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/flashing.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/keymap.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/newbs_flashing.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/newbs_flashing.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/custom_quantum_functions.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/faq_build.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/feature_macros.md
Co-Authored-By: drashna <drashna@live.com>
* Update docs/keymap.md
Co-Authored-By: drashna <drashna@live.com>
* Fix up Common functions doc
* Make pre-init example accurate
* Update docs/custom_quantum_functions.md
Co-Authored-By: drashna <drashna@live.com>
* Zadig Driver catchall
* Spelling Depriciated
* Completely remove fn_actions section
Diffstat (limited to 'docs')
-rw-r--r-- | docs/_summary.md | 2 | ||||
-rw-r--r-- | docs/custom_quantum_functions.md | 44 | ||||
-rw-r--r-- | docs/faq_build.md | 9 | ||||
-rw-r--r-- | docs/feature_macros.md | 97 | ||||
-rw-r--r-- | docs/flashing.md | 19 | ||||
-rw-r--r-- | docs/keymap.md | 56 | ||||
-rw-r--r-- | docs/newbs_flashing.md | 69 | ||||
-rw-r--r-- | docs/understanding_qmk.md | 2 |
8 files changed, 172 insertions, 126 deletions
diff --git a/docs/_summary.md b/docs/_summary.md index df876b794f..c9d6c2bb14 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -3,7 +3,7 @@ * [Building Your First Firmware](newbs_building_firmware.md) * [Flashing Firmware](newbs_flashing.md) * [Testing and Debugging](newbs_testing_debugging.md) - * [Best Practices](newbs_best_practices.md) + * [Git Best Practices](newbs_best_practices.md) * [Learning Resources](newbs_learn_more_resources.md) * [QMK Basics](README.md) diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md index f291fc2d21..655fa1578e 100644 --- a/docs/custom_quantum_functions.md +++ b/docs/custom_quantum_functions.md @@ -116,29 +116,29 @@ Use the `IS_LED_ON(usb_led, led_name)` and `IS_LED_OFF(usb_led, led_name)` macro ```c void led_set_user(uint8_t usb_led) { if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) { - PORTB |= (1<<0); + writePinLow(B0); } else { - PORTB &= ~(1<<0); + writePinHigh(B0); } if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) { - PORTB |= (1<<1); + writePinLow(B1); } else { - PORTB &= ~(1<<1); + writePinHigh(B1); } if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) { - PORTB |= (1<<2); + writePinLow(B2); } else { - PORTB &= ~(1<<2); + writePinHigh(B2); } if (IS_LED_ON(usb_led, USB_LED_COMPOSE)) { - PORTB |= (1<<3); + writePinLow(B3); } else { - PORTB &= ~(1<<3); + writePinHigh(B3); } if (IS_LED_ON(usb_led, USB_LED_KANA)) { - PORTB |= (1<<4); + writePinLow(B4); } else { - PORTB &= ~(1<<4); + writePinHigh(B4); } } ``` @@ -189,16 +189,18 @@ However, if you have hardware stuff that you need initialized, this is the best ### Example `keyboard_pre_init_user()` Implementation -This example, at the keyboard level, sets up B1, B2, and B3 as LED pins. +This example, at the keyboard level, sets up B0, B1, B2, B3, and B4 as LED pins. ```c void keyboard_pre_init_user(void) { // Call the keyboard pre init code. // Set our LED pins as output - DDRB |= (1<<1); - DDRB |= (1<<2); - DDRB |= (1<<3); + setPinOutput(B0); + setPinOutput(B1); + setPinOutput(B2); + setPinOutput(B3); + setPinOutput(B4); } ``` @@ -270,16 +272,13 @@ This is controlled by two functions: `suspend_power_down_*` and `suspend_wakeup_ ### Example suspend_power_down_user() and suspend_wakeup_init_user() Implementation -This example, at the keyboard level, sets up B1, B2, and B3 as LED pins. ```c -void suspend_power_down_user(void) -{ +void suspend_power_down_user(void) { rgb_matrix_set_suspend_state(true); } -void suspend_wakeup_init_user(void) -{ +void suspend_wakeup_init_user(void) { rgb_matrix_set_suspend_state(false); } ``` @@ -356,11 +355,11 @@ user_config_t user_config; This sets up a 32 bit structure that we can store settings with in memory, and write to the EEPROM. Using this removes the need to define variables, since they're defined in this structure. Remember that `bool` (boolean) values use 1 bit, `uint8_t` uses 8 bits, `uint16_t` uses up 16 bits. You can mix and match, but changing the order can cause issues, as it will change the values that are read and written. -We're using `rgb_layer_change`, for the `layer_state_set_*` function, and use `matrix_init_user` and `process_record_user` to configure everything. +We're using `rgb_layer_change`, for the `layer_state_set_*` function, and use `keyboard_post_init_user` and `process_record_user` to configure everything. -Now, using the `matrix_init_user` code above, you want to add `eeconfig_read_user()` to it, to populate the structure you've just created. And you can then immediately use this structure to control functionality in your keymap. And It should look like: +Now, using the `keyboard_post_init_user` code above, you want to add `eeconfig_read_user()` to it, to populate the structure you've just created. And you can then immediately use this structure to control functionality in your keymap. And It should look like: ``` -void matrix_init_user(void) { +void keyboard_post_init_user(void) { // Call the keymap level matrix init. // Read the user config from EEPROM @@ -447,6 +446,7 @@ And lastly, you want to add the `eeconfig_init_user` function, so that when the ``` void eeconfig_init_user(void) { // EEPROM is getting reset! + user_config.raw = 0; user_config.rgb_layer_change = true; // We want this enabled by default eeconfig_update_user(user_config.raw); // Write default value to EEPROM now diff --git a/docs/faq_build.md b/docs/faq_build.md index be26a7c581..45d9439b48 100644 --- a/docs/faq_build.md +++ b/docs/faq_build.md @@ -15,7 +15,7 @@ or just: $ sudo make <keyboard>:<keymap>:dfu -Note that running `make` with `sudo` is generally *not* a good idea, and you should use one of the former methods, if possible. +Note that running `make` with `sudo` is generally ***not*** a good idea, and you should use one of the former methods, if possible. ### Linux `udev` Rules On Linux, you'll need proper privileges to access the MCU. You can either use @@ -47,7 +47,12 @@ If you're using Windows to flash your keyboard, and you are running into issues, Re-running the installation script for MSYS2 may help (eg run `./util/qmk_install.sh` from MSYS2/WSL) or reinstalling the QMK Toolbox may fix the issue. -If that doesn't work, then you may need to grab the [Zadig Utility](https://zadig.akeo.ie/). Download this, find the device in question, and select the `WinUS(libusb-1.0)` option, and hit "Reinstall driver". Once you've done that, try flashing your board, again. +If that doesn't work, then you may need to grab the [Zadig Utility](https://zadig.akeo.ie/). Download this, find the device in question, and select the `WinUSB` option, and hit "Reinstall driver". Once you've done that, try flashing your board, again. If that doesn't work, try all of the options, until one works. + +?> There isn't a best option for which driver should be used here. Some options work better on some systems than others. libUSB and WinUSB seem to be the best options here. + +If the bootloader doesn't show up in the list for devices, you may need to enable the "List all devices" option in the `Options` menu, and then find the bootloader in question. + ## WINAVR is Obsolete It is no longer recommended and may cause some problem. diff --git a/docs/feature_macros.md b/docs/feature_macros.md index 79419abd20..743fc3ad55 100644 --- a/docs/feature_macros.md +++ b/docs/feature_macros.md @@ -146,9 +146,59 @@ send_string(my_str); SEND_STRING(".."SS_TAP(X_END)); ``` -## The Old Way: `MACRO()` & `action_get_macro` -?> This is inherited from TMK, and hasn't been updated - it's recommend that you use `SEND_STRING` and `process_record_user` instead. +## Advanced Macro Functions + +There are some functions you may find useful in macro-writing. Keep in mind that while you can write some fairly advanced code within a macro, if your functionality gets too complex you may want to define a custom keycode instead. Macros are meant to be simple. + +### `record->event.pressed` + +This is a boolean value that can be tested to see if the switch is being pressed or released. An example of this is + +```c + if (record->event.pressed) { + // on keydown + } else { + // on keyup + } +``` + +### `register_code(<kc>);` + +This sends the `<kc>` keydown event to the computer. Some examples would be `KC_ESC`, `KC_C`, `KC_4`, and even modifiers such as `KC_LSFT` and `KC_LGUI`. + +### `unregister_code(<kc>);` + +Parallel to `register_code` function, this sends the `<kc>` keyup event to the computer. If you don't use this, the key will be held down until it's sent. + +### `tap_code(<kc>);` + +This will send `register_code(<kc>)` and then `unregister_code(<kc>)`. This is useful if you want to send both the press and release events ("tap" the key, rather than hold it). + +If you're having issues with taps (un)registering, you can add a delay between the register and unregister events by setting `#define TAP_CODE_DELAY 100` in your `config.h` file. The value is in milliseconds. + +### `register_code16(<kc>);`, `unregister_code16(<kc>);` and `tap_code16(<kc>);` + +These functions work similar to their regular counterparts, but allow you to use modded keycodes (with Shift, Alt, Control, and/or GUI applied to them). + +Eg, you could use `register_code16(S(KC_5));` instead of registering the mod, then registering the keycode. + +### `clear_keyboard();` + +This will clear all mods and keys currently pressed. + +### `clear_mods();` + +This will clear all mods currently pressed. + +### `clear_keyboard_but_mods();` + +This will clear all keys besides the mods currently pressed. + + +## **(DEPRECATED)** The Old Way: `MACRO()` & `action_get_macro` + +!> This is inherited from TMK, and hasn't been updated - it's recommended that you use `SEND_STRING` and `process_record_user` instead. By default QMK assumes you don't have any macros. To define your macros you create an `action_get_macro()` function. For example: @@ -222,49 +272,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; ``` -## Advanced Macro Functions - -There are some functions you may find useful in macro-writing. Keep in mind that while you can write some fairly advanced code within a macro if your functionality gets too complex you may want to define a custom keycode instead. Macros are meant to be simple. - -### `record->event.pressed` - -This is a boolean value that can be tested to see if the switch is being pressed or released. An example of this is - -```c - if (record->event.pressed) { - // on keydown - } else { - // on keyup - } -``` - -### `register_code(<kc>);` - -This sends the `<kc>` keydown event to the computer. Some examples would be `KC_ESC`, `KC_C`, `KC_4`, and even modifiers such as `KC_LSFT` and `KC_LGUI`. - -### `unregister_code(<kc>);` - -Parallel to `register_code` function, this sends the `<kc>` keyup event to the computer. If you don't use this, the key will be held down until it's sent. - -### `tap_code(<kc>);` - -This will send `register_code(<kc>)` and then `unregister_code(<kc>)`. This is useful if you want to send both the press and release events ("tap" the key, rather than hold it). - -If you're having issues with taps (un)registering, you can add a delay between the register and unregister events by setting `#define TAP_CODE_DELAY 100` in your `config.h` file. The value is in milliseconds. - -### `clear_keyboard();` - -This will clear all mods and keys currently pressed. - -### `clear_mods();` - -This will clear all mods currently pressed. - -### `clear_keyboard_but_mods();` - -This will clear all keys besides the mods currently pressed. -## Advanced Example: Single-Key Copy/Paste +### Advanced Example: Single-Key Copy/Paste This example defines a macro which sends `Ctrl-C` when pressed down, and `Ctrl-V` when released. diff --git a/docs/flashing.md b/docs/flashing.md index bc418c4150..cafb43910b 100644 --- a/docs/flashing.md +++ b/docs/flashing.md @@ -49,6 +49,15 @@ To generate this bootloader, use the `bootloader` target, eg `make planck/rev4:d To generate a production-ready .hex file (containing the application and the bootloader), use the `production` target, eg `make planck/rev4:default:production`. +### DFU commands + +There are a number of DFU commands that you can use to flash firmware to a DFU device: + +* `:dfu` - This is the normal option and waits until a DFU device is available, and then flashes the firmware. This will check every 5 seconds, to see if a DFU device has appeared. +* `:dfu-ee` - This flashes an `eep` file instead of the normal hex. This is uncommon. +* `:dfu-split-left` - This flashes the normal firmware, just like the default option (`:dfu`). However, this also flashes the "Left Side" EEPROM file for split keyboards. _This is ideal for Elite C based split keyboards._ +* `:dfu-split-right` - This flashes the normal firmware, just like the default option (`:dfu`). However, this also flashes the "Right Side" EEPROM file for split keyboards. _This is ideal for Elite C based split keyboards._ + ## Caterina Arduino boards and their clones use the [Caterina bootloader](https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/bootloaders/caterina) (any keyboard built with a Pro Micro, or clone), and uses the avr109 protocol to communicate through virtual serial. Bootloaders like [A-Star](https://www.pololu.com/docs/0J61/9) are based on Caterina. @@ -84,6 +93,7 @@ or if you want to flash multiple boards, use the following command When you're done flashing boards, you'll need to hit Ctrl + C or whatever the correct keystroke is for your operating system to break the loop. + ## Halfkay Halfkay is a super-slim protocol developed by PJRC that uses HID, and come on all Teensys (namely the 2.0). @@ -131,3 +141,12 @@ Flashing sequence: * You will receive a warning about the DFU signature; Just ignore it 4. Reset the device into application mode (may be done automatically) * If you are building from command line (e.g. `make planck/rev6:default:dfu-util`), make sure that `:leave` is passed to the `DFU_ARGS` variable inside your `rules.mk` (e.g. `DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave`) so that your device resets after flashing + +### STM32 Commands + +There are a number of DFU commands that you can use to flash firmware to a STM32 device: + +* `:dfu-util` - The default command for flashing to STM32 devices. +* `:dfu-util-wait` - This works like the default command, but it gives you a (configurable) 10 second timeout before it attempts to flash the firmware. You can use `TIME_DELAY=20` from the command line to change the timeout. + * Eg: `make <keyboard>:<keymap>:dfu-util TIME_DELAY=5` +* `:st-link-cli` - This allows you to flash the firmware via ST-LINK's CLI utility, rather than dfu-util. diff --git a/docs/keymap.md b/docs/keymap.md index 49e6654a26..457dbf67e1 100644 --- a/docs/keymap.md +++ b/docs/keymap.md @@ -161,62 +161,6 @@ Some interesting things to note: * We have used our `_______` definition to turn `KC_TRNS` into `_______`. This makes it easier to spot the keys that have changed on this layer. * While in this layer if you press one of the `_______` keys it will activate the key in the next lowest active layer. -### Custom Functions - -At the bottom of the file we've defined a single custom function. This function defines a key that sends `KC_ESC` when pressed without modifiers and `KC_GRAVE` when modifiers are held. There are a couple pieces that need to be in place for this to work, and we will go over both of them. - -#### `fn_actions[]` - -We define the `fn_actions[]` array to point to custom functions. `F(N)` in a keymap will call element N of that array. For the Clueboard's that looks like this: - - const uint16_t PROGMEM fn_actions[] = { - [0] = ACTION_FUNCTION(0), // Calls action_function() - }; - -In this case we've instructed QMK to call the `ACTION_FUNCTION` callback, which we will define in the next section. - -> This `fn_actions[]` interface is mostly for backward compatibility. In QMK, you don't need to use `fn_actions[]`. You can directly use `ACTION_FUNCTION(N)` or any other action code value itself normally generated by the macro in `keymaps[][MATRIX_ROWS][MATRIX_COLS]`. N in `F(N)` can only be 0 to 31. Use of the action code directly in `keymaps` unlocks this limitation. - -You can get a full list of Action Functions in [action_code.h](https://github.com/qmk/qmk_firmware/blob/master/tmk_core/common/action_code.h). - -#### `action_function()` - -To actually handle the keypress event we define an `action_function()`. This function will be called when the key is pressed, and then again when the key is released. We have to handle both situations within our code, as well as determining whether to send/release `KC_ESC` or `KC_GRAVE`. - - void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { - static uint8_t mods_pressed; - - switch (id) { - case 0: - /* Handle the combined Grave/Esc key - */ - mods_pressed = get_mods()&GRAVE_MODS; // Check to see what mods are pressed - - if (record->event.pressed) { - /* The key is being pressed. - */ - if (mods_pressed) { - add_key(KC_GRV); - send_keyboard_report(); - } else { - add_key(KC_ESC); - send_keyboard_report(); - } - } else { - /* The key is being released. - */ - if (mods_pressed) { - del_key(KC_GRV); - send_keyboard_report(); - } else { - del_key(KC_ESC); - send_keyboard_report(); - } - } - break; - } - } - # Nitty Gritty Details This should have given you a basic overview for creating your own keymap. For more details see the following resources: diff --git a/docs/newbs_flashing.md b/docs/newbs_flashing.md index 9d2bf920f5..a985e5d2b2 100644 --- a/docs/newbs_flashing.md +++ b/docs/newbs_flashing.md @@ -131,6 +131,16 @@ If you have any issues with this, you may need to this: sudo make <my_keyboard>:<my_keymap>:dfu +#### DFU commands + +There are a number of DFU commands that you can use to flash firmware to a DFU device: + +* `:dfu` - This is the normal option and waits until a DFU device is available, and then flashes the firmware. This will check every 5 seconds, to see if a DFU device has appeared. +* `:dfu-ee` - This flashes an `eep` file instead of the normal hex. This is uncommon. +* `:dfu-split-left` - This flashes the normal firmware, just like the default option (`:dfu`). However, this also flashes the "Left Side" EEPROM file for split keyboards. _This is ideal for Elite C based split keyboards._ +* `:dfu-split-right` - This flashes the normal firmware, just like the default option (`:dfu`). However, this also flashes the "Right Side" EEPROM file for split keyboards. _This is ideal for Elite C based split keyboards._ + + ### Caterina For Arduino boards and their clones (such as the SparkFun ProMicro), when you're ready to compile and flash your firmware, open up your terminal window and run the build command: @@ -199,6 +209,14 @@ If you have any issues with this, you may need to this: sudo make <my_keyboard>:<my_keymap>:avrdude + +Additionally, if you want to flash multiple boards, use the following command: + + make <keyboard>:<keymap>:avrdude-loop + +When you're done flashing boards, you'll need to hit Ctrl + C or whatever the correct keystroke is for your operating system to break the loop. + + ## HalfKay For the PJRC devices (Teensy's), when you're ready to compile and flash your firmware, open up your terminal window and run the build command: @@ -226,12 +244,61 @@ Waiting for Teensy device... ``` Found HalfKay Bootloader -Read "./.build/ergodox_ez_drashna.hex": 28532 bytes, 88.5% usage +Read "./.build/ergodox_ez_xyverz.hex": 28532 bytes, 88.5% usage Programming............................................................................................................................................................................ ................................................... Booting ``` +## STM32 (ARM) + +For a majority of ARM boards (including the Proton C, Planck Rev 6, and Preonic Rev 3), when you're ready to compile and flash your firmware, open up your terminal window and run the build command: + + make <my_keyboard>:<my_keymap>:dfu-util + +For example, if your keymap is named "xyverz" and you're building a keymap for the Planck Revision 6 keyboard, you'll use this command and then reboot the keyboard to the bootloader (before it finishes compiling): + + make planck/rev6:xyverz:dfu-util + +Once the firmware finishes compiling, it will output something like this: + +``` +Linking: .build/planck_rev6_xyverz.elf [OK] +Creating binary load file for flashing: .build/planck_rev6_xyverz.bin [OK] +Creating load file for flashing: .build/planck_rev6_xyverz.hex [OK] + +Size after: + text data bss dec hex filename + 0 41820 0 41820 a35c .build/planck_rev6_xyverz.hex + +Copying planck_rev6_xyverz.bin to qmk_firmware folder [OK] +dfu-util 0.9 + +Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. +Copyright 2010-2016 Tormod Volden and Stefan Schmidt +This program is Free Software and has ABSOLUTELY NO WARRANTY +Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ + +Invalid DFU suffix signature +A valid DFU suffix will be required in a future dfu-util release!!! +Opening DFU capable USB device... +ID 0483:df11 +Run-time device DFU version 011a +Claiming USB DFU Interface... +Setting Alternate Setting #0 ... +Determining device status: state = dfuERROR, status = 10 +dfuERROR, clearing status +Determining device status: state = dfuIDLE, status = 0 +dfuIDLE, continuing +DFU mode device DFU version 011a +Device returned transfer size 2048 +DfuSe interface name: "Internal Flash " +Downloading to address = 0x08000000, size = 41824 +Download [=========================] 100% 41824 bytes +Download done. +File downloaded successfully +Transitioning to dfuMANIFEST state +``` ## Test It Out! diff --git a/docs/understanding_qmk.md b/docs/understanding_qmk.md index bf4b5eadcd..a94c9c3191 100644 --- a/docs/understanding_qmk.md +++ b/docs/understanding_qmk.md @@ -135,9 +135,11 @@ The `process_record()` function itself is deceptively simple, but hidden within * [`void process_record(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/common/action.c#L172) * [`bool process_record_quantum(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L206) * [Map this record to a keycode](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L226) + * [`void velocikey_accelerate(void)`](https://github.com/qmk/qmk_firmware/blob/c1c5922aae7b60b7c7d13d3769350eed9dda17ab/quantum/velocikey.c#L27) * [`void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_tap_dance.c#L119) * [`bool process_key_lock(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_key_lock.c#L62) * [`bool process_clicky(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_clicky.c#L79) + * [`bool process_haptic(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/2cee371bf125a6ec541dd7c5a809573facc7c456/drivers/haptic/haptic.c#L216) * [`bool process_record_kb(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/card.c#L20) * [`bool process_record_user(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/keymaps/default/keymap.c#L58) * [`bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/rgb_matrix.c#L139) |