Activating a toggle LED using Hasu's TMK code.
-
- Location: Israel
- Main mouse: Logitech MX Master
- DT Pro Member: -
Hi guys,
Me and 4 other buddies grouped up to each make our own custom mechanical keyboard. This is my 1st time doing a thing of the sort, and I haven't even looked into mechanical keyboards before this project.
So after a few months of planning and work, I have finally soldered everything together (to a teensy, following Matt3o the great's guide, building brownfox). I continued using his guide to programme the teensy, using Hasu's tmk, and using the g60 as a base model.
Link to Matt3o's guide I used to programme:
http://deskthority.net/workshop-f7/how- ... t7177.html
It all works. In fact, I am typing this post at the moment with this keyboard I built .
But, there is a little thing I want to add to the keyboard. I have a toggling FN layer, and in order to know if this layer is toggled ON or OFF, I connected an LED to the FN key, and connected it to the GND and D4 pin on the teensy. Everything works, I connected it to the VCC and GND pins to check.
Now. To the point. I have searched the interwebs, and found nothing. Can any saint tell me how to activate the LED when press the FN key, and deactivate it when it is pressed again? (Basically outputting to a pin when the Fn is pressed)
Thanks a whole lot to any helper .
Me and 4 other buddies grouped up to each make our own custom mechanical keyboard. This is my 1st time doing a thing of the sort, and I haven't even looked into mechanical keyboards before this project.
So after a few months of planning and work, I have finally soldered everything together (to a teensy, following Matt3o the great's guide, building brownfox). I continued using his guide to programme the teensy, using Hasu's tmk, and using the g60 as a base model.
Link to Matt3o's guide I used to programme:
http://deskthority.net/workshop-f7/how- ... t7177.html
It all works. In fact, I am typing this post at the moment with this keyboard I built .
But, there is a little thing I want to add to the keyboard. I have a toggling FN layer, and in order to know if this layer is toggled ON or OFF, I connected an LED to the FN key, and connected it to the GND and D4 pin on the teensy. Everything works, I connected it to the VCC and GND pins to check.
Now. To the point. I have searched the interwebs, and found nothing. Can any saint tell me how to activate the LED when press the FN key, and deactivate it when it is pressed again? (Basically outputting to a pin when the Fn is pressed)
Thanks a whole lot to any helper .
- Ray
- Location: Germany
- Main mouse: touchpad
- DT Pro Member: -
There is no standard way of doing this in tmk. And there are many ways to skin this cat.
keyboard.c contains the following:
where keyboard_set_leds(...) calls led_set(...), which is used for setting/clearing the outputs for the lock-leds.
A quick way to achieve your goal is to remove the if in the snippet above and change led.c in the gh60 folder to set the output depending on the layer_state (more on that: https://github.com/tmk/tmk_keyboard/blo ... /keymap.md)
keyboard.c contains the following:
Code: Select all
// update LED
if (led_status != host_keyboard_leds()) {
led_status = host_keyboard_leds();
keyboard_set_leds(led_status);
}
A quick way to achieve your goal is to remove the if in the snippet above and change led.c in the gh60 folder to set the output depending on the layer_state (more on that: https://github.com/tmk/tmk_keyboard/blo ... /keymap.md)
- flabbergast
- Location: Southampton, UK
- DT Pro Member: 0120
- Contact:
Here's another way (there's a pull request about this on github: https://github.com/tmk/tmk_keyboard/pull/198 )
Namely: edit tmk_core/common/action_layer.c like this:
- line 6, add
- line 66 (between 'layer_state = state;' and 'layer_debug(); dprintln();') add
edit tmk_core/common/led.h, add on line 36 (after the declaration of 'led_set' function)
Then you can edit the file 'led.c' in your keyboard's directory, define a 'led_layer_set' function, for instance like this:
This function gets passed the state of layers, so you can act on this in whatever way you like. The code above should turn on a LED on PD4 whenever layer 2 is active.
Namely: edit tmk_core/common/action_layer.c like this:
- line 6, add
Code: Select all
#include "led.h"
Code: Select all
led_layer_set(state);
Code: Select all
void led_layer_set(uint32_t state);
Then you can edit the file 'led.c' in your keyboard's directory, define a 'led_layer_set' function, for instance like this:
Code: Select all
void led_layer_set(uint32_t state) {
DDRD |= (1<<4);
/* Led for Layer 2 */
if ((1<<2 & state) != 0) {
PORTD |= (1<<4);
} else {
PORTD &= ~(1<<4);
}
}
-
- Location: Israel
- Main mouse: Logitech MX Master
- DT Pro Member: -
Thank you so much for all the instant and awesomely helpful replies! Its so amazing to have such an amazing community.
I opted to use flabbergast's method, and it worked like a charm. Thank you again so so much to both of your answers .
Anyway, on a different note, I know that it doesn't have anything to do with this topic, I was wandering how do i make macro keys work, and if any of your guys could help with that (if it is not against forum rules to ask for help on a different topic to the post's original one).
I opted to use flabbergast's method, and it worked like a charm. Thank you again so so much to both of your answers .
Anyway, on a different note, I know that it doesn't have anything to do with this topic, I was wandering how do i make macro keys work, and if any of your guys could help with that (if it is not against forum rules to ask for help on a different topic to the post's original one).
- Ray
- Location: Germany
- Main mouse: touchpad
- DT Pro Member: -
https://github.com/tmk/tmk_keyboard/blo ... /keymap.md
2.3 has some (little) explanation of how tmk's built in macro support. With keyboard/hhkb/keymap.c it isn't too hard to figure it out.
2.3 has some (little) explanation of how tmk's built in macro support. With keyboard/hhkb/keymap.c it isn't too hard to figure it out.
- flabbergast
- Location: Southampton, UK
- DT Pro Member: 0120
- Contact:
This. Also have a look at keyboard/hhkb/keymap_hasu.c, he's got a couple of macro examples. However there's no "on-the-fly" macro programming in TMK (yet?), and each macro consumes one "Fn" action, so I think there's a limit of 16 for all the "Fn" things, including layer switching, etc...
-
- Location: Israel
- Favorite switch: Cherry MX Clear
- DT Pro Member: -
Hey, I tried using this function for more than one FN key, but it just wouldn't compile...flabbergast wrote: ↑Here's another way (there's a pull request about this on github: https://github.com/tmk/tmk_keyboard/pull/198 )
Namely: edit tmk_core/common/action_layer.c like this:
- line 6, add- line 66 (between 'layer_state = state;' and 'layer_debug(); dprintln();') addCode: Select all
#include "led.h"
edit tmk_core/common/led.h, addCode: Select all
led_layer_set(state);
on line 36 (after the declaration of 'led_set' function)Code: Select all
void led_layer_set(uint32_t state);
Then you can edit the file 'led.c' in your keyboard's directory, define a 'led_layer_set' function, for instance like this:This function gets passed the state of layers, so you can act on this in whatever way you like. The code above should turn on a LED on PD4 whenever layer 2 is active.Code: Select all
void led_layer_set(uint32_t state) { DDRD |= (1<<4); /* Led for Layer 2 */ if ((1<<2 & state) != 0) { PORTD |= (1<<4); } else { PORTD &= ~(1<<4); } }
Would you by any chance know how to do that? I have two FN keys and a CAPS lock key which I want to have toggle LEDs when they are "activated".
Here's my function for the two FN keys (I don't know how to make one for the caps lock key):
Code: Select all
void led_layer_set(uint32_t state) {
DDRC |= (1<<7);
/* Led for Layer 1 */
if ((1<<1 & state) != 0) {
PORTC |= (1<<7);
} else {
PORTC &= ~(1<<7);
}
}
void led_layer_set(uint32_t state) {
DDRD |= (1<<5);
/* Led for Layer 2 */
if ((1<<2 & state) != 0) {
PORTD |= (1<<5);
} else {
PORTD &= ~(1<<5);
}
}
Code: Select all
Microsoft Windows [Version 10.0.10240]
(c) 2015 Microsoft Corporation. All rights reserved.
C:\Users\kagan>cd C:\Users\kagan\Documents\Keyboard Software\tmk_keyboard-master\keyboard\gh60
C:\Users\kagan\Documents\Keyboard Software\tmk_keyboard-master\keyboard\gh60>make -f Makefile.pjrc
/usr/bin/sh: dfu-programmer: command not found
/usr/bin/sh: dfu-programmer: command not found
-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Size before:
text data bss dec hex filename
22546 24 148 22718 58be gh60_pjrc.elf
mkdir -p obj_gh60_pjrc
Compiling C: led.c
avr-gcc -c -mmcu=atmega32u4 -gdwarf-2 -DF_CPU=16000000UL -DBOOTLOADER_SIZE=4096 -DPROTOCOL_PJRC -DBOOTMAGIC_ENABLE -DMOUSEKEY_ENABLE -DMOUSE_ENABLE -DEXTRAKEY_ENABLE -DCONSOLE_ENABLE -DCOMMAND_ENABLE -DNKRO_ENABLE -DSLEEP_LED_ENABLE -DNO_SUSPEND_POWER_DOWN -DVERSION=unknown -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fdata-sections -fno-inline-small-functions -fpack-struct -fshort-enums -fno-strict-aliasing -Wall -Wstrict-prototypes -Wa,-adhlns=obj_gh60_pjrc/led.lst -I. -I../../tmk_core -I../../tmk_core/protocol/pjrc -I../../tmk_core/common -std=gnu99 -include config.h -MMD -MP -MF .dep/obj_gh60_pjrc_led.o.d led.c -o obj_gh60_pjrc/led.o
led.c:46: error: redefinition of 'led_layer_set'
led.c:35: error: previous definition of 'led_layer_set' was here
make: *** [obj_gh60_pjrc/led.o] Error 1
C:\Users\kagan\Documents\Keyboard Software\tmk_keyboard-master\keyboard\gh60>
- flabbergast
- Location: Southampton, UK
- DT Pro Member: 0120
- Contact:
In C, each function has to have a unique name - your code defines 2 functions with the same name. So, you'll need to combine the two LEDs into one function:
Code: Select all
void led_layer_set(uint32_t state) {
DDRC |= (1<<7);
DDRD |= (1<<5);
/* Led for Layer 1 */
if ((1<<1 & state) != 0) {
PORTC |= (1<<7);
} else {
PORTC &= ~(1<<7);
}
/* Led for Layer 2 */
if ((1<<2 & state) != 0) {
PORTD |= (1<<5);
} else {
PORTD &= ~(1<<5);
}
}
-
- Location: Israel
- Favorite switch: Cherry MX Clear
- DT Pro Member: -
Awesome! It worked! Thanks a bunch flabbergast!flabbergast wrote: ↑In C, each function has to have a unique name - your code defines 2 functions with the same name. So, you'll need to combine the two LEDs into one function:Code: Select all
void led_layer_set(uint32_t state) { DDRC |= (1<<7); DDRD |= (1<<5); /* Led for Layer 1 */ if ((1<<1 & state) != 0) { PORTC |= (1<<7); } else { PORTC &= ~(1<<7); } /* Led for Layer 2 */ if ((1<<2 & state) != 0) { PORTD |= (1<<5); } else { PORTD &= ~(1<<5); } }
Would you by any chance know how to make the function for the caps lock key?
- flabbergast
- Location: Southampton, UK
- DT Pro Member: 0120
- Contact:
Caps lock led is normally set in led.c, in the led_set function, just like in other keyboards (see e.g. gh60 example).
The point is that the "toggled" led indicators (caps, num, scroll locks) are dealt with in the led_set function, while the "layer" leds in the led_layer_set function.
The point is that the "toggled" led indicators (caps, num, scroll locks) are dealt with in the led_set function, while the "layer" leds in the led_layer_set function.
-
- Location: Israel
- Favorite switch: Cherry MX Clear
- DT Pro Member: -
I tried using the function for the CAPS lock key which LED is connected to the D6 pin:flabbergast wrote: ↑Caps lock led is normally set in led.c, in the led_set function, just like in other keyboards (see e.g. gh60 example).
The point is that the "toggled" led indicators (caps, num, scroll locks) are dealt with in the led_set function, while the "layer" leds in the led_layer_set function.
Code: Select all
void led_set(uint8_t usb_led) {
DDRD |= (1<<6);
/* Led for CAPS */
if ((1<<1 & state) != 0) {
PORTD |= (1<<6);
} else {
PORTD &= ~(1<<6);
}
}
Code: Select all
Microsoft Windows [Version 10.0.10240]
(c) 2015 Microsoft Corporation. All rights reserved.
C:\Users\kagan>cd C:\Users\kagan\Documents\Keyboard Software\tmk_keyboard-master\keyboard\gh60
C:\Users\kagan\Documents\Keyboard Software\tmk_keyboard-master\keyboard\gh60>make -f Makefile.pjrc
/usr/bin/sh: dfu-programmer: command not found
/usr/bin/sh: dfu-programmer: command not found
-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Size before:
text data bss dec hex filename
22558 24 148 22730 58ca gh60_pjrc.elf
mkdir -p obj_gh60_pjrc
Compiling C: led.c
avr-gcc -c -mmcu=atmega32u4 -gdwarf-2 -DF_CPU=16000000UL -DBOOTLOADER_SIZE=4096 -DPROTOCOL_PJRC -DBOOTMAGIC_ENABLE -DMOUSEKEY_ENABLE -DMOUSE_ENABLE -DEXTRAKEY_ENABLE -DCONSOLE_ENABLE -DCOMMAND_ENABLE -DNKRO_ENABLE -DSLEEP_LED_ENABLE -DNO_SUSPEND_POWER_DOWN -DVERSION=unknown -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fdata-sections -fno-inline-small-functions -fpack-struct -fshort-enums -fno-strict-aliasing -Wall -Wstrict-prototypes -Wa,-adhlns=obj_gh60_pjrc/led.lst -I. -I../../tmk_core -I../../tmk_core/protocol/pjrc -I../../tmk_core/common -std=gnu99 -include config.h -MMD -MP -MF .dep/obj_gh60_pjrc_led.o.d led.c -o obj_gh60_pjrc/led.o
led.c: In function 'led_set':
led.c:27: error: 'state' undeclared (first use in this function)
led.c:27: error: (Each undeclared identifier is reported only once
led.c:27: error: for each function it appears in.)
make: *** [obj_gh60_pjrc/led.o] Error 1
C:\Users\kagan\Documents\Keyboard Software\tmk_keyboard-master\keyboard\gh60>
- flabbergast
- Location: Southampton, UK
- DT Pro Member: 0120
- Contact:
Modified from gh60 to use pin D6:
Code: Select all
void led_set(uint8_t usb_led)
{
if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
// output high
DDRD |= (1<<6);
PORTD |= (1<<6);
} else {
// Hi-Z
DDRD &= ~(1<<6);
PORTD &= ~(1<<6);
}
}
-
- Location: Israel
- Favorite switch: Cherry MX Clear
- DT Pro Member: -
Tried using this function but it didn't work when I turned on the caps lock key.flabbergast wrote: ↑Modified from gh60 to use pin D6:Code: Select all
void led_set(uint8_t usb_led) { if (usb_led & (1<<USB_LED_CAPS_LOCK)) { // output high DDRD |= (1<<6); PORTD |= (1<<6); } else { // Hi-Z DDRD &= ~(1<<6); PORTD &= ~(1<<6); } }
Then I tried changing the target LED to a functioning LED in case the problem was a faulty LED - no luck...
Any idea of what might be the problem?
- flabbergast
- Location: Southampton, UK
- DT Pro Member: 0120
- Contact:
You may have the LED wired the other way, i.e. pin --- LED --- resistor --- 5V, rather than pin --- LED --- resistor --- GND (as assumed for the above code). If that's the case, you need to change the first branch of the if statement to
Other than this, I can't really tell without having more information.
Code: Select all
DDRD |= (1<<6);
PORTD &= ~(1<<6);
-
- Location: Israel
- Favorite switch: Cherry MX Clear
- DT Pro Member: -
You were right! Thanks!!!flabbergast wrote: ↑You may have the LED wired the other way, i.e. pin --- LED --- resistor --- 5V, rather than pin --- LED --- resistor --- GND (as assumed for the above code). If that's the case, you need to change the first branch of the if statement toOther than this, I can't really tell without having more information.Code: Select all
DDRD |= (1<<6); PORTD &= ~(1<<6);