158 lines
3.7 KiB
C
158 lines
3.7 KiB
C
#include <malloc.h>
|
|
|
|
#include "../include/logger.h"
|
|
#include "../include/utils.h"
|
|
#include "../include/ws2801.h"
|
|
|
|
#include "../include/fader.h"
|
|
|
|
uint32_t numModules;
|
|
|
|
float fadestep = 1;
|
|
double nextFrame;
|
|
|
|
int somethingChanged = 0; // indicates when a ws2801 update is required
|
|
|
|
static const double interval = 0.01f;
|
|
|
|
struct Colour {
|
|
float red, green, blue; // value range is 0.0 to 255.0
|
|
};
|
|
|
|
struct Colour *curColour;
|
|
struct Colour *targetColour;
|
|
|
|
int fader_init(uint32_t nMod)
|
|
{
|
|
numModules = nMod;
|
|
|
|
curColour = malloc(nMod * sizeof(struct Colour));
|
|
if(!curColour) {
|
|
LOG(LVL_ERR, "fader: could not allocate the array of current colours!");
|
|
return -1;
|
|
}
|
|
|
|
targetColour = malloc(nMod * sizeof(struct Colour));
|
|
if(!targetColour) {
|
|
LOG(LVL_ERR, "fader: could not allocate the array of target colours!");
|
|
return -1;
|
|
}
|
|
|
|
for(uint32_t i = 0; i < numModules; i++) {
|
|
curColour[i].red = targetColour[i].red = 0;
|
|
curColour[i].green = targetColour[i].green = 0;
|
|
curColour[i].blue = targetColour[i].blue = 0;
|
|
}
|
|
|
|
// timestamp for the first frame
|
|
nextFrame = get_hires_time() + interval;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void fader_shutdown(void)
|
|
{
|
|
free(curColour);
|
|
free(targetColour);
|
|
}
|
|
|
|
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)
|
|
{
|
|
// The original avr implementition had a frame rate of 25fps (interval 0,04 sec.).
|
|
// This scales the fadestep to the current frame rate.
|
|
fadestep = (float)newFadestep * interval / 0.04f;
|
|
}
|
|
|
|
/*!
|
|
* 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.
|
|
*/
|
|
void fade_colour(float *cur, const float *target, int *changed)
|
|
{
|
|
float 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 < numModules; 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;
|
|
}
|
|
}
|
|
|
|
void fader_wait_frame(void)
|
|
{
|
|
sleep_until(nextFrame);
|
|
nextFrame += interval;
|
|
}
|