diff --git a/common.mk b/common.mk index 540d8da4..0930406d 100644 --- a/common.mk +++ b/common.mk @@ -1,18 +1,18 @@ COMMON_DIR = common -SRC += $(COMMON_DIR)/host.c \ - $(COMMON_DIR)/keyboard.c \ - $(COMMON_DIR)/action.c \ - $(COMMON_DIR)/action_tapping.c \ - $(COMMON_DIR)/action_macro.c \ - $(COMMON_DIR)/action_layer.c \ - $(COMMON_DIR)/action_util.c \ - $(COMMON_DIR)/keymap.c \ - $(COMMON_DIR)/timer.c \ - $(COMMON_DIR)/print.c \ - $(COMMON_DIR)/bootloader.c \ - $(COMMON_DIR)/suspend.c \ - $(COMMON_DIR)/xprintf.S \ - $(COMMON_DIR)/util.c +SRC += $(COMMON_DIR)/host.c \ + $(COMMON_DIR)/keyboard.c \ + $(COMMON_DIR)/action.c \ + $(COMMON_DIR)/action_tapping.c \ + $(COMMON_DIR)/action_macro.c \ + $(COMMON_DIR)/action_layer.c \ + $(COMMON_DIR)/action_util.c \ + $(COMMON_DIR)/keymap.c \ + $(COMMON_DIR)/timer.c \ + $(COMMON_DIR)/print.c \ + $(COMMON_DIR)/bootloader.c \ + $(COMMON_DIR)/suspend.c \ + $(COMMON_DIR)/xprintf.S \ + $(COMMON_DIR)/util.c # Option modules @@ -76,6 +76,16 @@ ifdef BACKLIGHT_ENABLE OPT_DEFS += -DBACKLIGHT_ENABLE endif +ifdef LEDMAP_ENABLE + SRC += $(COMMON_DIR)/ledmap.c + OPT_DEFS += -DLEDMAP_ENABLE +ifdef LEDMAP_IN_EEPROM_ENABLE + SRC += $(COMMON_DIR)/ledmap_in_eeprom.c + OPT_DEFS += -DLEDMAP_IN_EEPROM_ENABLE +endif +endif + + ifdef KEYMAP_SECTION_ENABLE OPT_DEFS += -DKEYMAP_SECTION_ENABLE EXTRALDFLAGS = -Wl,-L$(TOP_DIR),-Tldscript_keymap_avr5.x diff --git a/common/action_layer.c b/common/action_layer.c index 526e24d5..579950ac 100644 --- a/common/action_layer.c +++ b/common/action_layer.c @@ -22,6 +22,9 @@ static void default_layer_state_set(uint32_t state) default_layer_debug(); debug(" to "); default_layer_state = state; default_layer_debug(); debug("\n"); +#ifdef LEDMAP_ENABLE + default_layer_state_change(state); +#endif clear_keyboard_but_mods(); // To avoid stuck keys } @@ -63,6 +66,9 @@ static void layer_state_set(uint32_t state) layer_debug(); dprint(" to "); layer_state = state; layer_debug(); dprintln(); +#ifdef LEDMAP_ENABLE + layer_state_change(state); +#endif clear_keyboard_but_mods(); // To avoid stuck keys } diff --git a/common/action_layer.h b/common/action_layer.h index 034e0002..9af7b875 100644 --- a/common/action_layer.h +++ b/common/action_layer.h @@ -70,6 +70,14 @@ void layer_xor(uint32_t state); #define layer_debug() #endif +#ifdef LEDMAP_ENABLE +void default_layer_state_change(uint32_t state); +void layer_state_change(uint32_t state); +#else +#define default_layer_state_change() +#define layer_state_change() +#endif + /* return action depending on current layer status */ action_t layer_switch_get_action(key_t key); diff --git a/common/bootmagic.c b/common/bootmagic.c index 7649a197..9e734db5 100644 --- a/common/bootmagic.c +++ b/common/bootmagic.c @@ -9,6 +9,7 @@ #include "action_layer.h" #include "eeconfig.h" #include "keymap_in_eeprom.h" +#include "ledmap_in_eeprom.h" #include "bootmagic.h" @@ -36,6 +37,9 @@ void bootmagic(void) eeconfig_init(); #ifdef KEYMAP_IN_EEPROM_ENABLE write_keymap_to_eeprom(); +#endif +#ifdef LEDMAP_IN_EEPROM_ENABLE + write_ledmap_to_eeprom(); #endif } diff --git a/common/keyboard.c b/common/keyboard.c index c7793eec..1fedc8c8 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -36,6 +36,8 @@ along with this program. If not, see . #else #include "breathing_led.h" #endif +#include "ledmap.h" +#include "ledmap_in_eeprom.h" #include "keymap_in_eeprom.h" #ifdef MOUSEKEY_ENABLE # include "mousekey.h" @@ -82,6 +84,13 @@ void keyboard_init(void) bootmagic(); #endif +#ifdef LEDMAP_ENABLE +#ifdef LEDMAP_IN_EEPROM_ENABLE + ledmap_in_eeprom_init(); +#endif + ledmap_init(); +#endif + #ifdef BACKLIGHT_ENABLE backlight_init(); #endif diff --git a/common/led.h b/common/led.h index 402a247b..f72d5dc7 100644 --- a/common/led.h +++ b/common/led.h @@ -19,6 +19,32 @@ along with this program. If not, see . #define LED_H #include "stdint.h" +#ifndef LED_COUNT +#define LED_COUNT 1 +#endif + +#if (LED_COUNT <= 8) +typedef uint8_t led_pack_t; +#elif (LED_COUNT <= 16) +typedef uint16_t led_pack_t; +#elif (LED_COUNT <= 32) +typedef uint32_t led_pack_t; +#else +#error "LED_COUNT: invalid value" +#endif + +#if (LED_COUNT <= 16) +#define LED_BIT(i) (1U<<(i)) +#elif (LED_COUNT <= 32) +#define LED_BIT(i) (1UL<<(i)) +#else +#error "LED_COUNT: invalid value" +#endif + +#define LED_BIT_SET(x, i) ((x) |= LED_BIT(i)) +#define LED_BIT_CLEAR(x, i) ((x) &= ~LED_BIT(i)) +#define LED_BIT_XOR(x, i) ((x) ^= LED_BIT(i)) +#define LED_BIT_IS_SET(x, i) ((x) & LED_BIT(i)) /* keyboard LEDs */ #define USB_LED_NUM_LOCK 0 diff --git a/common/ledmap.c b/common/ledmap.c new file mode 100644 index 00000000..113db621 --- /dev/null +++ b/common/ledmap.c @@ -0,0 +1,131 @@ +#include "ledmap.h" +#include "ledmap_in_eeprom.h" +#include "led.h" +#include "softpwm_led.h" +#include "action_layer.h" +#include "debug.h" + +static led_state_t led_state_last = 0; +static led_binding_t usb_led_binding = 0; +static led_binding_t default_layer_binding = 0; +static led_binding_t layer_binding = 0; +static led_binding_t backlight_binding = 0; + +static void update_led_state(led_state_t state); + +void ledmap_init(void) +{ + for (uint8_t i = 0; i < LED_COUNT; i++) { + uint8_t code = ledmap_get_code(i); + if (code & LEDMAP_BACKLIGHT) { + LED_BIT_SET(backlight_binding, i); + } + code &= LEDMAP_MASK; + if (code >= LEDMAP_DEFAULT_LAYER_0 && code <= LEDMAP_DEFAULT_LAYER_31) { + LED_BIT_SET(default_layer_binding, i); + } + else if (code >= LEDMAP_LAYER_0 && code <= LEDMAP_LAYER_31) { + LED_BIT_SET(layer_binding, i); + } + else if (code >= LEDMAP_NUM_LOCK && code <= LEDMAP_KANA) { + LED_BIT_SET(usb_led_binding, i); + } + } + ledmap_led_init(); +} + +void led_set(uint8_t usb_led) +{ + if (usb_led_binding) { + led_state_t led_state = led_state_last; + for (uint8_t i = 0; i < LED_COUNT; i++) { + if (usb_led_binding & LED_BIT(i)) { + uint8_t code = ledmap_get_code(i) & LEDMAP_MASK; + for (uint8_t j = USB_LED_NUM_LOCK; j <= USB_LED_KANA; j++) { + if (code - LEDMAP_NUM_LOCK == j) { + (usb_led & (1 << j)) ? LED_BIT_SET(led_state, i) : LED_BIT_CLEAR(led_state, i); + } + } + } + } + update_led_state(led_state); + } +} + +#ifndef NO_ACTION_LAYER +void default_layer_state_change(uint32_t state) +{ + if (default_layer_binding) { + led_state_t led_state = led_state_last; + for (uint8_t i = 0; i < LED_COUNT; i++) { + if (default_layer_binding & LED_BIT(i)) { + uint8_t code = ledmap_get_code(i) & LEDMAP_MASK; + (state & (1UL << (code - LEDMAP_DEFAULT_LAYER_0))) ? LED_BIT_SET(led_state, i) : LED_BIT_CLEAR(led_state, i); + } + } + update_led_state(led_state); + } +} + +void layer_state_change(uint32_t state) +{ + if (layer_binding) { + led_state_t led_state = led_state_last; + for (uint8_t i = 0; i < LED_COUNT; i++) { + if (layer_binding & LED_BIT(i)) { + uint8_t code = ledmap_get_code(i) & LEDMAP_MASK; + (state & (1UL << (code - LEDMAP_LAYER_0))) ? LED_BIT_SET(led_state, i) : LED_BIT_CLEAR(led_state, i); + } + } + update_led_state(led_state); + } +} +#endif + +#ifdef SOFTPWM_LED_ENABLE +void softpwm_led_on(uint8_t index) +{ + if (backlight_binding & LED_BIT(index)) { + ledmap_led_on(index); + } +} + +void softpwm_led_off(uint8_t index) +{ + if (backlight_binding & LED_BIT(index)) { + ledmap_led_off(index); + } +} + +void softpwm_led_state_change(uint8_t state) +{ + if (state) { + } + else { + led_state_t led_state = led_state_last; + led_state_last &= ~(backlight_binding); + update_led_state(led_state); + } +} +#endif + +void update_led_state(led_state_t state) +{ + uint8_t diff = led_state_last ^ state; + if (diff) { + for (uint8_t i = 0; i < LED_COUNT; i++) { + if (softpwm_led_get_state() && (backlight_binding & LED_BIT(i))) { + continue; + } + if (diff & LED_BIT(i)) { + if (state & LED_BIT(i)) { + ledmap_led_on(i); + } + else { + ledmap_led_off(i); + } + } + } + led_state_last = state; + } +} diff --git a/common/ledmap.h b/common/ledmap.h new file mode 100644 index 00000000..9a6754f3 --- /dev/null +++ b/common/ledmap.h @@ -0,0 +1,53 @@ +#ifndef LEDMAP_H +#define LEDMAP_H + +#include "stdint.h" +#include "stdbool.h" +#include "led.h" + +typedef led_pack_t led_state_t; +typedef led_pack_t led_binding_t; + +typedef enum { + LEDMAP_NO = 0, + LEDMAP_DEFAULT_LAYER_0, + LEDMAP_DEFAULT_LAYER_31 = LEDMAP_DEFAULT_LAYER_0 + 31, + LEDMAP_LAYER_0, + LEDMAP_LAYER_31 = LEDMAP_LAYER_0 + 31, + LEDMAP_NUM_LOCK, + LEDMAP_CAPS_LOCK, + LEDMAP_SCROLL_LOCK, + LEDMAP_COMPOSE, + LEDMAP_KANA, + LEDMAP_BACKLIGHT = 0x80 +} ledmap_code_t; + +#define LEDMAP_MASK 0x7F + +typedef union { + uint8_t raw; + struct { + uint8_t binding : 7; + bool backlight : 1; + }; +} ledmap_t; + +#define LEDMAP_DEFAULT_LAYER(x) (LEDMAP_DEFAULT_LAYER_0 + x) +#define LEDMAP_LAYER(x) (LEDMAP_LAYER_0 + x) + +void ledmap_init(void); + +#ifdef LEDMAP_ENABLE +uint8_t ledmap_get_code(uint8_t index); +void ledmap_led_init(void); +void ledmap_led_on(uint8_t index); +void ledmap_led_off(uint8_t index); +#else +#define ledmaps +#define ledmap_get() +#define ledmap_led_init() +#define ledmap_led_on() +#define ledmap_led_off() +#endif + +#endif diff --git a/common/ledmap_in_eeprom.c b/common/ledmap_in_eeprom.c new file mode 100644 index 00000000..9876fc72 --- /dev/null +++ b/common/ledmap_in_eeprom.c @@ -0,0 +1,36 @@ +#include +#include +#include "ledmap.h" +#include "ledmap_in_eeprom.h" + +#ifdef LEDMAP_IN_EEPROM_ENABLE + +#undef ledmap_get_code + +static uint8_t ledmap[LED_COUNT]; + +void ledmap_in_eeprom_init(void) +{ + for (uint8_t i = 0; i < LED_COUNT; i++) { + ledmap[i] = eeprom_read_byte(EECONFIG_LEDMAP + i); + //ledmap[i] = LEDMAP_UNCONFIGURED; + if (ledmap[i] == LEDMAP_UNCONFIGURED) { + ledmap[i] = ledmap_get_code(i); + eeprom_write_byte(EECONFIG_LEDMAP + i, ledmap[i]); + } + } +} + +void write_ledmap_to_eeprom(void) +{ + for (uint8_t i = 0; i < LED_COUNT; i++) { + eeprom_write_byte(EECONFIG_LEDMAP + i, ledmap_get_code(i)); + } +} + +uint8_t ledmap_in_eeprom_get_code(uint8_t i) +{ + return ledmap[i]; +} + +#endif diff --git a/common/ledmap_in_eeprom.h b/common/ledmap_in_eeprom.h new file mode 100644 index 00000000..3e6400c3 --- /dev/null +++ b/common/ledmap_in_eeprom.h @@ -0,0 +1,24 @@ +#ifndef LEDMAP_IN_EEPROM_H +#define LEDMAP_IN_EEPROM_H + +#ifndef EECONFIG_LEDMAP_IN_EEPROM +#define EECONFIG_LEDMAP_IN_EEPROM 7 +#endif + +#define EECONFIG_LEDMAP (uint8_t*)EECONFIG_LEDMAP_IN_EEPROM +#define LEDMAP_SIZE (sizeof(uint8_t) * LED_COUNT) + +#define LEDMAP_UNCONFIGURED 0xFF + +#ifdef LEDMAP_IN_EEPROM_ENABLE +#define ledmap_get_code ledmap_in_eeprom_get_code +void ledmap_in_eeprom_init(void); +void write_ledmap_to_eeprom(void); +uint8_t ledmap_in_eeprom_get_code(uint8_t index); +#else +#define ledmap_in_eeprom_init() +#define write_ledmap_to_eeprom() +#define ledmap_in_eeprom_get_code() +#endif + +#endif diff --git a/common/softpwm_led.c b/common/softpwm_led.c index e2195c2f..5fd0e80f 100644 --- a/common/softpwm_led.c +++ b/common/softpwm_led.c @@ -7,8 +7,9 @@ #define SOFTPWM_LED_FREQ 64 #define SOFTPWM_LED_TIMER_TOP F_CPU / (256 * SOFTPWM_LED_FREQ) -uint8_t softpwm_ocr = 0; -uint8_t softpwm_ocr_buff = 0; +static uint8_t softpwm_led_state = 0; +static uint8_t softpwm_led_ocr[LED_COUNT] = {0}; +static uint8_t softpwm_led_ocr_buff[LED_COUNT] = {0}; void softpwm_led_init(void) { @@ -44,10 +45,14 @@ void softpwm_led_enable(void) /* Enable Compare Match Interrupt */ #ifdef SOFTPWM_LED_TIMER3 TIMSK3 |= (1< SOFTPWM_LED_FREQ) { + if (++count > SOFTPWM_LED_FREQ) { count = 0; - step++; - if (step > breathing_led_duration) { - step = 0; - softpwm_ocr_buff = pgm_read_byte(&breathing_table[index]); - index++; + for (uint8_t i = 0; i < LED_COUNT; i++) { + if (breathing_led_state & LED_BIT(i)) { + if (++step[i] > breathing_led_duration[i]) { + step[i] = 0; + softpwm_led_ocr_buff[i] = pgm_read_byte(&breathing_table[index[i]]); + index[i]++; + } + } } } } diff --git a/common/softpwm_led.h b/common/softpwm_led.h index 5236b1df..63e5a133 100644 --- a/common/softpwm_led.h +++ b/common/softpwm_led.h @@ -1,28 +1,44 @@ #ifndef SOFTPWM_LED_H #define SOFTPWM_LED_H +#include "stdint.h" +#include "led.h" + +typedef led_pack_t led_state_t; + #ifdef SOFTPWM_LED_ENABLE void softpwm_led_init(void); void softpwm_led_enable(void); void softpwm_led_disable(void); void softpwm_led_toggle(void); -void softpwm_led_set(uint8_t val); -void softpwm_led_on(void); -void softpwm_led_off(void); +void softpwm_led_set(uint8_t index, uint8_t val); +void softpwm_led_set_all(uint8_t val); +void softpwm_led_on(uint8_t index); +void softpwm_led_off(uint8_t index); +uint8_t softpwm_led_get_state(void); +void softpwm_led_state_change(uint8_t state); #ifdef BREATHING_LED_ENABLE #define breathing_led_init() -void breathing_led_enable(void); -void breathing_led_disable(void); -void breathing_led_toggle(void); -void breathing_led_set_duration(uint8_t dur); +void breathing_led_enable(uint8_t index); +void breathing_led_enable_all(void); +void breathing_led_disable(uint8_t index); +void breathing_led_disable_all(void); +void breathing_led_toggle(uint8_t index); +void breathing_led_toggle_all(void); +void breathing_led_set_duration(uint8_t index, uint8_t dur); +void breathing_led_set_duration_all(uint8_t dur); #else #define breathing_led_init() #define breathing_led_enable() +#define breathing_led_enable_all() #define breathing_led_disable() +#define breathing_led_disable_all() #define breathing_led_toggle() +#define breathing_led_toggle_all() #define breathing_led_set_duration() +#define breathing_led_set_duration_all() #endif #else @@ -32,8 +48,11 @@ void breathing_led_set_duration(uint8_t dur); #define softpwm_led_disable() #define softpwm_led_toggle() #define softpwm_led_set() +#define softpwm_led_set_all() #define softpwm_led_on() #define softpwm_led_off() +#define softpwm_led_get_state() +#define softpwm_led_state_change() #endif