#include "keycode.h" | #include "keycode.h" | ||||
#include "action.h" | #include "action.h" | ||||
#include "keymap_common.h" | #include "keymap_common.h" | ||||
#include "rgb.h" | |||||
// Default | // Default | ||||
#ifdef KEYMAP_SECTION_ENABLE | #ifdef KEYMAP_SECTION_ENABLE | ||||
KEYMAP( FN5, FN3, FN6, FN4, FN7 ), | 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 | * Fn action definition | ||||
*/ | */ | ||||
[1] = ACTION_DEFAULT_LAYER_SET(2), | [1] = ACTION_DEFAULT_LAYER_SET(2), | ||||
[2] = ACTION_DEFAULT_LAYER_SET(3), | [2] = ACTION_DEFAULT_LAYER_SET(3), | ||||
[3] = ACTION_DEFAULT_LAYER_SET(0), | [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 | #endif | ||||
}; | }; | ||||
return sizeof(fn_actions) / sizeof(fn_actions[0]); | return sizeof(fn_actions) / sizeof(fn_actions[0]); | ||||
} | } | ||||
#endif | #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; | |||||
} | |||||
} | |||||
} |
/* | |||||
* 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; | |||||
} |
/* | |||||
* 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_ */ |
#include "util.h" | #include "util.h" | ||||
#include "matrix.h" | #include "matrix.h" | ||||
#include "keymap_common.h" | #include "keymap_common.h" | ||||
#include "rgb.h" | |||||
#ifndef DEBOUNCE | #ifndef DEBOUNCE | ||||
void matrix_init(void) | void matrix_init(void) | ||||
{ | { | ||||
rgb_init(); | |||||
// initialize cols | // initialize cols | ||||
init_cols(); | init_cols(); | ||||
} | } |
/* | |||||
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); | |||||
} |
/* | |||||
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 |
/* | |||||
* 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_ */ |