OPT_DEFS += -DNO_SUSPEND_POWER_DOWN | OPT_DEFS += -DNO_SUSPEND_POWER_DOWN | ||||
endif | endif | ||||
ifdef BREATHING_LED_ENABLE | |||||
SRC += $(COMMON_DIR)/breathing_led.c | |||||
OPT_DEFS += -DBREATHING_LED_ENABLE | |||||
endif | |||||
ifdef BACKLIGHT_ENABLE | ifdef BACKLIGHT_ENABLE | ||||
SRC += $(COMMON_DIR)/backlight.c | SRC += $(COMMON_DIR)/backlight.c | ||||
OPT_DEFS += -DBACKLIGHT_ENABLE | OPT_DEFS += -DBACKLIGHT_ENABLE |
*/ | */ | ||||
#include "backlight.h" | #include "backlight.h" | ||||
#include "breathing_led.h" | |||||
#include "eeconfig.h" | #include "eeconfig.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
void backlight_increase(void) | void backlight_increase(void) | ||||
{ | { | ||||
#ifdef BACKLIGHT_CUSTOM | |||||
#if defined(BACKLIGHT_CUSTOM) || defined(BREATHING_LED_ENABLE) | |||||
if (backlight_config.enable) { | if (backlight_config.enable) { | ||||
if (backlight_config.level < BACKLIGHT_LEVELS) { | if (backlight_config.level < BACKLIGHT_LEVELS) { | ||||
backlight_config.level++; | backlight_config.level++; | ||||
dprintf("backlight custom increase: %u\n", backlight_config.level); | dprintf("backlight custom increase: %u\n", backlight_config.level); | ||||
backlight_set(backlight_config.level); | backlight_set(backlight_config.level); | ||||
} | } | ||||
#ifdef BREATHING_LED_ENABLE | |||||
breathing_led_increase(); | |||||
#endif | |||||
#else | #else | ||||
if(backlight_config.level < BACKLIGHT_LEVELS) | if(backlight_config.level < BACKLIGHT_LEVELS) | ||||
{ | { | ||||
void backlight_decrease(void) | void backlight_decrease(void) | ||||
{ | { | ||||
#ifdef BACKLIGHT_CUSTOM | |||||
#if defined(BACKLIGHT_CUSTOM) || defined(BREATHING_LED_ENABLE) | |||||
if (backlight_config.enable) { | if (backlight_config.enable) { | ||||
if(backlight_config.level > 1) | if(backlight_config.level > 1) | ||||
{ | { | ||||
dprintf("backlight custom decrease: %u\n", backlight_config.level); | dprintf("backlight custom decrease: %u\n", backlight_config.level); | ||||
backlight_set(backlight_config.level); | backlight_set(backlight_config.level); | ||||
} | } | ||||
#ifdef BREATHING_LED_ENABLE | |||||
breathing_led_decrease(); | |||||
#endif | |||||
#else | #else | ||||
if(backlight_config.level > 0) | if(backlight_config.level > 0) | ||||
{ | { | ||||
void backlight_toggle(void) | void backlight_toggle(void) | ||||
{ | { | ||||
#ifdef BREATHING_LED_ENABLE | |||||
if (breathing_led_is_enabled()) { | |||||
breathing_led_disable(); | |||||
backlight_disable(); | |||||
return; | |||||
} | |||||
#endif | |||||
backlight_config.enable ^= 1; | backlight_config.enable ^= 1; | ||||
if (backlight_config.enable) | |||||
{ | |||||
if (backlight_config.enable) { | |||||
#if defined(BACKLIGHT_CUSTOM) || defined(BREATHING_LED_ENABLE) | |||||
backlight_enable(); | |||||
#endif | |||||
if (backlight_config.level == 0) { | if (backlight_config.level == 0) { | ||||
backlight_config.level = 1; | backlight_config.level = 1; | ||||
} | } | ||||
} | } | ||||
else { | |||||
#ifndef BREATHING_LED_ENABLE | |||||
#ifdef BACKLIGHT_CUSTOM | |||||
backlight_disable(); | |||||
#endif | |||||
#endif | |||||
} | |||||
eeconfig_write_backlight(backlight_config.raw); | eeconfig_write_backlight(backlight_config.raw); | ||||
dprintf("backlight toggle: %u\n", backlight_config.enable); | dprintf("backlight toggle: %u\n", backlight_config.enable); | ||||
backlight_set(backlight_config.enable ? backlight_config.level : 0); | backlight_set(backlight_config.enable ? backlight_config.level : 0); | ||||
#ifdef BREATHING_LED_ENABLE | |||||
if (!backlight_config.enable) { | |||||
breathing_led_enable(); | |||||
} | |||||
#endif | |||||
} | } | ||||
void backlight_step(void) | void backlight_step(void) |
void backlight_toggle(void); | void backlight_toggle(void); | ||||
void backlight_step(void); | void backlight_step(void); | ||||
void backlight_enable(void); | |||||
void backlight_disable(void); | |||||
void backlight_set(uint8_t level); | void backlight_set(uint8_t level); | ||||
void backlight_set_raw(uint8_t raw); | |||||
#endif | #endif |
#include <avr/io.h> | |||||
#include <avr/interrupt.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "led.h" | |||||
#include "breathing_led.h" | |||||
#include "backlight.h" | |||||
#include "debug.h" | |||||
#define BREATHING_LED_TIMER_TOP F_CPU/64 | |||||
breathing_led_config_t breathing_led_config; | |||||
void breathing_led_init(void) | |||||
{ | |||||
/* Timer3 setup */ | |||||
/* CTC mode */ | |||||
TCCR3B |= _BV(WGM12); | |||||
/* Clock selelct: clk/1 */ | |||||
TCCR3B |= _BV(CS10); | |||||
/* Set TOP value */ | |||||
uint8_t sreg = SREG; | |||||
cli(); | |||||
OCR3AH = (BREATHING_LED_TIMER_TOP>>8)&0xff; | |||||
OCR3AL = BREATHING_LED_TIMER_TOP&0xff; | |||||
SREG = sreg; | |||||
} | |||||
bool breathing_led_is_enabled(void) | |||||
{ | |||||
return breathing_led_config.enable; | |||||
} | |||||
void breathing_led_enable(void) | |||||
{ | |||||
/* Enable Compare Match Interrupt */ | |||||
TIMSK3 |= _BV(OCIE3A); | |||||
breathing_led_config.enable = true; | |||||
dprintf("breathing led on: %u\n", breathing_led_config.enable); | |||||
eeconfig_write_breathing_led(breathing_led_config.raw); | |||||
} | |||||
void breathing_led_disable(void) | |||||
{ | |||||
/* Disable Compare Match Interrupt */ | |||||
TIMSK3 &= ~_BV(OCIE3A); | |||||
breathing_led_config.enable = false; | |||||
dprintf("breathing led off: %u\n", breathing_led_config.enable); | |||||
eeconfig_write_breathing_led(breathing_led_config.raw); | |||||
} | |||||
void breathing_led_toggle(void) | |||||
{ | |||||
/* Disable Compare Match Interrupt */ | |||||
TIMSK3 ^= _BV(OCIE3A); | |||||
breathing_led_config.enable ^= 1; | |||||
dprintf("breathing led toggle: %u\n", breathing_led_config.enable); | |||||
eeconfig_write_breathing_led(breathing_led_config.raw); | |||||
} | |||||
void breathing_led_increase(void) | |||||
{ | |||||
if (breathing_led_config.enable) { | |||||
if (breathing_led_config.level < BREATHING_LED_LEVELS) { | |||||
breathing_led_config.level++; | |||||
eeconfig_write_breathing_led(breathing_led_config.raw); | |||||
} | |||||
dprintf("breathing led speed increase: %u\n", breathing_led_config.level); | |||||
} | |||||
} | |||||
void breathing_led_decrease(void) | |||||
{ | |||||
if (breathing_led_config.enable) { | |||||
if (breathing_led_config.level > 0) | |||||
{ | |||||
breathing_led_config.level--; | |||||
eeconfig_write_breathing_led(breathing_led_config.raw); | |||||
} | |||||
dprintf("breathing led speed decrease: %u\n", breathing_led_config.level); | |||||
} | |||||
} | |||||
/* Breathing LED brighness(PWM On period) table | |||||
* (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle | |||||
* | |||||
* http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63 | |||||
* (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i } | |||||
*/ | |||||
static const uint8_t breathing_table[64] PROGMEM = { | |||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, | |||||
15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, | |||||
255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, | |||||
15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |||||
}; | |||||
ISR(TIMER3_COMPA_vect) | |||||
{ | |||||
uint8_t index = 0; | |||||
uint8_t step = 0; | |||||
step++; | |||||
if (step >= BREATHING_LED_LEVELS - breathing_led_config.level) { | |||||
step = 0; | |||||
index++; | |||||
backlight_set_raw(pgm_read_byte(&breathing_table[index])); | |||||
} | |||||
} |
#ifndef BREATHING_LED_H | |||||
#define BREATHING_LED_H | |||||
#ifdef BREATHING_LED_ENABLE | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#ifndef BREATHING_LED_LEVEL | |||||
#define BREATHING_LED_LEVEL 1 | |||||
#endif | |||||
typedef union { | |||||
uint8_t raw; | |||||
struct { | |||||
bool enable:1; | |||||
uint8_t level:7; | |||||
}; | |||||
} breathing_led_config_t; | |||||
void breathing_led_init(void); | |||||
bool breathing_led_is_enabled(void); | |||||
void breathing_led_enable(void); | |||||
void breathing_led_disable(void); | |||||
void breathing_led_toggle(void); | |||||
void breathing_led_increase(void); | |||||
void breathing_led_decrease(void); | |||||
#else | |||||
#define breathing_led_init() | |||||
#define breathing_led_enable() | |||||
#define breathing_led_disable() | |||||
#define breathing_led_toggle() | |||||
#endif | |||||
#endif |
#ifdef BACKLIGHT_ENABLE | #ifdef BACKLIGHT_ENABLE | ||||
eeprom_write_byte(EECONFIG_BACKLIGHT, 0); | eeprom_write_byte(EECONFIG_BACKLIGHT, 0); | ||||
#endif | #endif | ||||
#ifdef BREATHING_LED_ENABLE | |||||
eeprom_write_byte(EECONFIG_BREATHING_LED, 0); | |||||
#endif | |||||
#ifdef KEYMAP_EX_ENABLE | #ifdef KEYMAP_EX_ENABLE | ||||
keymap_ex_init(); | keymap_ex_init(); | ||||
#endif | #endif | ||||
uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); } | uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); } | ||||
void eeconfig_write_backlight(uint8_t val) { eeprom_write_byte(EECONFIG_BACKLIGHT, val); } | void eeconfig_write_backlight(uint8_t val) { eeprom_write_byte(EECONFIG_BACKLIGHT, val); } | ||||
#endif | #endif | ||||
#ifdef BREATHING_LED_ENABLE | |||||
uint8_t eeconfig_read_breathing_led(void) { return eeprom_read_byte(EECONFIG_BREATHING_LED); } | |||||
void eeconfig_write_breathing_led(uint8_t val) { eeprom_write_byte(EECONFIG_BREATHING_LED, val); } | |||||
#endif |
#define EECONFIG_KEYMAP (uint8_t *)4 | #define EECONFIG_KEYMAP (uint8_t *)4 | ||||
#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5 | #define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5 | ||||
#define EECONFIG_BACKLIGHT (uint8_t *)6 | #define EECONFIG_BACKLIGHT (uint8_t *)6 | ||||
#define EECONFIG_BREATHING_LED (uint8_t *)7 | |||||
/* debug bit */ | /* debug bit */ | ||||
void eeconfig_write_backlight(uint8_t val); | void eeconfig_write_backlight(uint8_t val); | ||||
#endif | #endif | ||||
#ifdef BREATHING_LED_ENABLE | |||||
uint8_t eeconfig_read_breathing_led(void); | |||||
void eeconfig_write_breathing_led(uint8_t val); | |||||
#endif | |||||
#endif | #endif |
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality | BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality | ||||
KEYMAP_EX_ENABLE = yes # External keymap in eeprom | KEYMAP_EX_ENABLE = yes # External keymap in eeprom | ||||
KEYMAP_SECTION_ENABLE = yes # Fixed address keymap for keymap editor | KEYMAP_SECTION_ENABLE = yes # Fixed address keymap for keymap editor | ||||
#LED_MATRIX_ENABLE = yes | |||||
BREATHING_LED_ENABLE = yes # Enable breathing backlight | |||||
# Optimize size but this may cause error "relocation truncated to fit" | # Optimize size but this may cause error "relocation truncated to fit" | ||||
#EXTRALDFLAGS = -Wl,--relax | #EXTRALDFLAGS = -Wl,--relax |
#include <avr/pgmspace.h> | #include <avr/pgmspace.h> | ||||
#include "backlight.h" | #include "backlight.h" | ||||
#if defined(GH60_REV_CHN) | |||||
static const uint8_t backlight_table[] PROGMEM = { | static const uint8_t backlight_table[] PROGMEM = { | ||||
0, 16, 128, 255 | 0, 16, 128, 255 | ||||
}; | }; | ||||
/* Backlight pin configuration | /* Backlight pin configuration | ||||
* PWM: PB7 | * PWM: PB7 | ||||
*/ | */ | ||||
void backlight_set(uint8_t level) | |||||
void backlight_enable(void) | |||||
{ | { | ||||
if (level > 0) { | |||||
// Turn on PWM | |||||
cli(); | |||||
DDRB |= (1<<PB6); | |||||
TCCR1A |= ( (1<<WGM10) | (1<<COM1B1) ); | |||||
TCCR1B |= ( (1<<CS11) | (1<<CS10) ); | |||||
sei(); | |||||
// Set PWM | |||||
OCR1B = pgm_read_byte(&backlight_table[level]); | |||||
} | |||||
else { | |||||
// Turn off PWM | |||||
cli(); | |||||
DDRB &= ~(1<<PB6); | |||||
TCCR1A &= ~( (1<<WGM10) | (1<<COM1B1) ); | |||||
TCCR1B &= ~( (1<<CS11) | (1<<CS10) ); | |||||
sei(); | |||||
// Set PWM | |||||
OCR1B = 0; | |||||
} | |||||
#if defined(GH60_REV_CHN) | |||||
// Turn on PWM | |||||
cli(); | |||||
DDRB |= (1<<PB6); | |||||
TCCR1A |= ( (1<<WGM10) | (1<<COM1B1) ); | |||||
TCCR1B |= ( (1<<CS11) | (1<<CS10) ); | |||||
sei(); | |||||
#else | |||||
DDRF |= (1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||||
PORTF |= (1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||||
cli(); | |||||
TCCR1A |= (1<<WGM10); | |||||
TCCR1B |= ((1<<CS11) | (1<<CS10)); | |||||
TIMSK1 |= ((1<<OCIE1A) | (1<<TOIE1)); | |||||
TIFR1 |= (1<<TOV1); | |||||
sei(); | |||||
#endif | |||||
} | } | ||||
#elif defined(GH60_REV_CNY) | |||||
static const uint8_t backlight_table[] PROGMEM = { | |||||
0, 16, 128, 255 | |||||
}; | |||||
void backlight_set(uint8_t level) | |||||
void backlight_disable(void) | |||||
{ | { | ||||
#ifdef LED_MATRIX_ENABLE | |||||
if (level > 0) { | |||||
led_matrix_disable(); | |||||
for (uint8_t row = 0; row < LED_MATRIX_ROWS; row++) { | |||||
for (uint8_t col = 0; col < LED_MATRIX_COLS; col++) { | |||||
led_matrix_set_value(row, col, pgm_read_byte(&backlight_table[level])); | |||||
} | |||||
} | |||||
led_matrix_enable(); | |||||
} | |||||
else { | |||||
led_matrix_disable(); | |||||
} | |||||
#if defined(GH60_REV_CHN) | |||||
// Turn off PWM | |||||
cli(); | |||||
DDRB &= ~(1<<PB6); | |||||
TCCR1A &= ~( (1<<WGM10) | (1<<COM1B1) ); | |||||
TCCR1B &= ~( (1<<CS11) | (1<<CS10) ); | |||||
sei(); | |||||
OCR1A = 0; | |||||
#else | |||||
DDRF &= ~(1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||||
cli(); | |||||
TCCR1A &= ~(1<<WGM10); | |||||
TCCR1B &= ~((1<<CS11) | (1<<CS10)); | |||||
TIMSK1 |= ((1<<OCIE1A) | (1<<TOIE1)); | |||||
TIFR1 |= (1<<TOV1); | |||||
sei(); | |||||
OCR1A = 0; | |||||
#endif | #endif | ||||
} | } | ||||
#else | |||||
static const uint8_t backlight_table[] PROGMEM = { | |||||
0, 16, 128, 255 | |||||
}; | |||||
void backlight_set(uint8_t level) | void backlight_set(uint8_t level) | ||||
{ | { | ||||
if (level > 0) { | if (level > 0) { | ||||
DDRF |= (1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||||
PORTF |= (1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||||
cli(); | |||||
TCCR1A |= (1<<WGM10); | |||||
TCCR1B |= ((1<<CS11) | (1<<CS10)); | |||||
TIMSK1 |= ((1<<OCIE1A) | (1<<TOIE1)); | |||||
TIFR1 |= (1<<TOV1); | |||||
sei(); | |||||
OCR1A = pgm_read_byte(&backlight_table[level]); | |||||
} | |||||
else { | |||||
DDRF &= ~(1<<PF7 | 1<<PF6 | 1<<PF5 | 1<<PF4); | |||||
cli(); | |||||
TCCR1A &= ~(1<<WGM10); | |||||
TCCR1B &= ~((1<<CS11) | (1<<CS10)); | |||||
TIMSK1 |= ((1<<OCIE1A) | (1<<TOIE1)); | |||||
TIFR1 |= (1<<TOV1); | |||||
sei(); | |||||
OCR1A = 0; | |||||
backlight_set_raw(pgm_read_byte(&backlight_table[level])); | |||||
} | } | ||||
} | } | ||||
void backlight_set_raw(uint8_t raw) | |||||
{ | |||||
OCR1A = raw; | |||||
} | |||||
#ifndef GH60_REV_CHN | |||||
ISR(TIMER1_COMPA_vect) | ISR(TIMER1_COMPA_vect) | ||||
{ | { | ||||
// LED off | // LED off |
/* number of backlight levels */ | /* number of backlight levels */ | ||||
#define BACKLIGHT_LEVELS 3 | #define BACKLIGHT_LEVELS 3 | ||||
#define BREATHING_LED_LEVELS 4 | |||||
#ifdef GH60_REV_CNY | #ifdef GH60_REV_CNY | ||||
# define LED_MATRIX_ROWS 6 | # define LED_MATRIX_ROWS 6 |