diff --git a/README.md b/README.md index 27dbe66..0f8eeb9 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,10 @@ todo ## Software +#Librarys + +https://github.com/marenz2569/libws2812_avr + todo diff --git a/Software/src/ioController.cpp b/Software/src/ioController.cpp index 068b222..b3534f8 100644 --- a/Software/src/ioController.cpp +++ b/Software/src/ioController.cpp @@ -29,7 +29,6 @@ double ioController::get15VProbe() { } void ioController::ports_init() { - DDRD |= 1 << WS2812B; DDRB |= 1 << ACTIVELED; DDRB |= 1 << BUZZER; DDRB |= 1 << POWERON; @@ -103,3 +102,19 @@ void ioController::setMultiplexer(bool pS2, bool pS1, bool pS0) { } +void ioController::setWS2812(const unsigned char red, const unsigned char green, + const unsigned char blue) { + + WS2812 led(LED_C); + led.set_output(&PORTD, &DDRD, DDD2); + Color strobe; + uint8_t i; + + strobe.r = red; + strobe.g = green; + strobe.b = blue; + for (i = 0; i < LED_C; i++) + led.set_rgb_at(i, strobe); + led.sync(); +} + diff --git a/Software/src/ioController.h b/Software/src/ioController.h index 50b591d..13d2cdf 100644 --- a/Software/src/ioController.h +++ b/Software/src/ioController.h @@ -12,7 +12,6 @@ class ioController { private: - public: ioController(); ~ioController(); @@ -26,6 +25,9 @@ public: void adc_init(void); int readAdc(char chan); void setMultiplexer(bool pS2, bool pS1, bool pS0); + void setWS2812(const unsigned char red, const unsigned char green, + const unsigned char blue); + }; #endif /* SRC_IOCONTROLLER_H_ */ diff --git a/Software/src/main.cpp b/Software/src/main.cpp index 7b0991b..1153744 100644 --- a/Software/src/main.cpp +++ b/Software/src/main.cpp @@ -30,6 +30,8 @@ int main(void) { createChargers(); + io.setWS2812(0, 255, 255); + //loop till power off while (true) { checkForBattery(); @@ -131,13 +133,10 @@ void printStatus() { for (int i = 0; i < CHARGER_SIZE; i++) { if (chargers[i].getStatus()) { //chargers[i].getInfo(); //print values - char charVal[10]; - + //char charVal[10]; //dtostrf(chargers[i].getCurrent(), 4, 0, charVal); - - sprintf(charVal, "%i µAh\r\n", chargers[i].getCapacity()); - - serialSend(charVal); + //sprintf(charVal, "%i µAh\r\n", chargers[i].getCapacity()); + //serialSend(charVal); //serialSend(" mA\r\n"); } } diff --git a/Software/src/openChargeMicro.h b/Software/src/openChargeMicro.h index 2fc8332..23f8e88 100644 --- a/Software/src/openChargeMicro.h +++ b/Software/src/openChargeMicro.h @@ -7,12 +7,15 @@ #include /* project header */ +#include "ws2812/ws2812.h" #include "ioController.h" #include "multiplexer.h" #include "clock.h" #include "charger.h" + + /* Pins */ #define WS2812B PD2 #define ACTIVELED PB5 @@ -57,5 +60,6 @@ void serialSend(const char* sendString); #define CH3_U 3 #define CH3_I 7 - +/* ws2812 */ +#define LED_C 1 diff --git a/Software/src/ws2812/color.h b/Software/src/ws2812/color.h new file mode 100644 index 0000000..58e43be --- /dev/null +++ b/Software/src/ws2812/color.h @@ -0,0 +1,177 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef COLOR_H__ +#define COLOR_H__ + +#include + +/** + * A class used to save and convert hsi and rgb values + */ +class Color +{ + /** + * check if the rgb values of 2 Color objects are the same + * @param a first Color object + * @param b second Color object + */ + friend bool operator ==(Color a, Color b) + { + if (a.r != b.r) + return false; + if (a.g != b.g) + return false; + if (a.b != b.b) + return false; + return true; + } + + /** + * check if the rgb values of 2 Color objecs are not the same + * @param a first Color object + * @param b second Color object + */ + friend bool operator !=(Color a, Color b) + { + if (a.r != b.r) + return true; + if (a.g != b.g) + return true; + if (a.b != b.b) + return true; + return false; + } +public: + /** + * red value + */ + uint8_t r; + /** + * green value + */ + uint8_t g; + /** + * blue value + */ + uint8_t b; + /** + * hue value + */ + float h; + /** + * saturation value + */ + float s; + /** + * intensity value + */ + float i; + + /** + * convert hsi to rgb + * @param h_ hue value + * @param s_ saturation value + * @param i_ intensity value + */ + void hsi2rgb(float h_, float s_, float i_); + /** + * convert rgb to hsi + * @param r_ red value + * @param g_ green value + * @param b_ blue value + */ + void rgb2hsi(uint8_t r_, uint8_t g_, uint8_t b_); +}; + +/** + * A type to define the fadeing direction + */ +enum color_fade_dir_t +{ + shortest, + longest, + clockwise, + counter_clockwise +}; + +/** + * A class used to fade linear between two points in hsi color space + */ +class FadeLinear +{ +private: + uint16_t step_count; + + uint16_t cur_step; + + float h_step, s_step, i_step; + + Color cCur; + +public: + /** + * @param cFrom Color object as fade origin + * @param cTo Color oject as fade result + * @param stepCount number of fadeing steps + * @param fadeDir fade direction in hsi color space + */ + FadeLinear(Color &cFrom, Color &cTo, uint16_t stepCount, color_fade_dir_t fadeDir); + /** + * calls constructor {@link #FadeLinear(Color &cFrom, Color &cTo, uint16_t stepCount, color_fade_dir_t fadeDir)} + * with fadeDir = shortest + */ + FadeLinear(Color &cFrom, Color &cTo, uint16_t stepCount); + + /** + * updates Color object in this class, that saves current fade color + * @return 1 if successful, 0 if not + */ + uint8_t next(void); + + /** + * @return Color object + */ + Color get_cur_color(void); + +}; + +/** + * A class is used to fade from the color to a grayscale with i = deltaI / 2 to the second color + */ +class FadeThroughIAxis { +private: + uint16_t step_count; + + uint16_t cur_step; + + float from_step_count, to_step_count; + + float h_from_step, s_from_step, i_from_step; + + float h_to_step, s_to_step, i_to_step; + + Color cCur; +public: + FadeThroughIAxis(Color& cFrom, Color& cTo, uint16_t stepCount); + + uint8_t next(void); + + Color get_cur_color(void); +}; + +#endif diff --git a/Software/src/ws2812/color_hsi2rgb.cpp b/Software/src/ws2812/color_hsi2rgb.cpp new file mode 100644 index 0000000..1afe17b --- /dev/null +++ b/Software/src/ws2812/color_hsi2rgb.cpp @@ -0,0 +1,69 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "color.h" +#include "ws2812_avr_macros.h" + +/* derived from http://fourier.eng.hmc.edu/e161/lectures/ColorProcessing/node3.html */ +void Color::hsi2rgb(float h_, float s_, float i_) +{ + h = h_; + s = s_; + i = i_; + + h_ = fmod(h_, 360); + /* convert h to radiants */ + h_ = M_PI * h_ / 180.0; + /* clamp s and i to interval [0:1] */ + s_ = clamp_to_0_1(s_); + i_ = clamp_to_0_1(i_); + + if (s_ == 0.0) { + r = g = b = i_ * 255; + } else { + float r_, g_, b_; +#define hsi2rgb_color1 ((1 - s_) / 3) +#define hsi2rgb_color2 ((1 + s_ * cos(h_) / cos((M_PI / 3.0) - h_)) / 3) + if ((h_ >= 0.0) && (h_ < 2.0 * M_PI / 3.0)) { + b_ = hsi2rgb_color1; + r_ = hsi2rgb_color2; + g_ = 1 - b_ - r_; + } else if ((h_ >= 2.0 * M_PI / 3.0) && (h_ < 4.0 * M_PI / 3.0)) { + h_ -= 2.0 * M_PI / 3.0; + r_ = hsi2rgb_color1; + g_ = hsi2rgb_color2; + b_ = 1 - r_ - g_; + } else { + h_ -= 4.0 * M_PI / 3.0; + g_ = hsi2rgb_color1; + b_ = hsi2rgb_color2; + r_ = 1 - g_ - b_; + } + + r_ = i_ * r_ * 255; + g_ = i_ * g_ * 255; + b_ = i_ * b_ * 255; + + /* clamp r, g and b to interval [0:255] */ + r = clamp_to_0_255(r_); + g = clamp_to_0_255(g_); + b = clamp_to_0_255(b_); + } + +} diff --git a/Software/src/ws2812/color_rgb2hsi.cpp b/Software/src/ws2812/color_rgb2hsi.cpp new file mode 100644 index 0000000..ec7e7f3 --- /dev/null +++ b/Software/src/ws2812/color_rgb2hsi.cpp @@ -0,0 +1,48 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "color.h" + +/* derived form http://www.cse.usf.edu/~mshreve/rgb-to-hsi */ +void Color::rgb2hsi(uint8_t r_, uint8_t g_, uint8_t b_) +{ + r = r_; + g = g_; + b = b_; + + float h_, s_, i_, sum; + sum = (float) (r_ + g_ + b_); + i_ = sum / 255.0; + + /* normalize rgb values */ + float n_r = (float) r_ / sum; + float n_g = (float) g_ / sum; + float n_b = (float) b_ / sum; + + h_ = acos(0.5 * ((n_r - n_g) + (n_r - n_b)) / sqrt(pow((n_r - n_g), 2.0) + ((n_r - n_b) * (n_g - n_b)))); + + if (n_b > n_g) + h_ = 2 * M_PI - h_; + + s_ = 1 - 3 * fmin(n_r, fmin(n_g, n_b)); + + h = h_ * 180.0 / M_PI; + s = s_; + i = i_; +} diff --git a/Software/src/ws2812/fadelinear.cpp b/Software/src/ws2812/fadelinear.cpp new file mode 100644 index 0000000..c056cf6 --- /dev/null +++ b/Software/src/ws2812/fadelinear.cpp @@ -0,0 +1,68 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "color.h" +#include "ws2812_avr_macros.h" + +FadeLinear::FadeLinear(Color &cFrom, Color &cTo, uint16_t stepCount, color_fade_dir_t fadeDir) : step_count(stepCount), cCur(cFrom), cur_step(0) +{ + float h_step_; + h_step_ = cTo.h - cFrom.h; + + switch (fadeDir) { + case shortest: + if (fabs(h_step_) > 180.0) + h_step_ = _change_pos_neg(h_step_) * _360_min_fabs(h_step_); + break; + case longest: + if (fabs(h_step_) < 180.0) + h_step_ = _change_pos_neg(h_step_) * _360_min_fabs(h_step_); + break; + case clockwise: + if (h_step_ < 0.0) + h_step_ = _360_min_fabs(h_step_); + break; + case counter_clockwise: + if (h_step_ > 0.0) + h_step_ = -1.0 * _360_min_fabs(h_step_); + break; + } + h_step = h_step_ / (float)step_count; + s_step = (cTo.s - cFrom.s) / (float)step_count; + i_step = (cTo.i - cFrom.i) / (float)step_count; +} + +FadeLinear::FadeLinear(Color &cFrom, Color &cTo, uint16_t stepCount) : FadeLinear(cFrom, cTo, stepCount, shortest) +{ + +} + +uint8_t FadeLinear::next(void) +{ + if (cur_step++ < step_count) { + cCur.hsi2rgb(cCur.h + h_step, cCur.s + s_step, cCur.i + i_step); + return 1; + } + return 0; +} + +Color FadeLinear::get_cur_color(void) +{ + return cCur; +} diff --git a/Software/src/ws2812/fadethroughiaxis.cpp b/Software/src/ws2812/fadethroughiaxis.cpp new file mode 100644 index 0000000..991e991 --- /dev/null +++ b/Software/src/ws2812/fadethroughiaxis.cpp @@ -0,0 +1,71 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "color.h" +#include "ws2812_avr_macros.h" + +FadeThroughIAxis::FadeThroughIAxis(Color& cFrom, Color& cTo, uint16_t stepCount) : step_count(stepCount), cur_step(0), cCur(cFrom) +{ + Color center; + float deltaI, tri_i_s_from; + + deltaI = fabs(cFrom.i - cTo.i); + tri_i_s_from = sqrt(pow(deltaI, 2) / 4 + pow(cFrom.s, 2)); + from_step_count = tri_i_s_from / (tri_i_s_from + sqrt(pow(deltaI, 2) / 4 + pow(cTo.s, 2))) * step_count; + to_step_count = step_count - from_step_count; + + center.i = fmin(cFrom.i, cTo.i) + deltaI / 2; + center.h = 0.0; + center.s = 0.0; + + float h_from_step_; + /* shortest */ + h_from_step_ = center.h - cFrom.h; + if (fabs(h_from_step_) > 180.0) + h_from_step_ = _change_pos_neg(h_from_step_) * _360_min_fabs(h_from_step_); + h_from_step = h_from_step_ / (float)from_step_count; + s_from_step = (center.s - cFrom.s) / (float)from_step_count; + i_from_step = (center.i - cFrom.i) / (float)from_step_count; + + float h_to_step_; + /* shortest */ + h_to_step_ = cTo.h - center.h; + if (fabs(h_to_step_) > 180.0) + h_to_step_ = _change_pos_neg(h_to_step_) * _360_min_fabs(h_to_step_); + h_to_step = h_to_step_; + s_to_step = (cTo.s - center.s) / (float)to_step_count; + i_to_step = (cTo.i - center.i) / (float)to_step_count; +} + +uint8_t FadeThroughIAxis::next(void) +{ + if (cur_step++ < from_step_count) { + cCur.hsi2rgb(cCur.h + h_from_step, cCur.s + s_from_step, cCur.i + i_from_step); + return 1; + } else if (cur_step++ < step_count) { + cCur.hsi2rgb(cCur.h + h_to_step, cCur.s + s_to_step, cCur.i + i_to_step); + return 1; + } + return 0; +} + +Color FadeThroughIAxis::get_cur_color(void) +{ + return cCur; +} diff --git a/Software/src/ws2812/light_ws2812.cpp b/Software/src/ws2812/light_ws2812.cpp new file mode 100644 index 0000000..1bba322 --- /dev/null +++ b/Software/src/ws2812/light_ws2812.cpp @@ -0,0 +1,156 @@ +/* +* light weight WS2812 lib V2.1 - Arduino support +* +* Controls WS2811/WS2812/WS2812B RGB-LEDs +* Author: Tim (cpldcpu@gmail.com) +* +* Jan 18th, 2014 v2.0b Initial Version +* March 7th, 2014 v2.1 Added option to retarget the port register during runtime +* Removes inlining to allow compiling with c++ +* +* License: GNU GPL v2 (see LICENSE) +*/ + +#include "ws2812.h" + +/* + 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 3 +#define w_fixedhigh 6 +#define w_fixedtotal 10 + +// 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 WS2812::ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi,uint8_t *port, uint8_t *portreg) +{ + uint8_t curbyte,ctr,masklo; + uint8_t sreg_prev; + + masklo = ~maskhi & *port; + maskhi |= *port; + sreg_prev=SREG; + cli(); + + while (datlen--) { + curbyte=*data++; + + asm volatile( + " ldi %0,8 \n\t" + "loop%=: \n\t" + " st X,%3 \n\t" // '1' [02] '0' [02] - 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' [04] '0' [03] + " st X,%4 \n\t" // '1' [--] '0' [05] - fe-low + " lsl %1 \n\t" // '1' [05] '0' [06] +#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 + " brcc skipone%= \n\t" // '1' [+1] '0' [+2] - + " st X,%4 \n\t" // '1' [+3] '0' [--] - fe-high + "skipone%=: " // '1' [+3] '0' [+2] - + +#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' [+4] '0' [+3] + " brne loop%=\n\t" // '1' [+5] '0' [+4] + : "=&d" (ctr) +// : "r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_PORTREG)), "r" (maskhi), "r" (masklo) + : "r" (curbyte), "x" (port), "r" (maskhi), "r" (masklo) + ); + } + + SREG=sreg_prev; +} diff --git a/Software/src/ws2812/ws2812.cpp b/Software/src/ws2812/ws2812.cpp new file mode 100644 index 0000000..289cee0 --- /dev/null +++ b/Software/src/ws2812/ws2812.cpp @@ -0,0 +1,53 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "ws2812.h" + +WS2812::WS2812(int ledCount) { + count_led = ledCount; + pixels = (uint8_t*) malloc(count_led * 3); +} + +void WS2812::sync(void) { + *ws2812_port_reg |= pinMask; + ws2812_sendarray_mask(pixels, 3 * count_led, pinMask, + (uint8_t*) ws2812_port, (uint8_t*) ws2812_port_reg); +} + +/* &PORTB, &DDRB, DDB2 */ +void WS2812::set_output(const volatile uint8_t* port, volatile uint8_t* reg, + uint8_t pin) { + pinMask = (1 << pin); + ws2812_port = port; + ws2812_port_reg = reg; +} + +uint8_t WS2812::set_rgb_at(uint16_t index, Color &pixel) { + if (index < count_led) { + uint16_t tmp; + tmp = index * 3; + + pixels[OFFSET_R(tmp)] = pixel.r; + pixels[OFFSET_G(tmp)] = pixel.g; + pixels[OFFSET_B(tmp)] = pixel.b; + + return 1; + } + return 0; +} diff --git a/Software/src/ws2812/ws2812.h b/Software/src/ws2812/ws2812.h new file mode 100644 index 0000000..856cf51 --- /dev/null +++ b/Software/src/ws2812/ws2812.h @@ -0,0 +1,87 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef WS2812_H__ +#define WS2812_H__ + +#include +#include +#include +#include + +#include "color.h" + +#define OFFSET_R(r) r+1 +#define OFFSET_G(g) g +#define OFFSET_B(b) b+2 + +class WS2812 +{ +public: + /** + * @param num_led number of WS2812 leds + */ + WS2812(int ledCount); + ~WS2812(void); + + /** + * sets a pin as signal output + * @param port PORTx + * @param reg DDRx + * @param pin DDBy + */ + void set_output(const volatile uint8_t* port, volatile uint8_t* reg, uint8_t pin); + + /** + * get number of leds + * @return number of leds + */ + uint16_t get_led_count(void); + + /** + * get rgb values of a led + * @param index number of the led + * @return Color object with rgb values + */ + Color get_rgb_at(uint16_t index); + /** + * set rgb values of a led + * @param index number of the led + * @param pixel Color object with rgb values + * @return 1 if successful, 0 if not + */ + uint8_t set_rgb_at(uint16_t index, Color &pixel); + + /** + * synchronize the leds with the set color values + */ + void sync(void); + +private: + uint16_t count_led; + uint8_t *pixels; + + void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask, uint8_t *port, uint8_t *portreg); + + const volatile uint8_t *ws2812_port; + volatile uint8_t *ws2812_port_reg; + uint8_t pinMask; +}; + + + +#endif diff --git a/Software/src/ws2812/ws2812_avr_macros.h b/Software/src/ws2812/ws2812_avr_macros.h new file mode 100644 index 0000000..13f094c --- /dev/null +++ b/Software/src/ws2812/ws2812_avr_macros.h @@ -0,0 +1,39 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * clamps x to interval [0,1] + */ +#define clamp_to_0_1(x) (x>0?(x<1?x:1):0) +/** + * clamps x to interval [0,255] + */ +#define clamp_to_0_255(x) (x>0?(x<255?x:255):0) +/** + * function + * + * 360 - |x| + */ +#define _360_min_fabs(x) (360.0 - fabs(x)) +/** + * function + * + * x + * - ----- + * |x| + */ +#define _change_pos_neg(x) (-1.0 * x / fabs(x)) diff --git a/Software/src/ws2812/ws2812_deconstructor.cpp b/Software/src/ws2812/ws2812_deconstructor.cpp new file mode 100644 index 0000000..e508d1a --- /dev/null +++ b/Software/src/ws2812/ws2812_deconstructor.cpp @@ -0,0 +1,25 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "ws2812.h" + +WS2812::~WS2812(void) +{ + free(pixels); +} diff --git a/Software/src/ws2812/ws2812_get_led_count.cpp b/Software/src/ws2812/ws2812_get_led_count.cpp new file mode 100644 index 0000000..9b5bec9 --- /dev/null +++ b/Software/src/ws2812/ws2812_get_led_count.cpp @@ -0,0 +1,23 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ws2812.h" + +uint16_t WS2812::get_led_count(void) +{ + return count_led; +} diff --git a/Software/src/ws2812/ws2812_get_rgb_at.cpp b/Software/src/ws2812/ws2812_get_rgb_at.cpp new file mode 100644 index 0000000..5427839 --- /dev/null +++ b/Software/src/ws2812/ws2812_get_rgb_at.cpp @@ -0,0 +1,34 @@ +/* + * A library for avr microcontrollers to control WS2812 leds + * + * Copyright (C) 2016 Markus Schmidl + * + * 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ws2812.h" + +Color WS2812::get_rgb_at(uint16_t index) +{ + Color pixel; + + if (index < count_led) { + uint16_t tmp; + tmp = index * 3; + + pixel.r = pixels[OFFSET_R(tmp)]; + pixel.g = pixels[OFFSET_G(tmp)]; + pixel.b = pixels[OFFSET_B(tmp)]; + } + + return pixel; +}