diff --git a/keyboard/staryu/keymap_lite.c b/keyboard/staryu/keymap_lite.c index 892b8da4..775f3d86 100644 --- a/keyboard/staryu/keymap_lite.c +++ b/keyboard/staryu/keymap_lite.c @@ -19,6 +19,7 @@ along with this program. If not, see . #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; + } + } +} diff --git a/keyboard/staryu/light_ws2812.c b/keyboard/staryu/light_ws2812.c new file mode 100644 index 00000000..fb147681 --- /dev/null +++ b/keyboard/staryu/light_ws2812.c @@ -0,0 +1,170 @@ +/* +* light weight WS2812 lib V2.0b +* +* Controls WS2811/WS2812/WS2812B RGB-LEDs +* Author: Tim (cpldcpu@gmail.com) +* +* Jan 18th, 2014 v2.0b Initial Version +* +* License: GNU GPL v2 (see License.txt) +*/ + +#include "light_ws2812.h" +#include +#include +#include + +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; +} diff --git a/keyboard/staryu/light_ws2812.h b/keyboard/staryu/light_ws2812.h new file mode 100644 index 00000000..bc2c4e86 --- /dev/null +++ b/keyboard/staryu/light_ws2812.h @@ -0,0 +1,63 @@ +/* + * light weight WS2812 lib include + * + * Version 2.0a3 - Jan 18th 2014 + * Author: Tim (cpldcpu@gmail.com) + * + * 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 +#include +#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_ */ diff --git a/keyboard/staryu/matrix.c b/keyboard/staryu/matrix.c index 3cce65b9..c9504832 100644 --- a/keyboard/staryu/matrix.c +++ b/keyboard/staryu/matrix.c @@ -28,6 +28,7 @@ along with this program. If not, see . #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(); } diff --git a/keyboard/staryu/rgb.c b/keyboard/staryu/rgb.c new file mode 100644 index 00000000..f2e051c2 --- /dev/null +++ b/keyboard/staryu/rgb.c @@ -0,0 +1,126 @@ +/* +Copyright 2015 Kai Ryu + +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 . +*/ + +#include +#include +#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); +} diff --git a/keyboard/staryu/rgb.h b/keyboard/staryu/rgb.h new file mode 100644 index 00000000..61073dde --- /dev/null +++ b/keyboard/staryu/rgb.h @@ -0,0 +1,56 @@ +/* +Copyright 2015 Kai Ryu + +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 . +*/ + +#ifndef RGB_H +#define RGB_H + +#include +#include + +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 diff --git a/keyboard/staryu/ws2812_config.h b/keyboard/staryu/ws2812_config.h new file mode 100644 index 00000000..1d5a6738 --- /dev/null +++ b/keyboard/staryu/ws2812_config.h @@ -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_ */