Переглянути джерело

fantastic60: Implement improved controlling of RGB LED

fantastic60
Kai Ryu 9 роки тому
джерело
коміт
49b426a378

+ 5
- 5
keyboard/fantastic60/Makefile Переглянути файл

@@ -52,8 +52,8 @@ SRC = keymap_common.c \
matrix.c \
led.c \
backlight.c \
ledmap.c \
fantastic.c
shift_register.c \
rgb.c

ifdef KEYMAP
SRC := keymap_$(KEYMAP).c $(SRC)
@@ -133,13 +133,13 @@ USB_6KRO_ENABLE = yes # USB 6key Rollover
PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support
PS2_USE_BUSYWAIT = yes
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
KEYMAP_IN_EEPROM_ENABLE = yes # Read keymap from eeprom
#KEYMAP_IN_EEPROM_ENABLE = yes # Read keymap from eeprom
#KEYMAP_SECTION_ENABLE = yes # Fixed address keymap for keymap editor
SOFTPWM_LED_ENABLE = yes # Enable SoftPWM to drive backlight
#FADING_LED_ENABLE = yes # Enable fading backlight
BREATHING_LED_ENABLE = yes # Enable breathing backlight
LEDMAP_ENABLE = yes # Enable LED mapping
LEDMAP_IN_EEPROM_ENABLE = yes # Read LED mapping from eeprom
#LEDMAP_ENABLE = yes # Enable LED mapping
#LEDMAP_IN_EEPROM_ENABLE = yes # Read LED mapping from eeprom


# Optimize size but this may cause error "relocation truncated to fit"

+ 88
- 46
keyboard/fantastic60/backlight.c Переглянути файл

@@ -24,98 +24,119 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.

#ifdef BACKLIGHT_ENABLE

static uint8_t backlight_mode;
#define BACKLIGHT 0

extern backlight_config_t backlight_config;
static const uint8_t backlight_table[] PROGMEM = {
0, 16, 128, 255
};

void backlight_enable(void);
void backlight_disable(void);

/* Backlight pin configuration
* PWM: PF7
*/
void backlight_enable(void)
{
DDRF |= (1<<PF7);
softpwm_led_enable();
}

void backlight_disable(void)
{
DDRF &= ~(1<<PF7);
softpwm_led_disable();
}

void backlight_set(uint8_t level)
{
softpwm_led_enable();
#ifdef BREATHING_LED_ENABLE
switch (level) {
case 1:
case 2:
case 3:
backlight_enable();
#ifdef FADING_LED_ENABLE
fading_led_disable_all();
fading_led_disable(BACKLIGHT);
#endif
breathing_led_disable_all();
softpwm_led_set_all(pgm_read_byte(&backlight_table[level]));
breathing_led_disable(BACKLIGHT);
softpwm_led_set(BACKLIGHT, pgm_read_byte(&backlight_table[level]));
break;
case 4:
case 5:
case 6:
backlight_enable();
#ifdef FADING_LED_ENABLE
fading_led_disable_all();
fading_led_disable(BACKLIGHT);
#endif
breathing_led_enable_all();
breathing_led_enable(BACKLIGHT);
breathing_led_set_duration(6 - level);
break;
#ifdef FADING_LED_ENABLE
case 7:
backlight_enable();
fading_led_enable_all();
breathing_led_disable_all();
fading_led_set_direction(FADING_LED_FADE_IN);
fading_led_enable(BACKLIGHT);
breathing_led_disable(BACKLIGHT);
fading_led_set_direction(BACKLIGHT, FADING_LED_FADE_IN);
fading_led_set_duration(3);
case 8:
backlight_enable();
fading_led_enable_all();
breathing_led_disable_all();
fading_led_set_direction(FADING_LED_FADE_OUT);
fading_led_enable(BACKLIGHT);
breathing_led_disable(BACKLIGHT);
fading_led_set_direction(BACKLIGHT, FADING_LED_FADE_OUT);
fading_led_set_duration(3);
#endif
case 0:
default:
#ifdef FADING_LED_ENABLE
fading_led_disable_all();
fading_led_disable(BACKLIGHT);
#endif
breathing_led_disable_all();
backlight_disable();
breathing_led_disable(BACKLIGHT);
softpwm_led_set(BACKLIGHT, 0);
break;
}
#else
if (level > 0) {
backlight_enable();
softpwm_led_set_all(pgm_read_byte(&backlight_table[level]));
softpwm_led_set(BACKLIGHT, pgm_read_byte(&backlight_table[level]));
}
else {
backlight_disable();
softpwm_led_set(BACKLIGHT, 0);
}
#endif
}

