@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "keycode.h" | |||
#include "action.h" | |||
#include "keymap_common.h" | |||
#include "rgb.h" | |||
// Default | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
@@ -60,6 +61,13 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
KEYMAP( FN5, FN3, FN6, FN4, FN7 ), | |||
}; | |||
enum function_id { | |||
AF_RGB_TOGGLE = 0, | |||
AF_RGB_DECREASE, | |||
AF_RGB_INCREASE, | |||
AF_RGB_STEP | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
@@ -71,10 +79,10 @@ const uint16_t fn_actions[] PROGMEM = { | |||
[1] = ACTION_DEFAULT_LAYER_SET(2), | |||
[2] = ACTION_DEFAULT_LAYER_SET(3), | |||
[3] = ACTION_DEFAULT_LAYER_SET(0), | |||
[4] = ACTION_BACKLIGHT_TOGGLE(), | |||
[5] = ACTION_BACKLIGHT_STEP(), | |||
[6] = ACTION_BACKLIGHT_DECREASE(), | |||
[7] = ACTION_BACKLIGHT_INCREASE() | |||
[4] = ACTION_BACKLIGHT_DECREASE(), | |||
[5] = ACTION_BACKLIGHT_INCREASE(), | |||
[6] = ACTION_FUNCTION(AF_RGB_DECREASE), | |||
[7] = ACTION_FUNCTION(AF_RGB_INCREASE) | |||
#endif | |||
}; | |||
@@ -87,3 +95,23 @@ 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_DECREASE: | |||
rgb_decrease(); | |||
break; | |||
case AF_RGB_INCREASE: | |||
rgb_increase(); | |||
break; | |||
case AF_RGB_STEP: | |||
rgb_step(); | |||
break; | |||
} | |||
} | |||
} |
@@ -0,0 +1,170 @@ | |||
/* | |||
* light weight WS2812 lib V2.0b | |||
* | |||
* Controls WS2811/WS2812/WS2812B RGB-LEDs | |||
* Author: Tim ([email protected]) | |||
* | |||
* Jan 18th, 2014 v2.0b Initial Version | |||
* | |||
* License: GNU GPL v2 (see License.txt) | |||
*/ | |||
#include "light_ws2812.h" | |||
#include <avr/interrupt.h> | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds) | |||
{ | |||
ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); | |||
} | |||
void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask) | |||
{ | |||
ws2812_DDRREG |= pinmask; // Enable DDR | |||
ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask); | |||
_delay_us(50); | |||
} | |||
void ws2812_sendarray(uint8_t *data,uint16_t datlen) | |||
{ | |||
ws2812_sendarray_mask(data,datlen,_BV(ws2812_pin)); | |||
} | |||
/* | |||
This routine writes an array of bytes with RGB values to the Dataout pin | |||
using the fast 800kHz clockless WS2811/2812 protocol. | |||
*/ | |||
// Timing in ns | |||
#define w_zeropulse 350 | |||
#define w_onepulse 900 | |||
#define w_totalperiod 1250 | |||
// Fixed cycles used by the inner loop | |||
#define w_fixedlow 2 | |||
#define w_fixedhigh 4 | |||
#define w_fixedtotal 8 | |||
// Insert NOPs to match the timing, if possible | |||
#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000) | |||
#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000) | |||
#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000) | |||
// w1 - nops between rising edge and falling edge - low | |||
#define w1 (w_zerocycles-w_fixedlow) | |||
// w2 nops between fe low and fe high | |||
#define w2 (w_onecycles-w_fixedhigh-w1) | |||
// w3 nops to complete loop | |||
#define w3 (w_totalcycles-w_fixedtotal-w1-w2) | |||
#if w1>0 | |||
#define w1_nops w1 | |||
#else | |||
#define w1_nops 0 | |||
#endif | |||
// The only critical timing parameter is the minimum pulse length of the "0" | |||
// Warn or throw error if this timing can not be met with current F_CPU settings. | |||
#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000) | |||
#if w_lowtime>550 | |||
#error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?" | |||
#elif w_lowtime>450 | |||
#warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)." | |||
#warning "Please consider a higher clockspeed, if possible" | |||
#endif | |||
#if w2>0 | |||
#define w2_nops w2 | |||
#else | |||
#define w2_nops 0 | |||
#endif | |||
#if w3>0 | |||
#define w3_nops w3 | |||
#else | |||
#define w3_nops 0 | |||
#endif | |||
#define w_nop1 "nop \n\t" | |||
#define w_nop2 "rjmp .+0 \n\t" | |||
#define w_nop4 w_nop2 w_nop2 | |||
#define w_nop8 w_nop4 w_nop4 | |||
#define w_nop16 w_nop8 w_nop8 | |||
void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi) | |||
{ | |||
uint8_t curbyte,ctr,masklo; | |||
uint8_t sreg_prev; | |||
masklo =~maskhi&ws2812_PORTREG; | |||
maskhi |= ws2812_PORTREG; | |||
sreg_prev=SREG; | |||
cli(); | |||
while (datlen--) { | |||
curbyte=*data++; | |||
asm volatile( | |||
" ldi %0,8 \n\t" | |||
"loop%=: \n\t" | |||
" out %2,%3 \n\t" // '1' [01] '0' [01] - re | |||
#if (w1_nops&1) | |||
w_nop1 | |||
#endif | |||
#if (w1_nops&2) | |||
w_nop2 | |||
#endif | |||
#if (w1_nops&4) | |||
w_nop4 | |||
#endif | |||
#if (w1_nops&8) | |||
w_nop8 | |||
#endif | |||
#if (w1_nops&16) | |||
w_nop16 | |||
#endif | |||
" sbrs %1,7 \n\t" // '1' [03] '0' [02] | |||
" out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low | |||
" lsl %1 \n\t" // '1' [04] '0' [04] | |||
#if (w2_nops&1) | |||
w_nop1 | |||
#endif | |||
#if (w2_nops&2) | |||
w_nop2 | |||
#endif | |||
#if (w2_nops&4) | |||
w_nop4 | |||
#endif | |||
#if (w2_nops&8) | |||
w_nop8 | |||
#endif | |||
#if (w2_nops&16) | |||
w_nop16 | |||
#endif | |||
" out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high | |||
#if (w3_nops&1) | |||
w_nop1 | |||
#endif | |||
#if (w3_nops&2) | |||
w_nop2 | |||
#endif | |||
#if (w3_nops&4) | |||
w_nop4 | |||
#endif | |||
#if (w3_nops&8) | |||
w_nop8 | |||
#endif | |||
#if (w3_nops&16) | |||
w_nop16 | |||
#endif | |||
" dec %0 \n\t" // '1' [+2] '0' [+2] | |||
" brne loop%=\n\t" // '1' [+3] '0' [+4] | |||
: "=&d" (ctr) | |||
: "r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_PORTREG)), "r" (maskhi), "r" (masklo) | |||
); | |||
} | |||
SREG=sreg_prev; | |||
} |
@@ -0,0 +1,63 @@ | |||
/* | |||
* light weight WS2812 lib include | |||
* | |||
* Version 2.0a3 - Jan 18th 2014 | |||
* Author: Tim ([email protected]) | |||
* | |||
* Please do not change this file! All configuration is handled in "ws2812_config.h" | |||
* | |||
* License: GNU GPL v2 (see License.txt) | |||
+ | |||
*/ | |||
#ifndef LIGHT_WS2812_H_ | |||
#define LIGHT_WS2812_H_ | |||
#include <avr/io.h> | |||
#include <avr/interrupt.h> | |||
#include "ws2812_config.h" | |||
/* | |||
* Structure of the LED array | |||
*/ | |||
struct cRGB { uint8_t g; uint8_t r; uint8_t b; }; | |||
/* User Interface | |||
* | |||
* Input: | |||
* ledarray: An array of GRB data describing the LED colors | |||
* number_of_leds: The number of LEDs to write | |||
* pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0) | |||
* | |||
* The functions will perform the following actions: | |||
* - Set the data-out pin as output | |||
* - Send out the LED data | |||
* - Wait 50µs to reset the LEDs | |||
*/ | |||
void ws2812_setleds (struct cRGB *ledarray, uint16_t number_of_leds); | |||
void ws2812_setleds_pin(struct cRGB *ledarray, uint16_t number_of_leds,uint8_t pinmask); | |||
/* | |||
* Old interface / Internal functions | |||
* | |||
* The functions take a byte-array and send to the data output as WS2812 bitstream. | |||
* The length is the number of bytes to send - three per LED. | |||
*/ | |||
void ws2812_sendarray (uint8_t *array,uint16_t length); | |||
void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask); | |||
/* | |||
* Internal defines | |||
*/ | |||
#define CONCAT(a, b) a ## b | |||
#define CONCAT_EXP(a, b) CONCAT(a, b) | |||
#define ws2812_PORTREG CONCAT_EXP(PORT,ws2812_port) | |||
#define ws2812_DDRREG CONCAT_EXP(DDR,ws2812_port) | |||
#endif /* LIGHT_WS2812_H_ */ |
@@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "util.h" | |||
#include "matrix.h" | |||
#include "keymap_common.h" | |||
#include "rgb.h" | |||
#ifndef DEBOUNCE | |||
@@ -56,6 +57,8 @@ uint8_t matrix_cols(void) | |||
void matrix_init(void) | |||
{ | |||
rgb_init(); | |||
// initialize cols | |||
init_cols(); | |||
} |
@@ -0,0 +1,126 @@ | |||
/* | |||
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 "rgb.h" | |||
#include "light_ws2812.h" | |||
static const uint8_t rgb_table[RGB_LEVELS][3] PROGMEM = { | |||
{ 0, 0, 0 }, | |||
{ 255, 0, 0 }, | |||
{ 255, 127, 0 }, | |||
{ 255, 255, 0 }, | |||
{ 0, 255, 0 }, | |||
{ 0, 255, 255 }, | |||
{ 0, 0, 255 }, | |||
{ 143, 0, 255 }, | |||
{ 255, 255, 255 } | |||
}; | |||
static rgb_config_t rgb_config; | |||
void rgb_write_config(void); | |||
void rgb_read_config(void); | |||
void rgb_set(uint8_t level); | |||
void rgb_init(void) | |||
{ | |||
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(rgb_config.level); | |||
} | |||
} | |||
void rgb_read_config(void) | |||
{ | |||
rgb_config.raw = eeprom_read_byte(EECONFIG_RGB); | |||
} | |||
void rgb_write_config(void) | |||
{ | |||
eeprom_write_byte(EECONFIG_RGB, rgb_config.raw); | |||
} | |||
void rgb_toggle(void) | |||
{ | |||
if (rgb_config.enable) { | |||
rgb_off(); | |||
} | |||
else { | |||
rgb_on(); | |||
} | |||
} | |||
void rgb_on(void) | |||
{ | |||
rgb_config.enable = 1; | |||
rgb_set(rgb_config.level); | |||
rgb_write_config(); | |||
} | |||
void rgb_off(void) | |||
{ | |||
rgb_config.enable = 0; | |||
rgb_set(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(rgb_config.level); | |||
} | |||
void rgb_increase(void) | |||
{ | |||
if(rgb_config.level < RGB_LEVELS - 1) { | |||
rgb_config.level++; | |||
rgb_config.enable = 1; | |||
rgb_write_config(); | |||
} | |||
rgb_set(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(rgb_config.level); | |||
} | |||
void rgb_set(uint8_t level) | |||
{ | |||
struct cRGB rgb[1]; | |||
rgb[0].r = pgm_read_byte(&rgb_table[level][0]); | |||
rgb[0].g = pgm_read_byte(&rgb_table[level][1]); | |||
rgb[0].b = pgm_read_byte(&rgb_table[level][2]); | |||
ws2812_setleds(rgb, 1); | |||
} |
@@ -0,0 +1,56 @@ | |||
/* | |||
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; | |||
enum { | |||
RGB_OFF = 0, | |||
RGB_RED, | |||
RGB_ORANGE, | |||
RGB_YELLOW, | |||
RGB_GREEN, | |||
RGB_CYAN, | |||
RGB_BLUE, | |||
RGB_VIOLET, | |||
RGB_WHITE, | |||
RGB_LEVELS | |||
}; | |||
#define EECONFIG_RGB (uint8_t *)7 | |||
#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); | |||
#endif |
@@ -0,0 +1,21 @@ | |||
/* | |||
* light_ws2812_config.h | |||
* | |||
* Created: 18.01.2014 09:58:15 | |||
* | |||
* User Configuration file for the light_ws2812_lib | |||
* | |||
*/ | |||
#ifndef WS2812_CONFIG_H_ | |||
#define WS2812_CONFIG_H_ | |||
/////////////////////////////////////////////////////////////////////// | |||
// Define I/O pin | |||
/////////////////////////////////////////////////////////////////////// | |||
#define ws2812_port C // Data port | |||
#define ws2812_pin 6 // Data out pin | |||
#endif /* WS2812_CONFIG_H_ */ |