Skip to content

Commit

Permalink
Defined IS_(HOST_)LED_ON/OFF() and improved LED documentation (#4853)
Browse files Browse the repository at this point in the history
* Defined IS_(HOST_)LED_ON/OFF() and improved LED documentation

* Update docs/custom_quantum_functions.md

Co-Authored-By: DidierLoiseau <[email protected]>

* Update docs/custom_quantum_functions.md

Co-Authored-By: DidierLoiseau <[email protected]>

* Integrated @drashna and @fauxpark's PR comments

- changed all plurals of "LED" to "LEDs" in the file
- rewording of the note about host_keyboard_leds() vs. led_set_user()

* Update docs/custom_quantum_functions.md

Co-Authored-By: DidierLoiseau <[email protected]>
  • Loading branch information
DidierLoiseau authored and drashna committed Jan 18, 2019
1 parent 77399bf commit 94ba2e5
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 8 deletions.
54 changes: 46 additions & 8 deletions docs/custom_quantum_functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,39 +90,54 @@ keyrecord_t record {

# LED Control

This allows you to control the 5 LED's defined as part of the USB Keyboard spec. It will be called when the state of one of those 5 LEDs changes.
QMK provides methods to read the 5 LEDs defined as part of the HID spec:

* `USB_LED_NUM_LOCK`
* `USB_LED_CAPS_LOCK`
* `USB_LED_SCROLL_LOCK`
* `USB_LED_COMPOSE`
* `USB_LED_KANA`

These five constants correspond to the positional bits of the host LED state.
There are two ways to get the host LED state:

* by implementing `led_set_user()`
* by calling `host_keyboard_leds()`

## `led_set_user()`

This function will be called when the state of one of those 5 LEDs changes.
It receives the LED state as parameter.
Use the `IS_LED_ON(USB_LED, LED_NAME)` and `IS_LED_OFF(USB_LED, LED_NAME)`
macros to check the LED status.

!> `host_keyboard_leds()` may already reflect a new value before `led_set_user()` is called.

### Example `led_set_user()` Implementation

```c
void led_set_user(uint8_t usb_led) {
if (usb_led & (1<<USB_LED_NUM_LOCK)) {
if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) {
PORTB |= (1<<0);
} else {
PORTB &= ~(1<<0);
}
if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) {
PORTB |= (1<<1);
} else {
PORTB &= ~(1<<1);
}
if (usb_led & (1<<USB_LED_SCROLL_LOCK)) {
if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) {
PORTB |= (1<<2);
} else {
PORTB &= ~(1<<2);
}
if (usb_led & (1<<USB_LED_COMPOSE)) {
if (IS_LED_ON(usb_led, USB_LED_COMPOSE)) {
PORTB |= (1<<3);
} else {
PORTB &= ~(1<<3);
}
if (usb_led & (1<<USB_LED_KANA)) {
if (IS_LED_ON(usb_led, USB_LED_KANA)) {
PORTB |= (1<<4);
} else {
PORTB &= ~(1<<4);
Expand All @@ -135,10 +150,33 @@ void led_set_user(uint8_t usb_led) {
* Keyboard/Revision: `void led_set_kb(uint8_t usb_led)`
* Keymap: `void led_set_user(uint8_t usb_led)`
## `host_keyboard_leds()`
Call this function to get the last received LED state.
This is useful for reading the LED state outside `led_set_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code).
For convenience, you can use the `IS_HOST_LED_ON(LED_NAME)` and `IS_HOST_LED_OFF(LED_NAME)` macros instead of calling `host_keyboard_leds()` directly.
## Setting physical LED state
Some keyboard implementations provide convenience methods for setting the state of the physical LEDs.
### Ergodox and Ergodox EZ
The Ergodox EZ implementation provides `ergodox_right_led_``1`/`2`/`3_on`/`off()`
to turn individual LEDs on and off, as well as
`ergodox_right_led_on`/`off(uint8_t led)`
to turn them on and off by their number.
In addition, it is possible to specify the brightness level with `ergodox_led_all_set(uint8_t n)`,
for individual LEDs with `ergodox_right_led_1`/`2`/`3_set(uint8_t n)`
or by their number using `ergodox_right_led_set(uint8_t led, uint8_t n)`.
It defines `LED_BRIGHTNESS_LO` for the lowest brightness and `LED_BRIGHTNESS_HI` for the highest brightness, which is also the default.
# Matrix Initialization Code
Before a keyboard can be used the hardware must be initialized. QMK handles initialization of the keyboard matrix itself, but if you have other hardware like LED's or i&#xb2;c controllers you will need to set up that hardware before it can be used.
Before a keyboard can be used the hardware must be initialized. QMK handles initialization of the keyboard matrix itself, but if you have other hardware like LEDs or i&#xb2;c controllers you will need to set up that hardware before it can be used.
### Example `matrix_init_user()` Implementation
Expand Down Expand Up @@ -176,7 +214,7 @@ This example has been deliberately omitted. You should understand enough about Q

This function gets called at every matrix scan, which is basically as often as the MCU can handle. Be careful what you put here, as it will get run a lot.

You should use this function if you need custom matrix scanning code. It can also be used for custom status output (such as LED's or a display) or other functionality that you want to trigger regularly even when the user isn't typing.
You should use this function if you need custom matrix scanning code. It can also be used for custom status output (such as LEDs or a display) or other functionality that you want to trigger regularly even when the user isn't typing.


# Keyboard Idling/Wake Code
Expand Down
6 changes: 6 additions & 0 deletions tmk_core/common/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ void host_consumer_send(uint16_t data);
uint16_t host_last_system_report(void);
uint16_t host_last_consumer_report(void);

#define IS_LED_ON(USB_LED, LED_NAME) ((USB_LED) & (1 << (LED_NAME)))
#define IS_LED_OFF(USB_LED, LED_NAME) (~(USB_LED) & (1 << (LED_NAME)))

#define IS_HOST_LED_ON(LED_NAME) IS_LED_ON(host_keyboard_leds(), (LED_NAME))
#define IS_HOST_LED_OFF(LED_NAME) IS_LED_OFF(host_keyboard_leds(), (LED_NAME))

#ifdef __cplusplus
}
#endif
Expand Down

0 comments on commit 94ba2e5

Please sign in to comment.