#ifndef LEDMAP_ENABLE
#ifdef SOFTPWM_LED_ENABLE
/* Backlight pin configuration
* Backlight: PF7
* RGB R: PE2
* RGB G: PC6
* RGB B: PC7
*/
void softpwm_led_init()
{
DDRF |= (1<<PF7);
PORTF |= (1<<PF7);
DDRE |= (1<<PE2);
PORTE |= (1<<PE2);
DDRC |= (1<<PC7 | 1<<PC6);
PORTC |= (1<<PC7 | 1<<PC6);
}

void softpwm_led_on(uint8_t index)
{
PORTF |= (1<<PF7);
switch (index) {
case 0:
PORTF &= ~(1<<PF7);
break;
case 1:
PORTE &= ~(1<<PE2);
break;
case 2:
PORTC &= ~(1<<PC6);
break;
case 3:
PORTC &= ~(1<<PC7);
break;
}
}

void softpwm_led_off(uint8_t index)
{
PORTF &= ~(1<<PF7);
switch (index) {
case 0:
PORTF |= (1<<PF7);
break;
case 1:
PORTE |= (1<<PE2);
break;
case 2:
PORTC |= (1<<PC6);
break;
case 3:
PORTC |= (1<<PC7);
break;
}
}
#endif
#endif
@@ -123,17 +144,38 @@ void softpwm_led_off(uint8_t index)
#ifdef FADING_LED_ENABLE
void action_keyevent(keyevent_t event)
{
if (backlight_mode == 7) {
if (backlight_config.level == 7) {
if (event.pressed) {
softpwm_led_decrease_all(32);
fading_led_set_delay(BACKLIGHT, 64);
softpwm_led_decrease(BACKLIGHT, 32);
}
}
if (backlight_mode == 8) {
if (backlight_config.level == 8) {
if (event.pressed) {
softpwm_led_increase_all(32);
fading_led_set_delay(BACKLIGHT, 64);
softpwm_led_increase(BACKLIGHT, 32);
}
}
}
#endif

#ifdef CUSTOM_LED_ENABLE
void softpwm_led_custom(void)
{
rgb_fading();
}

#ifdef FADING_LED_ENABLE
void fading_led_custom(uint8_t *value)
{
rgb_set_brightness(value[0]);
}
#endif

void breathing_led_custom(uint8_t *value)
{
rgb_set_brightness(value[0]);
}
#endif

#endif

+ 4
- 2
keyboard/fantastic60/config.h Переглянути файл

@@ -52,10 +52,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#else
#define BACKLIGHT_LEVELS 3
#endif

#define BACKLIGHT_CUSTOM
#define CUSTOM_LED_ENABLE

/* number of leds */
#define LED_COUNT 3
#define LED_COUNT 5

/* ledmap in eeprom */
#define EECONFIG_LEDMAP_IN_EEPROM 8
@@ -98,7 +100,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
#define NO_ACTION_ONESHOT
//#define NO_ACTION_ONESHOT
#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION


+ 1
- 9
keyboard/fantastic60/keymap_common.h Переглянути файл

@@ -17,18 +17,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KEYMAP_COMMON_H
#define KEYMAP_COMMON_H

#include <stdint.h>
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "keycode.h"
#include "action.h"
#include "action_macro.h"
#include "report.h"
#include "host.h"
#include "print.h"
#include "debug.h"
#include "keymap.h"
#include "keymap_in_eeprom.h"
#include "keymap_common.h"


extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS];

+ 101
- 2
keyboard/fantastic60/keymap_default.c Переглянути файл

@@ -1,4 +1,27 @@
/*
Copyright 2015 Kai Ryu <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <avr/pgmspace.h>
#include "keycode.h"
#include "action.h"
#include "keymap_common.h"
#include "rgb.h"
#include "debug.h"


// Default
#ifdef KEYMAP_SECTION_ENABLE
@@ -16,7 +39,7 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
* |-----------------------------------------------------------|
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |
* |-----------------------------------------------------------|
* |Ctrl|Gui |Alt | Space |Alt |Gui |App |Ctrl|
* |Ctrl|Gui |Alt | Space |Fn0 |Gui |App |Ctrl|
* `-----------------------------------------------------------'
*/
KEYMAP_ANSI(
@@ -24,7 +47,37 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, \
LSFT, Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL),
LCTL,LGUI,LALT, SPC, FN0, RGUI,APP, RCTL),
/* Keymap 1: Fn Layer
* ,-----------------------------------------------------------.
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete |
* |-----------------------------------------------------------|
* | | |Up |Fn4|Fn5|Fn6|Cal| |Ins| |Psc|Slk|Pau| |
* |-----------------------------------------------------------|
* | |Lef|Dow|Rig|Fn7|Fn8| | | | |Hom|PgU| |
* |-----------------------------------------------------------|
* | |Fn2|Fn1|Fn3|Fn9|F10|VoD|VoU|Mut|End|PgD| |
* |-----------------------------------------------------------|
* | | | | | | | | |
* `-----------------------------------------------------------'
*/
KEYMAP_ANSI(
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, \
TRNS,TRNS,UP, FN4, FN5, FN6, CALC,TRNS,INS, TRNS,PSCR,SLCK,PAUS,TRNS, \
TRNS,LEFT,DOWN,RGHT,FN7, FN8, TRNS,TRNS,TRNS,TRNS,HOME,PGUP, TRNS, \
TRNS, FN2, FN1, FN3, FN9, FN10,VOLD,VOLU,MUTE,END, PGDN, TRNS, \
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS),
};

