diff --git a/src/fader.cpp b/src/fader.cpp new file mode 100644 index 0000000..a867152 --- /dev/null +++ b/src/fader.cpp @@ -0,0 +1,115 @@ +#include "ws2801.h" + +#include "fader.h" + +int16_t fadestep = 1; + +int somethingChanged = 0; // indicates when a ws2801 update is required + +struct Colour { + int16_t red, green, blue; // value range is 0 to 255 +}; + +struct Colour curColour[NUM_MODULES]; +struct Colour targetColour[NUM_MODULES]; + +void fader_init(void) +{ + for(uint32_t i = 0; i < NUM_MODULES; i++) { + curColour[i].red = targetColour[i].red = 0; + curColour[i].green = targetColour[i].green = 0; + curColour[i].blue = targetColour[i].blue = 0; + } +} + +void fader_set_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b) +{ + curColour[module].red = targetColour[module].red = r; + curColour[module].green = targetColour[module].green = g; + curColour[module].blue = targetColour[module].blue = b; + + somethingChanged = 1; +} + +void fader_fade_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b) +{ + targetColour[module].red = r; + targetColour[module].green = g; + targetColour[module].blue = b; +} + +void fader_add_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b) +{ + curColour[module].red += r; + curColour[module].green += g; + curColour[module].blue += b; + + if(curColour[module].red > 255) { curColour[module].red = 255; } + if(curColour[module].green > 255) { curColour[module].green = 255; } + if(curColour[module].blue > 255) { curColour[module].blue = 255; } + + targetColour[module].red += r; + targetColour[module].green += g; + targetColour[module].blue += b; + + if(targetColour[module].red > 255) { targetColour[module].red = 255; } + if(targetColour[module].green > 255) { targetColour[module].green = 255; } + if(targetColour[module].blue > 255) { targetColour[module].blue = 255; } + + somethingChanged = 1; +} + +void fader_set_fadestep(uint8_t newFadestep) +{ + fadestep = newFadestep; +} + +/*! + * Fade the colour value in cur towards target. + * + * \param cur The colour value to update. + * \param target The target value that should be reached. + * \param changed Output value which is set to 1 if cur was changed. + */ +static void fade_colour(int16_t *cur, const int16_t *target, int *changed) +{ + int16_t diff; + if(*cur > *target) { + diff = *cur - *target; + if(diff < fadestep) { + *cur = *target; + } else { + *cur -= fadestep; + } + + *changed = 1; + } else if(*cur < *target) { + diff = *target - *cur; + if(diff < fadestep) { + *cur = *target; + } else { + *cur += fadestep; + } + + *changed = 1; + } +} + +void fader_update(void) +{ + for(uint32_t i = 0; i < NUM_MODULES; i++) { + fade_colour(&(curColour[i].red), &(targetColour[i].red), &somethingChanged); + fade_colour(&(curColour[i].green), &(targetColour[i].green), &somethingChanged); + fade_colour(&(curColour[i].blue), &(targetColour[i].blue), &somethingChanged); + + ws2801_set_colour(i, + (uint8_t)curColour[i].red, + (uint8_t)curColour[i].green, + (uint8_t)curColour[i].blue); + } + + if(somethingChanged) { + ws2801_send_update(); + somethingChanged = 0; + } +} diff --git a/src/fader.h b/src/fader.h new file mode 100644 index 0000000..7026b1f --- /dev/null +++ b/src/fader.h @@ -0,0 +1,13 @@ +#ifndef FADER_H +#define FADER_H + +#include + +void fader_init(void); +void fader_set_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b); +void fader_fade_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b); +void fader_add_colour(uint32_t module, uint8_t r, uint8_t g, uint8_t b); +void fader_set_fadestep(uint8_t newFadestep); +void fader_update(void); + +#endif // FADER_H diff --git a/src/main.cpp b/src/main.cpp index e5b24c8..21c98f7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,8 @@ #include "relais.h" #include "wlan.h" +#include "fader.h" +#include "ws2801.h" WiFiUDP udpServer; @@ -22,6 +24,9 @@ const char *favorite_wlans[2*NWLANFAV] = { "franken.freifunk.net", NULL }; +uint32_t fader_next_update = 0; +uint32_t fader_loop = 0; + void setup_wifi() { bool connected = false; @@ -55,6 +60,14 @@ void setup() relais_setup(); + ws2801_init(); + fader_init(); + + for(int i = 0; i < NUM_MODULES; i++) { + fader_set_colour(i, 0, 0, 0); + fader_fade_colour(i, 0, 255, 0); + } + Serial.print("starting UDP server on port "); Serial.println(UDP_PORT); @@ -76,6 +89,27 @@ void loop() setup_wifi(); } + uint32_t now = millis(); + if(now > fader_next_update) { + fader_update(); + + fader_next_update += 20; // -> 50 FPS + + if((fader_loop % 50) == 0) { + if(((fader_loop / 50) % 2) == 0) { + for(int i = 0; i < NUM_MODULES; i++) { + fader_fade_colour(i, 0, 255, 0); + } + } else { + for(int i = 0; i < NUM_MODULES; i++) { + fader_fade_colour(i, 255, 0, 0); + } + } + } + + fader_loop++; + } + /*int n = udpServer.read(buf, 512); if(n > 0) { diff --git a/src/ws2801.cpp b/src/ws2801.cpp new file mode 100644 index 0000000..8a853ae --- /dev/null +++ b/src/ws2801.cpp @@ -0,0 +1,29 @@ +#include + +#include "ws2801.h" + +uint8_t message[3 * NUM_MODULES]; + +void ws2801_init(void) +{ + SPI.begin(); +} + +void ws2801_set_colour(uint32_t module, uint8_t red, uint8_t green, uint8_t blue) +{ + message[3*module + 0] = red; + message[3*module + 1] = blue; + message[3*module + 2] = green; +} + +void ws2801_send_update(void) +{ + SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); + + for(uint32_t i = 0; i < 3*NUM_MODULES; i++) { + SPI.transfer(message[i]); + } + + SPI.endTransaction(); +} + diff --git a/src/ws2801.h b/src/ws2801.h new file mode 100644 index 0000000..ba34923 --- /dev/null +++ b/src/ws2801.h @@ -0,0 +1,12 @@ +#ifndef WS2801_H +#define WS2801_H + +#include + +#define NUM_MODULES 32 + +void ws2801_init(void); +void ws2801_set_colour(uint32_t module, uint8_t red, uint8_t green, uint8_t blue); +void ws2801_send_update(void); + +#endif // WS2801_H