Qmk_firmware: How can I toggle my LED when I toggle layer?

Created on 30 Apr 2018  ·  9Comments  ·  Source: qmk/qmk_firmware

My keymap's "Fn" just be set as toggle layer rather than momentary jump to layer, then I try to toggle the user defined LED at the mean time. But I can't find it in code, I think it will be somewhere in process_action, and try to do it under "ACT_LAYER_TAP" but just failed. Anyone who know about this?

help wanted question

Most helpful comment

Googling brought me here. So for the Googlers, for the future reference, I toggle my backlight made of a single led light like this (using backlight_set() method):

// My layer names
#define _MAIN 0
#define _FUNC 1

uint32_t layer_state_set_user(uint32_t state) {
  switch (biton32(state)) {
    case _MAIN:
      backlight_set(3); // The number depends on your configuration's BACKLIGHT_LEVELS definition at config.h
      break;
    case _FUNC:
      backlight_set(0);
      break;
  }
  return state;
}

I’m currently trying to figure this out for an M60-A Seq2. I want to light up specific keys when toggling my layer 1 which has arrow keys and have no idea how to go about it. Any tips? I’m a complete n00b when it comes to anything more than setting up a keymap.

All 9 comments

I think you want something like this: https://qmk.github.io/qmk_firmware/#/custom_quantum_functions?id=layer-change-code

@drashna I can't figure out how to get this working when switching default layers (using DF(layer)). I don't get the layer_state_set_user call when switching default layer. default_layer_state_set_user doesn't seem to be implemented (only default_layer_state_set_kb and if I understand things correctly that shouldn't be used in keymaps?).

What I'm currently doing is

uint32_t layer_state_set_user(uint32_t state) {
    layer = biton32(default_layer_state);
    // set leds
}

The behavior I'm getting is,
switching default layers -> no effect,
then tapping a MO(layer)-key -> the leds are updated.

I do this, actually.