enum function_id {
AF_RGB_TOGGLE = 0,
AF_RGB_ON,
AF_RGB_OFF,
AF_RGB_DECREASE,
AF_RGB_INCREASE,
AF_RGB_STEP,
AF_RGB_COLOR_DECREASE,
AF_RGB_COLOR_INCREASE
};

/*
@@ -35,6 +88,17 @@ const uint16_t fn_actions[FN_ACTIONS_COUNT] __attribute__ ((section (".keymap.fn
#else
const uint16_t fn_actions[] PROGMEM = {
#endif
[0] = ACTION_LAYER_MOMENTARY(1),
[1] = ACTION_BACKLIGHT_TOGGLE(),
[2] = ACTION_BACKLIGHT_DECREASE(),
[3] = ACTION_BACKLIGHT_INCREASE(),
[4] = ACTION_FUNCTION(AF_RGB_STEP),
[5] = ACTION_FUNCTION_OPT(AF_RGB_COLOR_DECREASE, RGB_R),
[6] = ACTION_FUNCTION_OPT(AF_RGB_COLOR_INCREASE, RGB_R),
[7] = ACTION_FUNCTION_OPT(AF_RGB_COLOR_DECREASE, RGB_G),
[8] = ACTION_FUNCTION_OPT(AF_RGB_COLOR_INCREASE, RGB_G),
[9] = ACTION_FUNCTION_OPT(AF_RGB_COLOR_DECREASE, RGB_B),
[10] = ACTION_FUNCTION_OPT(AF_RGB_COLOR_INCREASE, RGB_B),
};

#ifdef KEYMAP_IN_EEPROM_ENABLE
@@ -46,3 +110,38 @@ uint16_t fn_actions_count(void) {
return sizeof(fn_actions) / sizeof(fn_actions[0]);
}
#endif

void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
if (record->event.pressed) {
switch (id) {
case AF_RGB_TOGGLE:
rgb_toggle();
break;
case AF_RGB_ON:
rgb_on();
break;
case AF_RGB_OFF:
rgb_off();
break;
case AF_RGB_DECREASE:
rgb_decrease();
break;
case AF_RGB_INCREASE:
rgb_increase();
break;
case AF_RGB_STEP:
rgb_step();
dprintf("RGB Step\n");
break;
case AF_RGB_COLOR_INCREASE:
rgb_color_increase(opt);
dprintf("RGB Increase %d\n", opt);
break;
case AF_RGB_COLOR_DECREASE:
rgb_color_decrease(opt);
dprintf("RGB Decrease %d\n", opt);
break;
}
}
}

+ 4
- 0
keyboard/fantastic60/matrix.c Переглянути файл

@@ -29,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "ps2.h"
#endif
#include "matrix.h"
#include "rgb.h"

#ifndef DEBOUNCE
# define DEBOUNCE 5
@@ -66,6 +67,9 @@ void matrix_init(void)
MCUCR = (1<<JTD);
MCUCR = (1<<JTD);

// initialize RGB LED
rgb_init();

// initialize row and col
unselect_rows();
init_cols();

+ 233
- 0
keyboard/fantastic60/rgb.c Переглянути файл

@@ -0,0 +1,233 @@
/*
Copyright 2015 Kai Ryu <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include "softpwm_led.h"
#include "backlight.h"
#include "shift_register.h"
#include "rgb.h"

volatile static uint8_t rgb_fading_enable = 0;
static rgb_config_t rgb_config;
static rgb_color_t rgb_color;
static uint16_t rgb_hue = 0;
const uint8_t rgb_saturation = 255;
static uint8_t rgb_brightness = 16;

extern backlight_config_t backlight_config;
extern uint8_t backlight_brightness;

static void rgb_write_config(void);
static void rgb_read_config(void);
static void rgb_write_color(void);
static void rgb_read_color(void);
static void rgb_set_level(uint8_t level);
static void rgb_refresh(rgb_color_t *rgb);
static void hsb_to_rgb(uint16_t hue, uint8_t saturation, uint8_t brightness, rgb_color_t *rgb);

void rgb_init(void)
{
shift_register_init();
shift_register_write_word(0xFFFF);
rgb_read_config();
if (rgb_config.raw == RGB_UNCONFIGURED) {
rgb_config.enable = 0;
rgb_config.level = RGB_OFF;
rgb_write_config();
}
if (rgb_config.enable) {
rgb_set_level(rgb_config.level);
}
}

void rgb_read_config(void)
{
rgb_config.raw = eeprom_read_byte(EECONFIG_RGB_CONFIG);
}

void rgb_write_config(void)
{
eeprom_write_byte(EECONFIG_RGB_CONFIG, rgb_config.raw);
}

void rgb_read_color(void)
{
for (uint8_t i = 0; i < 3; i++) {
rgb_color.raw[i] = eeprom_read_byte(EECONFIG_RGB_COLOR + i);
}
}

void rgb_write_color(void)
{
for (uint8_t i = 0; i < 3; i++) {
eeprom_write_byte(EECONFIG_RGB_COLOR + i, rgb_color.raw[i]);
}
}

void rgb_toggle(void)
{
if (rgb_config.enable) {
rgb_off();
}
else {
rgb_on();
}
}

void rgb_on(void)
{
rgb_config.enable = 1;
rgb_set_level(rgb_config.level);
rgb_write_config();
}

void rgb_off(void)
{
rgb_config.enable = 0;
rgb_set_level(RGB_OFF);
rgb_write_config();
}

void rgb_decrease(void)
{
if(rgb_config.level > 0) {
rgb_config.level--;
rgb_config.enable = (rgb_config.level != 0);
rgb_write_config();
}
rgb_set_level(rgb_config.level);
}

void rgb_increase(void)
{
if(rgb_config.level < RGB_LEVELS) {
rgb_config.level++;
rgb_config.enable = 1;
rgb_write_config();
}
rgb_set_level(rgb_config.level);
}

void rgb_step(void)
{
rgb_config.level++;
if(rgb_config.level > RGB_LEVELS)
{
rgb_config.level = 0;
}
rgb_config.enable = (rgb_config.level != 0);
rgb_set_level(rgb_config.level);
}

void rgb_color_increase(uint8_t color)
{
uint8_t *c = &rgb_color.raw[color];
if (*c >= 240) {
*c = 255;
}
else {
*c += 16;
}
rgb_refresh(&rgb_color);
rgb_write_color();
}

void rgb_color_decrease(uint8_t color)
{
uint8_t *c = &rgb_color.raw[color];
if (*c > 240) {
*c = 240;
}
else if (*c < 16) {
*c = 0;
}
else {
*c -= 16;
}
rgb_refresh(&rgb_color);
rgb_write_color();
}

void rgb_set_level(uint8_t level)
{
switch (level) {
case RGB_OFF:
rgb_fading_enable = 0;
rgb_brightness = 0;
shift_register_write_word(0xFFFF);
break;
case RGB_FIXED:
rgb_refresh(&rgb_color);
shift_register_write_word(0x0000);
break;
case RGB_FADE_SLOW:
case RGB_FADE_MID:
case RGB_FADE_FAST:
rgb_fading_enable = 3 - (level - RGB_FADE_SLOW);
shift_register_write_word(0x0000);
break;
}
}

void rgb_set_brightness(uint8_t brightness)
{
rgb_brightness = brightness;
}

void rgb_refresh(rgb_color_t *rgb)
{
for (uint8_t i = 0; i < 3; i++) {
softpwm_led_set(i + 1, rgb->raw[i]);
}
}

/*
* original code: https://blog.adafruit.com/2012/03/14/constant-brightness-hsb-to-rgb-algorithm/
*/
void hsb_to_rgb(uint16_t hue, uint8_t saturation, uint8_t brightness, rgb_color_t *rgb)
{
uint8_t temp[5];
uint8_t n = (hue >> 8) % 3;
uint8_t x = ((((hue & 255) * saturation) >> 8) * brightness) >> 8;
uint8_t s = ((256 - saturation) * brightness) >> 8;
temp[0] = temp[3] = s;
temp[1] = temp[4] = x + s;
temp[2] = brightness - x;
rgb->r = temp[n + 2];
rgb->g = temp[n + 1];
rgb->b = temp[n];
}

