Let the ws2801 fade

This commit is contained in:
Thomas Kolb 2017-03-01 23:56:34 +01:00
parent 6a573d176a
commit 7b369169d2
5 changed files with 203 additions and 0 deletions

115
src/fader.cpp Normal file
View file

@ -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;
}
}

13
src/fader.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef FADER_H
#define FADER_H
#include <stdint.h>
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

View file

@ -9,6 +9,8 @@
#include "relais.h" #include "relais.h"
#include "wlan.h" #include "wlan.h"
#include "fader.h"
#include "ws2801.h"
WiFiUDP udpServer; WiFiUDP udpServer;
@ -22,6 +24,9 @@ const char *favorite_wlans[2*NWLANFAV] = {
"franken.freifunk.net", NULL "franken.freifunk.net", NULL
}; };
uint32_t fader_next_update = 0;
uint32_t fader_loop = 0;
void setup_wifi() void setup_wifi()
{ {
bool connected = false; bool connected = false;
@ -55,6 +60,14 @@ void setup()
relais_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.print("starting UDP server on port ");
Serial.println(UDP_PORT); Serial.println(UDP_PORT);
@ -76,6 +89,27 @@ void loop()
setup_wifi(); 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); /*int n = udpServer.read(buf, 512);
if(n > 0) { if(n > 0) {

29
src/ws2801.cpp Normal file
View file

@ -0,0 +1,29 @@
#include <SPI.h>
#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();
}

12
src/ws2801.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef WS2801_H
#define WS2801_H
#include <stdint.h>
#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