From 41741230b841780b2a4d74f54f400643ba682c6b Mon Sep 17 00:00:00 2001 From: Kai Ryu Date: Mon, 18 Jan 2016 11:59:50 +0900 Subject: [PATCH] kimera: Add a simple rgb led and ws2812 support --- keyboard/kimera/Makefile | 4 +- keyboard/kimera/backlight.c | 63 +++++--- keyboard/kimera/config.h | 6 +- keyboard/kimera/keymap_default.c | 30 ++++ keyboard/kimera/kimera.h | 6 +- keyboard/kimera/ledmap.c | 4 + keyboard/kimera/light_ws2812.c | 170 ++++++++++++++++++++++ keyboard/kimera/light_ws2812.h | 63 ++++++++ keyboard/kimera/rgb.c | 237 +++++++++++++++++++++++++++++++ keyboard/kimera/rgb.h | 60 ++++++++ keyboard/kimera/ws2812_config.h | 21 +++ 11 files changed, 637 insertions(+), 27 deletions(-) create mode 100644 keyboard/kimera/light_ws2812.c create mode 100644 keyboard/kimera/light_ws2812.h create mode 100644 keyboard/kimera/rgb.c create mode 100644 keyboard/kimera/rgb.h create mode 100644 keyboard/kimera/ws2812_config.h diff --git a/keyboard/kimera/Makefile b/keyboard/kimera/Makefile index bc6f5613..74264b49 100644 --- a/keyboard/kimera/Makefile +++ b/keyboard/kimera/Makefile @@ -54,7 +54,9 @@ SRC = keymap_common.c \ backlight.c \ ledmap.c \ twimaster.c \ - kimera.c + kimera.c \ + light_ws2812.c \ + rgb.c ifdef KEYMAP SRC := keymap_$(KEYMAP).c $(SRC) diff --git a/keyboard/kimera/backlight.c b/keyboard/kimera/backlight.c index 6cc3f0b6..bef3be13 100644 --- a/keyboard/kimera/backlight.c +++ b/keyboard/kimera/backlight.c @@ -26,6 +26,7 @@ along with this program. If not, see . #endif #include "action.h" #include "kimera.h" +#include "rgb.h" #ifdef BACKLIGHT_ENABLE @@ -37,11 +38,8 @@ static const uint8_t backlight_table[] PROGMEM = { 0, 16, 128, 255 }; -#ifdef SOFTPWM_LED_ENABLE -#ifdef FADING_LED_ENABLE -static uint8_t backlight_mode; -#endif -#endif +extern backlight_config_t backlight_config; +uint8_t backlight_brightness; /* Backlight pin configuration * LED4: PB6 (D10) OC1B @@ -73,17 +71,15 @@ void backlight_disable(void) void backlight_set(uint8_t level) { -#ifdef FADING_LED_ENABLE - backlight_mode = level; +#ifdef SOFTPWM_LED_ENABLE + softpwm_led_enable(); #endif - #ifdef BREATHING_LED_ENABLE switch (level) { case 1: case 2: case 3: #ifdef SOFTPWM_LED_ENABLE - softpwm_led_enable(); #ifdef FADING_LED_ENABLE fading_led_disable_all(); #endif @@ -92,13 +88,16 @@ void backlight_set(uint8_t level) backlight_enable(); breathing_led_disable(); #endif - backlight_set_raw(pgm_read_byte(&backlight_table[level])); + backlight_brightness = pgm_read_byte(&backlight_table[level]); +#ifdef RGB_LED_ENABLE + rgb_set_brightness(backlight_brightness); +#endif + backlight_set_raw(backlight_brightness); break; case 4: case 5: case 6: #ifdef SOFTPWM_LED_ENABLE - softpwm_led_enable(); #ifdef FADING_LED_ENABLE fading_led_disable_all(); #endif @@ -112,14 +111,12 @@ void backlight_set(uint8_t level) #ifdef SOFTPWM_LED_ENABLE #ifdef FADING_LED_ENABLE case 7: - softpwm_led_enable(); fading_led_enable_all(); breathing_led_disable_all(); fading_led_set_direction_all(FADING_LED_FADE_IN); fading_led_set_duration(3); break; case 8: - softpwm_led_enable(); fading_led_enable_all(); breathing_led_disable_all(); fading_led_set_direction_all(FADING_LED_FADE_OUT); @@ -134,7 +131,8 @@ void backlight_set(uint8_t level) fading_led_disable_all(); #endif breathing_led_disable_all(); - softpwm_led_disable(); + backlight_brightness = 0; + backlight_set_raw(backlight_brightness); #else breathing_led_disable(); backlight_disable(); @@ -193,18 +191,41 @@ void softpwm_led_off(uint8_t index) #ifdef FADING_LED_ENABLE void action_keyevent(keyevent_t event) { - if (backlight_mode == 7) { - if (event.pressed) { - softpwm_led_decrease_all(32); + if (backlight_config.enable) { + if (backlight_config.level == 7) { + if (event.pressed) { + fading_led_set_delay_all(64); + softpwm_led_decrease_all(32); + } } - } - if (backlight_mode == 8) { - if (event.pressed) { - softpwm_led_increase_all(32); + if (backlight_config.level == 8) { + if (event.pressed) { + fading_led_set_delay_all(64); + softpwm_led_increase_all(32); + } } } } #endif + +#ifdef RGB_LED_ENABLE +#ifdef CUSTOM_LED_ENABLE +void softpwm_led_custom(void) +{ + rgb_fading(); +} + +void fading_led_custom(uint8_t *value) +{ + rgb_set_brightness(value[0]); +} + +void breathing_led_custom(uint8_t *value) +{ + rgb_set_brightness(value[0]); +} +#endif +#endif #endif #endif diff --git a/keyboard/kimera/config.h b/keyboard/kimera/config.h index b08002e7..8fef70fb 100644 --- a/keyboard/kimera/config.h +++ b/keyboard/kimera/config.h @@ -36,9 +36,9 @@ along with this program. If not, see . #define FN_ACTIONS_COUNT 32 #define KEYMAPS_COUNT 3 #ifndef TWO_HEADED_KIMERA -#define EECONFIG_KEYMAP_IN_EEPROM 49 +#define EECONFIG_KEYMAP_IN_EEPROM 50 #else -#define EECONFIG_KEYMAP_IN_EEPROM 81 +#define EECONFIG_KEYMAP_IN_EEPROM 82 #endif /* define if matrix has ghost */ @@ -60,6 +60,8 @@ along with this program. If not, see . /* enable customized backlight logic */ #define BACKLIGHT_CUSTOM +#define CUSTOM_LED_ENABLE +#define RGB_LED_ENABLE /* number of leds */ #define LED_COUNT 4 diff --git a/keyboard/kimera/keymap_default.c b/keyboard/kimera/keymap_default.c index 4045ef45..7e750b4f 100644 --- a/keyboard/kimera/keymap_default.c +++ b/keyboard/kimera/keymap_default.c @@ -1,4 +1,5 @@ #include "keymap_common.h" +#include "rgb.h" // Default #ifdef KEYMAP_SECTION_ENABLE @@ -49,3 +50,32 @@ uint16_t fn_actions_count(void) { return sizeof(fn_actions) / sizeof(fn_actions[0]); } #endif + +#ifndef NO_ACTION_FUNCTION +enum function_id { + AF_RGB_TOGGLE = 0, + AF_RGB_DECREASE, + AF_RGB_INCREASE, + AF_RGB_STEP +}; + +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; + } + } +} +#endif diff --git a/keyboard/kimera/kimera.h b/keyboard/kimera/kimera.h index 387b5157..24d3c132 100644 --- a/keyboard/kimera/kimera.h +++ b/keyboard/kimera/kimera.h @@ -148,9 +148,9 @@ const uint16_t PROGMEM dummy[] = { /* Matrix Mapping in EEPROM */ -#define EECONFIG_ROW_COUNT (uint8_t *)15 -#define EECONFIG_COL_COUNT (uint8_t *)16 -#define EECONFIG_ROW_COL_MAPPING (uint8_t *)17 +#define EECONFIG_ROW_COUNT (uint8_t *)16 +#define EECONFIG_COL_COUNT (uint8_t *)17 +#define EECONFIG_ROW_COL_MAPPING (uint8_t *)18 #define UNCONFIGURED 0xFF /* Functions */ diff --git a/keyboard/kimera/ledmap.c b/keyboard/kimera/ledmap.c index a2794068..753b3dc2 100644 --- a/keyboard/kimera/ledmap.c +++ b/keyboard/kimera/ledmap.c @@ -55,7 +55,9 @@ void ledmap_led_on(uint8_t index) LED2_PORT &= ~(1< +#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/kimera/light_ws2812.h b/keyboard/kimera/light_ws2812.h new file mode 100644 index 00000000..bc2c4e86 --- /dev/null +++ b/keyboard/kimera/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/kimera/rgb.c b/keyboard/kimera/rgb.c new file mode 100644 index 00000000..4954a996 --- /dev/null +++ b/keyboard/kimera/rgb.c @@ -0,0 +1,237 @@ +/* +Copyright 2016 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 "softpwm_led.h" +#include "backlight.h" +#include "rgb.h" +#include "light_ws2812.h" +#include "debug.h" + +#ifdef RGB_LED_ENABLE + +volatile static uint8_t rgb_fading_enable = 0; +static rgb_config_t rgb_config; +static struct cRGB rgb_color[RGB_LED_COUNT]; +static uint16_t rgb_hue = 0; +static uint8_t rgb_saturation = 255; +static uint8_t rgb_brightness = 16; +static uint8_t rgb_rainbow = 0; + +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_set_level(uint8_t level); +static void rgb_refresh(void); +static void hue_to_rgb(uint16_t hue, struct cRGB *rgb); +static void hsb_to_rgb(uint16_t hue, uint8_t saturation, uint8_t brightness, struct cRGB *rgb); + +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_level(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_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_set_level(uint8_t level) +{ + dprintf("RGB Level: %d\n", level); + if (level <= RGB_WHITE) { + rgb_fading_enable = 0; + rgb_rainbow = 0; + if (level == RGB_OFF) { + rgb_brightness = 0; + } + else { + if (level == RGB_WHITE) { + rgb_saturation = 0; + } + else { + rgb_hue = (level - 1) * 128; + rgb_saturation = 255; + } + if (backlight_config.enable) { + if (backlight_config.level >= 1 && backlight_config.level <= 3) { + rgb_brightness = backlight_brightness; + } + } + else { + rgb_brightness = 16; + } + } + rgb_refresh(); + } + else { + rgb_saturation = 255; + rgb_fading_enable = 1; + rgb_rainbow = (level >= RGB_RAINBOW) ? 1 : 0; + } +} + +void rgb_set_brightness(uint8_t brightness) +{ + if (rgb_config.enable) { + rgb_brightness = brightness; + rgb_refresh(); + } +} + +void rgb_refresh(void) +{ + struct cRGB rgb; + uint16_t hue; + uint8_t i; + if (rgb_rainbow) { + for (i = 0; i < RGB_LED_COUNT; i++) { + hue = rgb_hue + (768 / RGB_LED_COUNT) * i; + hsb_to_rgb(hue, rgb_saturation, rgb_brightness, &rgb); + rgb_color[i] = rgb; + } + } + else { + hsb_to_rgb(rgb_hue, rgb_saturation, rgb_brightness, &rgb); + for (i = 0; i < RGB_LED_COUNT; i++) { + rgb_color[i] = rgb; + } + } + /* xprintf("R%d G%d B%d\n", rgb_color[0].r, rgb_color[0].g, rgb_color[0].b); */ + ws2812_setleds(rgb_color, RGB_LED_COUNT); +} + +void hue_to_rgb(uint16_t hue, struct cRGB *rgb) +{ + uint8_t hi = hue / 60; + uint16_t f = (hue % 60) * 425 / 100; + uint8_t q = 255 - f; + switch (hi) { + case 0: rgb->r = 255; rgb->g = f; rgb->b = 0; break; + case 1: rgb->r = q; rgb->g = 255; rgb->b = 0; break; + case 2: rgb->r = 0; rgb->g = 255; rgb->b = f; break; + case 3: rgb->r = 0; rgb->g = q; rgb->b = 255; break; + case 4: rgb->r = f; rgb->g = 0; rgb->b = 255; break; + case 5: rgb->r = 255; rgb->g = 0; rgb->b = q; break; + } +} + +/* + * 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, struct cRGB *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; + if (rgb_fading_enable) { + if (++step > rgb_fading_enable) { + step = 0; + rgb_hue = hue; + rgb_refresh(); + if (++hue >= 768) { + hue = 0; + } + } + } +} + +#endif diff --git a/keyboard/kimera/rgb.h b/keyboard/kimera/rgb.h new file mode 100644 index 00000000..bde1db75 --- /dev/null +++ b/keyboard/kimera/rgb.h @@ -0,0 +1,60 @@ +/* +Copyright 2016 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_YELLOW, + RGB_GREEN, + RGB_CYAN, + RGB_BLUE, + RGB_MAGENTA, + RGB_WHITE, + RGB_FADE, + RGB_RAINBOW, + RGB_LEVELS = RGB_RAINBOW +}; + +#define EECONFIG_RGB (uint8_t *)15 +#define RGB_UNCONFIGURED 0xFF +#define RGB_LED_COUNT 16 + +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_set_brightness(uint8_t brightness); +void rgb_fading(void); + +#endif diff --git a/keyboard/kimera/ws2812_config.h b/keyboard/kimera/ws2812_config.h new file mode 100644 index 00000000..1d5a6738 --- /dev/null +++ b/keyboard/kimera/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_ */