void rgb_fading(void)
{
static uint8_t step = 0;
static uint16_t hue = 0;
static rgb_color_t color;
if (rgb_fading_enable) {
if (++step > rgb_fading_enable) {
step = 0;
rgb_hue = hue;
hsb_to_rgb(rgb_hue, rgb_saturation, rgb_brightness, &color);
rgb_refresh(&color);
if (++hue >= 768) {
hue = 0;
}
}
}
}

+ 72
- 0
keyboard/fantastic60/rgb.h Переглянути файл

@@ -0,0 +1,72 @@
/*
Copyright 2015 Kai Ryu <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef RGB_H
#define RGB_H

#include <stdint.h>
#include <stdbool.h>

typedef union {
uint8_t raw;
struct {
uint8_t level :7;
bool enable :1;
};
} rgb_config_t;

typedef union {
uint8_t raw[3];
struct {
uint8_t r;
uint8_t g;
uint8_t b;
};
} rgb_color_t;

enum {
RGB_OFF = 0,
RGB_FIXED,
RGB_FADE_SLOW,
RGB_FADE_MID,
RGB_FADE_FAST,
RGB_LEVELS = RGB_FADE_FAST
};

enum {
RGB_R = 0,
RGB_G,
RGB_B,
};

#define EECONFIG_RGB_CONFIG (uint8_t *)8
#define EECONFIG_RGB_COLOR (uint8_t *)9
#define RGB_UNCONFIGURED 0xFF

void rgb_init(void);
void rgb_toggle(void);
void rgb_on(void);
void rgb_off(void);
void rgb_decrease(void);
void rgb_increase(void);
void rgb_step(void);
void rgb_color_decrease(uint8_t color);
void rgb_color_increase(uint8_t color);
void rgb_set_brightness(uint8_t brightness);
void rgb_fading(void);

#endif

keyboard/fantastic60/fantastic.c → keyboard/fantastic60/shift_register.c Переглянути файл

@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "fantastic.h"
#include "shift_register.h"

void shift_register_init(void)
{

keyboard/fantastic60/fantastic.h → keyboard/fantastic60/shift_register.h Переглянути файл

@@ -15,8 +15,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef FANTASTIC_H
#define FANTASTIC_H
#ifndef SHIFT_REGISTER_H
#define SHIFT_REGISTER_H

#include <avr/io.h>
#include <stdint.h>