uint32_t layer_state_set_user(uint32_t state) {
#ifdef RGBLIGHT_ENABLE
  uint8_t default_layer = eeconfig_read_default_layer();
  if (userspace_config.rgb_layer_change) {
    switch (biton32(state)) {
    case _MACROS:
      rgblight_sethsv_noeeprom_orange();
      userspace_config.is_overwatch ? rgblight_mode_noeeprom(17) : rgblight_mode_noeeprom(18);
      break;
    case _MEDIA:
      rgblight_sethsv_noeeprom_chartreuse();
      rgblight_mode_noeeprom(22);
      break;
    case _GAMEPAD:
      rgblight_sethsv_noeeprom_orange();
      rgblight_mode_noeeprom(17);
      break;
    case _DIABLO:
      rgblight_sethsv_noeeprom_red();
      rgblight_mode_noeeprom(5);
      break;
    case _RAISE:
      rgblight_sethsv_noeeprom_yellow();
      rgblight_mode_noeeprom(5);
      break;
    case _LOWER:
      rgblight_sethsv_noeeprom_orange();
      rgblight_mode_noeeprom(5);
      break;
    case _ADJUST:
      rgblight_sethsv_noeeprom_red();
      rgblight_mode_noeeprom(23);
      break;
    default: //  for any other layers, or the default layer
      if (default_layer & (1UL << _COLEMAK)) {
        rgblight_sethsv_noeeprom_magenta();
      } else if (default_layer & (1UL << _DVORAK)) {
        rgblight_sethsv_noeeprom_green();
      } else if (default_layer & (1UL << _WORKMAN)) {
        rgblight_sethsv_noeeprom_goldenrod();
      } else {
        rgblight_sethsv_noeeprom_cyan();
      }
      biton32(state) == _MODS ? rgblight_mode_noeeprom(2) : rgblight_mode_noeeprom(1); // if _MODS layer is on, then breath to denote it
      break;
    }
  }
#endif // RGBLIGHT_ENABLE

So on the "0" layer, the base layer.... it checks the default layer, and shows the status based on that.

you could use this instead though:

uint32_t layer_state_set_user(uint32_t state) {
#ifdef RGBLIGHT_ENABLE
  if (userspace_config.rgb_layer_change) {
    switch (biton32(state)) {
    case _MACROS:
      rgblight_sethsv_noeeprom_orange();
      userspace_config.is_overwatch ? rgblight_mode_noeeprom(17) : rgblight_mode_noeeprom(18);
      break;
    case _MEDIA:
      rgblight_sethsv_noeeprom_chartreuse();
      rgblight_mode_noeeprom(22);
      break;
    case _GAMEPAD:
      rgblight_sethsv_noeeprom_orange();
      rgblight_mode_noeeprom(17);
      break;
    case _DIABLO:
      rgblight_sethsv_noeeprom_red();
      rgblight_mode_noeeprom(5);
      break;
    case _RAISE:
      rgblight_sethsv_noeeprom_yellow();
      rgblight_mode_noeeprom(5);
      break;
    case _LOWER:
      rgblight_sethsv_noeeprom_orange();
      rgblight_mode_noeeprom(5);
      break;
    case _ADJUST:
      rgblight_sethsv_noeeprom_red();
      rgblight_mode_noeeprom(23);
      break;
    default: //  for any other layers, or the default layer
      switch (biton32(default_layer_state)) {
        case _COLEMAK:
           rgblight_sethsv_noeeprom_magenta(); break;
        case _DVORAK:
            rgblight_sethsv_noeeprom_green(); break;
         case _WORKMAN:
            rgblight_sethsv_noeeprom_goldenrod(); break;
          default:
        rgblight_sethsv_noeeprom_cyan(); breake
        }
      biton32(state) == _MODS ? rgblight_mode_noeeprom(2) : rgblight_mode_noeeprom(1); // if _MODS layer is on, then breath to denote it
      break;
    }
  }
#endif // RGBLIGHT_ENABLE

Thanks for the reply.
I think I framed my actual question badly. The problem is that it seems like there's no call to layer_state_set_user when the default layer is changed (ie. a DF() mapped key is pressed). The update works, but not until a temporary layer-switch happens (ie. a MO()-key is pressed). So the question is how do I detect a changed default layer?

Well, if you check the default section, it checks the default layer, actually. And I can verify that this works, since I use it in my code.

Though, there is also default_layer_state_set_kb that does get called immediately, when you change the default layer.

There isn't a USER function for this, but you should be fine calling the Keyboard version of it, since it's not used.

Ok I'll use the _kb func. And yes the default works, I just wanted to get the update immediately.
Thanks!

There is a _user function for this now.

Googling brought me here. So for the Googlers, for the future reference, I toggle my backlight made of a single led light like this (using backlight_set() method):

// My layer names
#define _MAIN 0
#define _FUNC 1

uint32_t layer_state_set_user(uint32_t state) {
  switch (biton32(state)) {
    case _MAIN:
      backlight_set(3); // The number depends on your configuration's BACKLIGHT_LEVELS definition at config.h
      break;
    case _FUNC:
      backlight_set(0);
      break;
  }
  return state;
}

Googling brought me here. So for the Googlers, for the future reference, I toggle my backlight made of a single led light like this (using backlight_set() method):

// My layer names
#define _MAIN 0
#define _FUNC 1

uint32_t layer_state_set_user(uint32_t state) {
  switch (biton32(state)) {
    case _MAIN:
      backlight_set(3); // The number depends on your configuration's BACKLIGHT_LEVELS definition at config.h
      break;
    case _FUNC:
      backlight_set(0);
      break;
  }
  return state;
}

I’m currently trying to figure this out for an M60-A Seq2. I want to light up specific keys when toggling my layer 1 which has arrow keys and have no idea how to go about it. Any tips? I’m a complete n00b when it comes to anything more than setting up a keymap.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matz-e picture matz-e  ·  4Comments

MarkuBu picture MarkuBu  ·  3Comments

levitanong picture levitanong  ·  3Comments

kb3dow picture kb3dow  ·  3Comments

mrceephax picture mrceephax  ·  4Comments