Ported musiclight to RGBW LEDs
Not all scripts are ported yet...
This commit is contained in:
parent
57b2fa6cbc
commit
0a76acd85b
4
Makefile
4
Makefile
|
@ -6,8 +6,8 @@ CFLAGS+=-O2 -Wall -march=native -pedantic -std=c99 -D_POSIX_C_SOURCE=20120607L -
|
||||||
LIBS=-lm -lpthread -lrt $(LUA_LIBS)
|
LIBS=-lm -lpthread -lrt $(LUA_LIBS)
|
||||||
|
|
||||||
TARGET=musiclight2
|
TARGET=musiclight2
|
||||||
SOURCE=main.c fft.c utils.c ws2801.c lua_utils.c lua_wrappers.c lut.c
|
SOURCE=main.c fft.c utils.c sk6812.c lua_utils.c lua_wrappers.c lut.c
|
||||||
DEPS=config.h fft.h utils.h ws2801.h lua_utils.h lua_wrappers.h lut.h
|
DEPS=config.h fft.h utils.h sk6812.h lua_utils.h lua_wrappers.h lut.h
|
||||||
|
|
||||||
OBJ=$(patsubst %.c, %.o, $(SOURCE))
|
OBJ=$(patsubst %.c, %.o, $(SOURCE))
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
WS2801_HOST = "192.168.2.136"
|
WS2801_HOST = "zybot"
|
||||||
WS2801_PORT = 2703
|
WS2801_PORT = 2703
|
||||||
|
|
||||||
NUM_MODULES = 128
|
NUM_MODULES = 300
|
||||||
CENTER_MODULE = 64
|
CENTER_MODULE = 150
|
||||||
|
|
||||||
GAMMA = 2.0
|
GAMMA = 2.0
|
||||||
|
|
50
flame.lua
50
flame.lua
|
@ -1,13 +1,14 @@
|
||||||
COOLDOWN_FACTOR = 0.9995
|
COOLDOWN_FACTOR = 0.9998
|
||||||
OVERDRIVE = 1.70
|
OVERDRIVE = 1.70
|
||||||
EXPONENT = 1.5
|
EXPONENT = 1.5
|
||||||
|
W_EXPONENT = 2.2
|
||||||
|
|
||||||
M = 1.7 -- mass
|
M = 1.0--1.7 -- mass
|
||||||
D = 1 -- spring strength
|
D = 1 -- spring strength
|
||||||
DAMPING = {} -- filled in init()
|
DAMPING = {} -- filled in init()
|
||||||
|
|
||||||
num_modules = 128
|
num_modules = 300
|
||||||
center_module = 64
|
center_module = 150
|
||||||
|
|
||||||
num_masses = math.floor(num_modules/2)
|
num_masses = math.floor(num_modules/2)
|
||||||
excitement_pos = 1
|
excitement_pos = 1
|
||||||
|
@ -16,28 +17,34 @@ excitement_pos = 1
|
||||||
maxRedEnergy = 1
|
maxRedEnergy = 1
|
||||||
maxGreenEnergy = 1
|
maxGreenEnergy = 1
|
||||||
maxBlueEnergy = 1
|
maxBlueEnergy = 1
|
||||||
|
maxWhiteEnergy = 1
|
||||||
|
|
||||||
-- spring-mass-grid values
|
-- spring-mass-grid values
|
||||||
pos_r = {}
|
pos_r = {}
|
||||||
pos_g = {}
|
pos_g = {}
|
||||||
pos_b = {}
|
pos_b = {}
|
||||||
|
pos_w = {}
|
||||||
|
|
||||||
vel_r = {}
|
vel_r = {}
|
||||||
vel_g = {}
|
vel_g = {}
|
||||||
vel_b = {}
|
vel_b = {}
|
||||||
|
vel_w = {}
|
||||||
|
|
||||||
acc_r = {}
|
acc_r = {}
|
||||||
acc_g = {}
|
acc_g = {}
|
||||||
acc_b = {}
|
acc_b = {}
|
||||||
|
acc_w = {}
|
||||||
|
|
||||||
-- output color buffers
|
-- output color buffers
|
||||||
red = {}
|
red = {}
|
||||||
green = {}
|
green = {}
|
||||||
blue = {}
|
blue = {}
|
||||||
|
white = {}
|
||||||
|
|
||||||
r_tmp = {}
|
r_tmp = {}
|
||||||
g_tmp = {}
|
g_tmp = {}
|
||||||
b_tmp = {}
|
b_tmp = {}
|
||||||
|
w_tmp = {}
|
||||||
|
|
||||||
function limit(val)
|
function limit(val)
|
||||||
if val > 1 then
|
if val > 1 then
|
||||||
|
@ -52,9 +59,12 @@ end
|
||||||
function periodic()
|
function periodic()
|
||||||
local redEnergy = get_energy_in_band(0, 400);
|
local redEnergy = get_energy_in_band(0, 400);
|
||||||
local greenEnergy = get_energy_in_band(400, 4000);
|
local greenEnergy = get_energy_in_band(400, 4000);
|
||||||
local blueEnergy = get_energy_in_band(4000, 22000);
|
local blueEnergy = get_energy_in_band(4000, 12000);
|
||||||
|
local whiteEnergy = get_energy_in_band(12000, 22000);
|
||||||
local centerIndex = 2 * center_module + 1;
|
local centerIndex = 2 * center_module + 1;
|
||||||
|
|
||||||
|
print(maxRedEnergy .. "\t" .. maxGreenEnergy .. "\t" .. maxBlueEnergy .. "\t" .. maxWhiteEnergy)
|
||||||
|
|
||||||
maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR
|
maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR
|
||||||
if redEnergy > maxRedEnergy then
|
if redEnergy > maxRedEnergy then
|
||||||
maxRedEnergy = redEnergy
|
maxRedEnergy = redEnergy
|
||||||
|
@ -70,6 +80,11 @@ function periodic()
|
||||||
maxBlueEnergy = blueEnergy
|
maxBlueEnergy = blueEnergy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
maxWhiteEnergy = maxWhiteEnergy * COOLDOWN_FACTOR
|
||||||
|
if whiteEnergy > maxWhiteEnergy then
|
||||||
|
maxWhiteEnergy = whiteEnergy
|
||||||
|
end
|
||||||
|
|
||||||
-- update the spring-mass string
|
-- update the spring-mass string
|
||||||
|
|
||||||
-- the outside masses are special, as they are auto-returned to 0 position
|
-- the outside masses are special, as they are auto-returned to 0 position
|
||||||
|
@ -77,16 +92,19 @@ function periodic()
|
||||||
--acc_r[1] = (-pos_r[1] + (pos_r[2] - pos_r[1])) * D / M
|
--acc_r[1] = (-pos_r[1] + (pos_r[2] - pos_r[1])) * D / M
|
||||||
--acc_g[1] = (-pos_g[1] + (pos_g[2] - pos_g[1])) * D / M
|
--acc_g[1] = (-pos_g[1] + (pos_g[2] - pos_g[1])) * D / M
|
||||||
--acc_b[1] = (-pos_b[1] + (pos_b[2] - pos_b[1])) * D / M
|
--acc_b[1] = (-pos_b[1] + (pos_b[2] - pos_b[1])) * D / M
|
||||||
|
--acc_w[1] = (-pos_w[1] + (pos_w[2] - pos_w[1])) * D / M
|
||||||
|
|
||||||
acc_r[num_masses] = (-pos_r[num_masses] + (pos_r[num_masses-1] - pos_r[num_masses])) * D / M
|
acc_r[num_masses] = (-pos_r[num_masses] + (pos_r[num_masses-1] - pos_r[num_masses])) * D / M
|
||||||
acc_g[num_masses] = (-pos_g[num_masses] + (pos_g[num_masses-1] - pos_g[num_masses])) * D / M
|
acc_g[num_masses] = (-pos_g[num_masses] + (pos_g[num_masses-1] - pos_g[num_masses])) * D / M
|
||||||
acc_b[num_masses] = (-pos_b[num_masses] + (pos_b[num_masses-1] - pos_b[num_masses])) * D / M
|
acc_b[num_masses] = (-pos_b[num_masses] + (pos_b[num_masses-1] - pos_b[num_masses])) * D / M
|
||||||
|
acc_w[num_masses] = (-pos_w[num_masses] + (pos_w[num_masses-1] - pos_w[num_masses])) * D / M
|
||||||
|
|
||||||
-- inside masses are only influenced by their neighbors
|
-- inside masses are only influenced by their neighbors
|
||||||
for i = 2,num_masses-1 do
|
for i = 2,num_masses-1 do
|
||||||
acc_r[i] = (pos_r[i-1] + pos_r[i+1] - 2 * pos_r[i]) * D / M
|
acc_r[i] = (pos_r[i-1] + pos_r[i+1] - 2 * pos_r[i]) * D / M
|
||||||
acc_g[i] = (pos_g[i-1] + pos_g[i+1] - 2 * pos_g[i]) * D / M
|
acc_g[i] = (pos_g[i-1] + pos_g[i+1] - 2 * pos_g[i]) * D / M
|
||||||
acc_b[i] = (pos_b[i-1] + pos_b[i+1] - 2 * pos_b[i]) * D / M
|
acc_b[i] = (pos_b[i-1] + pos_b[i+1] - 2 * pos_b[i]) * D / M
|
||||||
|
acc_w[i] = (pos_w[i-1] + pos_w[i+1] - 2 * pos_w[i]) * D / M
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update velocity and position
|
-- update velocity and position
|
||||||
|
@ -94,10 +112,12 @@ function periodic()
|
||||||
vel_r[i] = DAMPING[i] * (vel_r[i] + acc_r[i])
|
vel_r[i] = DAMPING[i] * (vel_r[i] + acc_r[i])
|
||||||
vel_g[i] = DAMPING[i] * (vel_g[i] + acc_g[i])
|
vel_g[i] = DAMPING[i] * (vel_g[i] + acc_g[i])
|
||||||
vel_b[i] = DAMPING[i] * (vel_b[i] + acc_b[i])
|
vel_b[i] = DAMPING[i] * (vel_b[i] + acc_b[i])
|
||||||
|
vel_w[i] = DAMPING[i] * (vel_w[i] + acc_w[i])
|
||||||
|
|
||||||
pos_r[i] = pos_r[i] + vel_r[i]
|
pos_r[i] = pos_r[i] + vel_r[i]
|
||||||
pos_g[i] = pos_g[i] + vel_g[i]
|
pos_g[i] = pos_g[i] + vel_g[i]
|
||||||
pos_b[i] = pos_b[i] + vel_b[i]
|
pos_b[i] = pos_b[i] + vel_b[i]
|
||||||
|
pos_w[i] = pos_w[i] + vel_w[i]
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set the new position for the center module
|
-- set the new position for the center module
|
||||||
|
@ -108,23 +128,30 @@ function periodic()
|
||||||
|
|
||||||
newGreen = greenEnergy / maxGreenEnergy
|
newGreen = greenEnergy / maxGreenEnergy
|
||||||
pos_g[excitement_pos] = newGreen
|
pos_g[excitement_pos] = newGreen
|
||||||
vel_b[excitement_pos] = 0
|
vel_g[excitement_pos] = 0
|
||||||
acc_b[excitement_pos] = 0
|
acc_g[excitement_pos] = 0
|
||||||
|
|
||||||
newBlue = blueEnergy / maxBlueEnergy
|
newBlue = blueEnergy / maxBlueEnergy
|
||||||
pos_b[excitement_pos] = newBlue
|
pos_b[excitement_pos] = newBlue
|
||||||
vel_b[excitement_pos] = 0
|
vel_b[excitement_pos] = 0
|
||||||
acc_b[excitement_pos] = 0
|
acc_b[excitement_pos] = 0
|
||||||
|
|
||||||
|
newWhite = whiteEnergy / maxWhiteEnergy
|
||||||
|
pos_w[excitement_pos] = newWhite
|
||||||
|
vel_w[excitement_pos] = 0
|
||||||
|
acc_w[excitement_pos] = 0
|
||||||
|
|
||||||
-- map to LED modules
|
-- map to LED modules
|
||||||
for i = 1,num_masses do
|
for i = 1,num_masses do
|
||||||
r_tmp[i] = pos_r[i]
|
r_tmp[i] = pos_r[i]
|
||||||
g_tmp[i] = pos_g[i]
|
g_tmp[i] = pos_g[i]
|
||||||
b_tmp[i] = pos_b[i]
|
b_tmp[i] = pos_b[i]
|
||||||
|
w_tmp[i] = pos_w[i]
|
||||||
|
|
||||||
r_tmp[num_modules-i+1] = pos_r[i]
|
r_tmp[num_modules-i+1] = pos_r[i]
|
||||||
g_tmp[num_modules-i+1] = pos_g[i]
|
g_tmp[num_modules-i+1] = pos_g[i]
|
||||||
b_tmp[num_modules-i+1] = pos_b[i]
|
b_tmp[num_modules-i+1] = pos_b[i]
|
||||||
|
w_tmp[num_modules-i+1] = pos_w[i]
|
||||||
|
|
||||||
--print(i, pos_r[i])
|
--print(i, pos_r[i])
|
||||||
end
|
end
|
||||||
|
@ -134,10 +161,11 @@ function periodic()
|
||||||
red[i] = limit(OVERDRIVE * math.pow(r_tmp[i], EXPONENT))
|
red[i] = limit(OVERDRIVE * math.pow(r_tmp[i], EXPONENT))
|
||||||
green[i] = limit(OVERDRIVE * math.pow(g_tmp[i], EXPONENT))
|
green[i] = limit(OVERDRIVE * math.pow(g_tmp[i], EXPONENT))
|
||||||
blue[i] = limit(OVERDRIVE * math.pow(b_tmp[i], EXPONENT))
|
blue[i] = limit(OVERDRIVE * math.pow(b_tmp[i], EXPONENT))
|
||||||
|
white[i] = limit(OVERDRIVE * math.pow(w_tmp[i], W_EXPONENT))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- return the 3 color arrays
|
-- return the 3 color arrays
|
||||||
return red, green, blue
|
return red, green, blue, white
|
||||||
end
|
end
|
||||||
|
|
||||||
function init(nmod, cmod)
|
function init(nmod, cmod)
|
||||||
|
@ -151,22 +179,26 @@ function init(nmod, cmod)
|
||||||
red[i] = 0
|
red[i] = 0
|
||||||
green[i] = 0
|
green[i] = 0
|
||||||
blue[i] = 0
|
blue[i] = 0
|
||||||
|
white[i] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1,num_masses do
|
for i = 1,num_masses do
|
||||||
pos_r[i] = 0
|
pos_r[i] = 0
|
||||||
pos_g[i] = 0
|
pos_g[i] = 0
|
||||||
pos_b[i] = 0
|
pos_b[i] = 0
|
||||||
|
pos_w[i] = 0
|
||||||
|
|
||||||
vel_r[i] = 0
|
vel_r[i] = 0
|
||||||
vel_g[i] = 0
|
vel_g[i] = 0
|
||||||
vel_b[i] = 0
|
vel_b[i] = 0
|
||||||
|
vel_w[i] = 0
|
||||||
|
|
||||||
acc_r[i] = 0
|
acc_r[i] = 0
|
||||||
acc_g[i] = 0
|
acc_g[i] = 0
|
||||||
acc_b[i] = 0
|
acc_b[i] = 0
|
||||||
|
acc_w[i] = 0
|
||||||
|
|
||||||
DAMPING[i] = 1 - 0.08 * math.pow(math.abs((i - excitement_pos) / num_masses), 2)
|
DAMPING[i] = 1 - 0.06 * math.pow(math.abs((i - excitement_pos) / num_masses), 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- don't use fading
|
-- don't use fading
|
||||||
|
|
48
main.c
48
main.c
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include "fft.h"
|
#include "fft.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "ws2801.h"
|
#include "sk6812.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
@ -74,16 +74,20 @@ void* fft_thread(void *param) {
|
||||||
|
|
||||||
memcpy(block, buffer, BLOCK_LEN * sizeof(sample));
|
memcpy(block, buffer, BLOCK_LEN * sizeof(sample));
|
||||||
|
|
||||||
apply_hanning(block);
|
|
||||||
fft_transform(block, fftOutReal, fftOutImag);
|
|
||||||
complex_to_absolute(fftOutReal, fftOutImag, tmpFFT);
|
|
||||||
|
|
||||||
tmpRMS = 0;
|
tmpRMS = 0;
|
||||||
for(i = 0; i < BLOCK_LEN; i++) {
|
for(i = 0; i < BLOCK_LEN; i++) {
|
||||||
tmpRMS += buffer[i]*buffer[i];
|
tmpRMS += buffer[i]*buffer[i];
|
||||||
}
|
}
|
||||||
tmpRMS = sqrt(tmpRMS/BLOCK_LEN);
|
tmpRMS = sqrt(tmpRMS/BLOCK_LEN);
|
||||||
|
|
||||||
|
if(tmpRMS == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_hanning(block);
|
||||||
|
fft_transform(block, fftOutReal, fftOutImag);
|
||||||
|
complex_to_absolute(fftOutReal, fftOutImag, tmpFFT);
|
||||||
|
|
||||||
// --- SAFE SECTION ---
|
// --- SAFE SECTION ---
|
||||||
sem_wait(&fftSemaphore);
|
sem_wait(&fftSemaphore);
|
||||||
|
|
||||||
|
@ -130,11 +134,12 @@ int main(int argc, char **argv) {
|
||||||
pthread_t fftThread;
|
pthread_t fftThread;
|
||||||
|
|
||||||
int active = 1;
|
int active = 1;
|
||||||
int frame = 0;
|
//int frame = 0;
|
||||||
|
|
||||||
double *red;
|
double *red;
|
||||||
double *green;
|
double *green;
|
||||||
double *blue;
|
double *blue;
|
||||||
|
double *white;
|
||||||
|
|
||||||
int useFading, fadeStep;
|
int useFading, fadeStep;
|
||||||
|
|
||||||
|
@ -192,6 +197,7 @@ int main(int argc, char **argv) {
|
||||||
red = malloc(num_modules * sizeof(double));
|
red = malloc(num_modules * sizeof(double));
|
||||||
green = malloc(num_modules * sizeof(double));
|
green = malloc(num_modules * sizeof(double));
|
||||||
blue = malloc(num_modules * sizeof(double));
|
blue = malloc(num_modules * sizeof(double));
|
||||||
|
white = malloc(num_modules * sizeof(double));
|
||||||
|
|
||||||
// load and initialize the script
|
// load and initialize the script
|
||||||
if(luaL_loadfile(L, argv[1])) {
|
if(luaL_loadfile(L, argv[1])) {
|
||||||
|
@ -214,13 +220,13 @@ int main(int argc, char **argv) {
|
||||||
fadeStep = lua_tointeger(L, -1);
|
fadeStep = lua_tointeger(L, -1);
|
||||||
useFading = fadeStep > 0;
|
useFading = fadeStep > 0;
|
||||||
if(useFading) {
|
if(useFading) {
|
||||||
ws2801_set_fadestep(fadeStep);
|
sk6812_set_fadestep(fadeStep);
|
||||||
printf("Fading enabled with fadestep %i.\n", fadeStep);
|
printf("Fading enabled with fadestep %i.\n", fadeStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize the WS2801 library
|
// initialize the WS2801 library
|
||||||
printf("Connecting to %s:%i\n", host, port);
|
printf("Connecting to %s:%i\n", host, port);
|
||||||
ws2801_init(host, port);
|
sk6812_init(host, port);
|
||||||
|
|
||||||
// create semaphores
|
// create semaphores
|
||||||
sem_init(&fftSemaphore, 0, 1);
|
sem_init(&fftSemaphore, 0, 1);
|
||||||
|
@ -232,32 +238,35 @@ int main(int argc, char **argv) {
|
||||||
if(active) {
|
if(active) {
|
||||||
// call the periodic() function from LUA
|
// call the periodic() function from LUA
|
||||||
lua_getglobal(L, "periodic");
|
lua_getglobal(L, "periodic");
|
||||||
if(lua_pcall(L, 0, 3, 0)) { // no arguments, 3 return values
|
if(lua_pcall(L, 0, 4, 0)) { // no arguments, 4 return values
|
||||||
lua_showerror(L, "lua_pcall(periodic) failed.");
|
lua_showerror(L, "lua_pcall(periodic) failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the return values (reverse order, as lua uses a stack)
|
// read the return values (reverse order, as lua uses a stack)
|
||||||
|
lua_readdoublearray(L, white, num_modules);
|
||||||
lua_readdoublearray(L, blue, num_modules);
|
lua_readdoublearray(L, blue, num_modules);
|
||||||
lua_readdoublearray(L, green, num_modules);
|
lua_readdoublearray(L, green, num_modules);
|
||||||
lua_readdoublearray(L, red, num_modules);
|
lua_readdoublearray(L, red, num_modules);
|
||||||
|
|
||||||
if((++frame & 1) == 0) {
|
/*if((++frame & 1) == 0)*/ {
|
||||||
if(useFading) {
|
if(useFading) {
|
||||||
for(i = 0; i < num_modules; i++) {
|
for(i = 0; i < num_modules; i++) {
|
||||||
ws2801_fade_color(i,
|
sk6812_fade_color(i,
|
||||||
255 * gamma_correct(red[i], gamma),
|
255 * gamma_correct(red[i], gamma),
|
||||||
255 * gamma_correct(green[i], gamma),
|
255 * gamma_correct(green[i], gamma),
|
||||||
255 * gamma_correct(blue[i], gamma));
|
255 * gamma_correct(blue[i], gamma),
|
||||||
|
255 * gamma_correct(white[i], gamma));
|
||||||
}
|
}
|
||||||
ws2801_commit();
|
sk6812_commit();
|
||||||
} else {
|
} else {
|
||||||
for(i = 0; i < num_modules; i++) {
|
for(i = 0; i < num_modules; i++) {
|
||||||
ws2801_set_color(i,
|
sk6812_set_color(i,
|
||||||
255 * gamma_correct(red[i], gamma),
|
255 * gamma_correct(red[i], gamma),
|
||||||
255 * gamma_correct(green[i], gamma),
|
255 * gamma_correct(green[i], gamma),
|
||||||
255 * gamma_correct(blue[i], gamma));
|
255 * gamma_correct(blue[i], gamma),
|
||||||
|
255 * gamma_correct(white[i], gamma));
|
||||||
}
|
}
|
||||||
ws2801_commit();
|
sk6812_commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,9 +274,9 @@ int main(int argc, char **argv) {
|
||||||
printf("Idle for 1 second -> stopping updates.\n");
|
printf("Idle for 1 second -> stopping updates.\n");
|
||||||
|
|
||||||
for(i = 0; i < num_modules; i++) {
|
for(i = 0; i < num_modules; i++) {
|
||||||
ws2801_fade_color(i, 20, 20, 20);
|
sk6812_fade_color(i, 0, 0, 0, 20);
|
||||||
}
|
}
|
||||||
ws2801_commit();
|
sk6812_commit();
|
||||||
|
|
||||||
active = 0;
|
active = 0;
|
||||||
}
|
}
|
||||||
|
@ -280,12 +289,13 @@ int main(int argc, char **argv) {
|
||||||
sleep_until(nextFrame);
|
sleep_until(nextFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
ws2801_shutdown();
|
sk6812_shutdown();
|
||||||
|
|
||||||
// free arrays
|
// free arrays
|
||||||
free(red);
|
free(red);
|
||||||
free(green);
|
free(green);
|
||||||
free(blue);
|
free(blue);
|
||||||
|
free(white);
|
||||||
|
|
||||||
pthread_join(fftThread, NULL);
|
pthread_join(fftThread, NULL);
|
||||||
|
|
||||||
|
|
43
pulsar.lua
43
pulsar.lua
|
@ -2,12 +2,12 @@ COOLDOWN_FACTOR = 0.9995
|
||||||
OVERDRIVE = 1.50
|
OVERDRIVE = 1.50
|
||||||
EXPONENT = 1.5
|
EXPONENT = 1.5
|
||||||
|
|
||||||
M = 1.7 -- mass
|
M = 1.3--1.7 -- mass
|
||||||
D = 1 -- spring strength
|
D = 1 -- spring strength
|
||||||
DAMPING = {} -- filled in init()
|
DAMPING = {} -- filled in init()
|
||||||
|
|
||||||
num_modules = 128
|
num_modules = 300
|
||||||
center_module = 64
|
center_module = 150
|
||||||
|
|
||||||
num_masses = math.floor(num_modules/2)
|
num_masses = math.floor(num_modules/2)
|
||||||
excitement_pos = math.floor(center_module/2)
|
excitement_pos = math.floor(center_module/2)
|
||||||
|
@ -16,28 +16,34 @@ excitement_pos = math.floor(center_module/2)
|
||||||
maxRedEnergy = 1
|
maxRedEnergy = 1
|
||||||
maxGreenEnergy = 1
|
maxGreenEnergy = 1
|
||||||
maxBlueEnergy = 1
|
maxBlueEnergy = 1
|
||||||
|
maxWhiteEnergy = 1
|
||||||
|
|
||||||
-- spring-mass-grid values
|
-- spring-mass-grid values
|
||||||
pos_r = {}
|
pos_r = {}
|
||||||
pos_g = {}
|
pos_g = {}
|
||||||
pos_b = {}
|
pos_b = {}
|
||||||
|
pos_w = {}
|
||||||
|
|
||||||
vel_r = {}
|
vel_r = {}
|
||||||
vel_g = {}
|
vel_g = {}
|
||||||
vel_b = {}
|
vel_b = {}
|
||||||
|
vel_w = {}
|
||||||
|
|
||||||
acc_r = {}
|
acc_r = {}
|
||||||
acc_g = {}
|
acc_g = {}
|
||||||
acc_b = {}
|
acc_b = {}
|
||||||
|
acc_w = {}
|
||||||
|
|
||||||
-- output color buffers
|
-- output color buffers
|
||||||
red = {}
|
red = {}
|
||||||
green = {}
|
green = {}
|
||||||
blue = {}
|
blue = {}
|
||||||
|
white = {}
|
||||||
|
|
||||||
r_tmp = {}
|
r_tmp = {}
|
||||||
g_tmp = {}
|
g_tmp = {}
|
||||||
b_tmp = {}
|
b_tmp = {}
|
||||||
|
w_tmp = {}
|
||||||
|
|
||||||
function limit(val)
|
function limit(val)
|
||||||
if val > 1 then
|
if val > 1 then
|
||||||
|
@ -52,7 +58,8 @@ end
|
||||||
function periodic()
|
function periodic()
|
||||||
local redEnergy = get_energy_in_band(0, 400);
|
local redEnergy = get_energy_in_band(0, 400);
|
||||||
local greenEnergy = get_energy_in_band(400, 4000);
|
local greenEnergy = get_energy_in_band(400, 4000);
|
||||||
local blueEnergy = get_energy_in_band(4000, 22000);
|
local blueEnergy = get_energy_in_band(4000, 12000);
|
||||||
|
local whiteEnergy = get_energy_in_band(12000, 22000);
|
||||||
local centerIndex = 2 * center_module + 1;
|
local centerIndex = 2 * center_module + 1;
|
||||||
|
|
||||||
maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR
|
maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR
|
||||||
|
@ -70,6 +77,11 @@ function periodic()
|
||||||
maxBlueEnergy = blueEnergy
|
maxBlueEnergy = blueEnergy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
maxWhiteEnergy = maxWhiteEnergy * COOLDOWN_FACTOR
|
||||||
|
if whiteEnergy > maxWhiteEnergy then
|
||||||
|
maxWhiteEnergy = whiteEnergy
|
||||||
|
end
|
||||||
|
|
||||||
-- update the spring-mass string
|
-- update the spring-mass string
|
||||||
|
|
||||||
-- the outside masses are special, as they are auto-returned to 0 position
|
-- the outside masses are special, as they are auto-returned to 0 position
|
||||||
|
@ -77,16 +89,19 @@ function periodic()
|
||||||
acc_r[1] = (-pos_r[1] + (pos_r[2] - pos_r[1])) * D / M
|
acc_r[1] = (-pos_r[1] + (pos_r[2] - pos_r[1])) * D / M
|
||||||
acc_g[1] = (-pos_g[1] + (pos_g[2] - pos_g[1])) * D / M
|
acc_g[1] = (-pos_g[1] + (pos_g[2] - pos_g[1])) * D / M
|
||||||
acc_b[1] = (-pos_b[1] + (pos_b[2] - pos_b[1])) * D / M
|
acc_b[1] = (-pos_b[1] + (pos_b[2] - pos_b[1])) * D / M
|
||||||
|
acc_w[1] = (-pos_w[1] + (pos_w[2] - pos_w[1])) * D / M
|
||||||
|
|
||||||
acc_r[num_masses] = (-pos_r[num_masses] + (pos_r[num_masses-1] - pos_r[num_masses])) * D / M
|
acc_r[num_masses] = (-pos_r[num_masses] + (pos_r[num_masses-1] - pos_r[num_masses])) * D / M
|
||||||
acc_g[num_masses] = (-pos_g[num_masses] + (pos_g[num_masses-1] - pos_g[num_masses])) * D / M
|
acc_g[num_masses] = (-pos_g[num_masses] + (pos_g[num_masses-1] - pos_g[num_masses])) * D / M
|
||||||
acc_b[num_masses] = (-pos_b[num_masses] + (pos_b[num_masses-1] - pos_b[num_masses])) * D / M
|
acc_b[num_masses] = (-pos_b[num_masses] + (pos_b[num_masses-1] - pos_b[num_masses])) * D / M
|
||||||
|
acc_w[num_masses] = (-pos_w[num_masses] + (pos_w[num_masses-1] - pos_w[num_masses])) * D / M
|
||||||
|
|
||||||
-- inside masses are only influenced by their neighbors
|
-- inside masses are only influenced by their neighbors
|
||||||
for i = 2,num_masses-1 do
|
for i = 2,num_masses-1 do
|
||||||
acc_r[i] = (pos_r[i-1] + pos_r[i+1] - 2 * pos_r[i]) * D / M
|
acc_r[i] = (pos_r[i-1] + pos_r[i+1] - 2 * pos_r[i]) * D / M
|
||||||
acc_g[i] = (pos_g[i-1] + pos_g[i+1] - 2 * pos_g[i]) * D / M
|
acc_g[i] = (pos_g[i-1] + pos_g[i+1] - 2 * pos_g[i]) * D / M
|
||||||
acc_b[i] = (pos_b[i-1] + pos_b[i+1] - 2 * pos_b[i]) * D / M
|
acc_b[i] = (pos_b[i-1] + pos_b[i+1] - 2 * pos_b[i]) * D / M
|
||||||
|
acc_w[i] = (pos_w[i-1] + pos_w[i+1] - 2 * pos_w[i]) * D / M
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update velocity and position
|
-- update velocity and position
|
||||||
|
@ -94,10 +109,12 @@ function periodic()
|
||||||
vel_r[i] = DAMPING[i] * (vel_r[i] + acc_r[i])
|
vel_r[i] = DAMPING[i] * (vel_r[i] + acc_r[i])
|
||||||
vel_g[i] = DAMPING[i] * (vel_g[i] + acc_g[i])
|
vel_g[i] = DAMPING[i] * (vel_g[i] + acc_g[i])
|
||||||
vel_b[i] = DAMPING[i] * (vel_b[i] + acc_b[i])
|
vel_b[i] = DAMPING[i] * (vel_b[i] + acc_b[i])
|
||||||
|
vel_w[i] = DAMPING[i] * (vel_w[i] + acc_w[i])
|
||||||
|
|
||||||
pos_r[i] = pos_r[i] + vel_r[i]
|
pos_r[i] = pos_r[i] + vel_r[i]
|
||||||
pos_g[i] = pos_g[i] + vel_g[i]
|
pos_g[i] = pos_g[i] + vel_g[i]
|
||||||
pos_b[i] = pos_b[i] + vel_b[i]
|
pos_b[i] = pos_b[i] + vel_b[i]
|
||||||
|
pos_w[i] = pos_w[i] + vel_w[i]
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set the new position for the center module
|
-- set the new position for the center module
|
||||||
|
@ -108,23 +125,30 @@ function periodic()
|
||||||
|
|
||||||
newGreen = greenEnergy / maxGreenEnergy
|
newGreen = greenEnergy / maxGreenEnergy
|
||||||
pos_g[excitement_pos] = newGreen
|
pos_g[excitement_pos] = newGreen
|
||||||
vel_b[excitement_pos] = 0
|
vel_g[excitement_pos] = 0
|
||||||
acc_b[excitement_pos] = 0
|
acc_g[excitement_pos] = 0
|
||||||
|
|
||||||
newBlue = blueEnergy / maxBlueEnergy
|
newBlue = blueEnergy / maxBlueEnergy
|
||||||
pos_b[excitement_pos] = newBlue
|
pos_b[excitement_pos] = newBlue
|
||||||
vel_b[excitement_pos] = 0
|
vel_b[excitement_pos] = 0
|
||||||
acc_b[excitement_pos] = 0
|
acc_b[excitement_pos] = 0
|
||||||
|
|
||||||
|
newWhite = whiteEnergy / maxWhiteEnergy
|
||||||
|
pos_w[excitement_pos] = newWhite
|
||||||
|
vel_w[excitement_pos] = 0
|
||||||
|
acc_w[excitement_pos] = 0
|
||||||
|
|
||||||
-- map to LED modules
|
-- map to LED modules
|
||||||
for i = 1,num_masses do
|
for i = 1,num_masses do
|
||||||
r_tmp[i] = pos_r[i]
|
r_tmp[i] = pos_r[i]
|
||||||
g_tmp[i] = pos_g[i]
|
g_tmp[i] = pos_g[i]
|
||||||
b_tmp[i] = pos_b[i]
|
b_tmp[i] = pos_b[i]
|
||||||
|
w_tmp[i] = pos_w[i]
|
||||||
|
|
||||||
r_tmp[num_modules-i+1] = pos_r[i]
|
r_tmp[num_modules-i+1] = pos_r[i]
|
||||||
g_tmp[num_modules-i+1] = pos_g[i]
|
g_tmp[num_modules-i+1] = pos_g[i]
|
||||||
b_tmp[num_modules-i+1] = pos_b[i]
|
b_tmp[num_modules-i+1] = pos_b[i]
|
||||||
|
w_tmp[num_modules-i+1] = pos_w[i]
|
||||||
|
|
||||||
--print(i, pos_r[i])
|
--print(i, pos_r[i])
|
||||||
end
|
end
|
||||||
|
@ -134,10 +158,11 @@ function periodic()
|
||||||
red[i] = limit(OVERDRIVE * math.pow(r_tmp[i], EXPONENT))
|
red[i] = limit(OVERDRIVE * math.pow(r_tmp[i], EXPONENT))
|
||||||
green[i] = limit(OVERDRIVE * math.pow(g_tmp[i], EXPONENT))
|
green[i] = limit(OVERDRIVE * math.pow(g_tmp[i], EXPONENT))
|
||||||
blue[i] = limit(OVERDRIVE * math.pow(b_tmp[i], EXPONENT))
|
blue[i] = limit(OVERDRIVE * math.pow(b_tmp[i], EXPONENT))
|
||||||
|
white[i] = limit(OVERDRIVE * math.pow(w_tmp[i], EXPONENT))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- return the 3 color arrays
|
-- return the 3 color arrays
|
||||||
return red, green, blue
|
return red, green, blue, white
|
||||||
end
|
end
|
||||||
|
|
||||||
function init(nmod, cmod)
|
function init(nmod, cmod)
|
||||||
|
@ -151,20 +176,24 @@ function init(nmod, cmod)
|
||||||
red[i] = 0
|
red[i] = 0
|
||||||
green[i] = 0
|
green[i] = 0
|
||||||
blue[i] = 0
|
blue[i] = 0
|
||||||
|
white[i] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1,num_masses do
|
for i = 1,num_masses do
|
||||||
pos_r[i] = 0
|
pos_r[i] = 0
|
||||||
pos_g[i] = 0
|
pos_g[i] = 0
|
||||||
pos_b[i] = 0
|
pos_b[i] = 0
|
||||||
|
pos_w[i] = 0
|
||||||
|
|
||||||
vel_r[i] = 0
|
vel_r[i] = 0
|
||||||
vel_g[i] = 0
|
vel_g[i] = 0
|
||||||
vel_b[i] = 0
|
vel_b[i] = 0
|
||||||
|
vel_w[i] = 0
|
||||||
|
|
||||||
acc_r[i] = 0
|
acc_r[i] = 0
|
||||||
acc_g[i] = 0
|
acc_g[i] = 0
|
||||||
acc_b[i] = 0
|
acc_b[i] = 0
|
||||||
|
acc_w[i] = 0
|
||||||
|
|
||||||
DAMPING[i] = 1 - 0.5 * math.pow(math.abs((i - excitement_pos) / num_masses), 2)
|
DAMPING[i] = 1 - 0.5 * math.pow(math.abs((i - excitement_pos) / num_masses), 2)
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@ case "$MODE" in
|
||||||
|
|
||||||
*)
|
*)
|
||||||
# soundkarte
|
# soundkarte
|
||||||
parec -d "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor" --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2 $*
|
parec --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2 $*
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
socat UDP4-RECV:12345 STDOUT | ./musiclight2 $*
|
socat TCP:cubietruck:6601 STDOUT | ./musiclight2 $*
|
||||||
|
|
|
@ -16,25 +16,25 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "ws2801.h"
|
#include "sk6812.h"
|
||||||
|
|
||||||
#define SET_COLOR 0
|
#define SET_COLOR 0
|
||||||
#define FADE_COLOR 1
|
#define FADE_COLOR 1
|
||||||
#define ADD_COLOR 2
|
#define ADD_COLOR 2
|
||||||
#define SET_FADESTEP 3
|
#define SET_FADESTEP 3
|
||||||
|
|
||||||
struct WS2801Packet {
|
struct __attribute__((__packed__)) SK6812Packet {
|
||||||
uint8_t action;
|
uint8_t action;
|
||||||
uint8_t module;
|
uint16_t module;
|
||||||
uint8_t data[3];
|
uint8_t data[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
int ws2801_socket = -1;
|
int sk6812_socket = -1;
|
||||||
struct WS2801Packet packetQueue[1024];
|
struct __attribute__((__packed__)) SK6812Packet packetQueue[1024];
|
||||||
int queueIndex = 0;
|
int queueIndex = 0;
|
||||||
|
|
||||||
// creates the socket needed for steering the LED strip
|
// creates the socket needed for steering the LED strip
|
||||||
int ws2801_init(const char *host, unsigned short port) {
|
int sk6812_init(const char *host, unsigned short port) {
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result;
|
struct addrinfo *result;
|
||||||
char portstr[6];
|
char portstr[6];
|
||||||
|
@ -52,14 +52,14 @@ int ws2801_init(const char *host, unsigned short port) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ws2801_socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
sk6812_socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||||
if (ws2801_socket == -1) {
|
if (sk6812_socket == -1) {
|
||||||
perror("socket() failed");
|
perror("socket() failed");
|
||||||
freeaddrinfo(result);
|
freeaddrinfo(result);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(ws2801_socket, result->ai_addr, result->ai_addrlen) == -1) {
|
if (connect(sk6812_socket, result->ai_addr, result->ai_addrlen) == -1) {
|
||||||
perror("connect() failed");
|
perror("connect() failed");
|
||||||
freeaddrinfo(result);
|
freeaddrinfo(result);
|
||||||
return 3;
|
return 3;
|
||||||
|
@ -70,41 +70,44 @@ int ws2801_init(const char *host, unsigned short port) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws2801_set_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b) {
|
void sk6812_set_color(uint16_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
|
||||||
packetQueue[queueIndex].action = SET_COLOR;
|
packetQueue[queueIndex].action = SET_COLOR;
|
||||||
packetQueue[queueIndex].module = module;
|
packetQueue[queueIndex].module = htons(module);
|
||||||
packetQueue[queueIndex].data[0] = r;
|
packetQueue[queueIndex].data[0] = r;
|
||||||
packetQueue[queueIndex].data[1] = g;
|
packetQueue[queueIndex].data[1] = g;
|
||||||
packetQueue[queueIndex].data[2] = b;
|
packetQueue[queueIndex].data[2] = b;
|
||||||
|
packetQueue[queueIndex].data[3] = w;
|
||||||
queueIndex++;
|
queueIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws2801_fade_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b) {
|
void sk6812_fade_color(uint16_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
|
||||||
packetQueue[queueIndex].action = FADE_COLOR;
|
packetQueue[queueIndex].action = FADE_COLOR;
|
||||||
packetQueue[queueIndex].module = module;
|
packetQueue[queueIndex].module = htons(module);
|
||||||
packetQueue[queueIndex].data[0] = r;
|
packetQueue[queueIndex].data[0] = r;
|
||||||
packetQueue[queueIndex].data[1] = g;
|
packetQueue[queueIndex].data[1] = g;
|
||||||
packetQueue[queueIndex].data[2] = b;
|
packetQueue[queueIndex].data[2] = b;
|
||||||
|
packetQueue[queueIndex].data[3] = w;
|
||||||
queueIndex++;
|
queueIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws2801_add_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b) {
|
void sk6812_add_color(uint16_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
|
||||||
packetQueue[queueIndex].action = ADD_COLOR;
|
packetQueue[queueIndex].action = ADD_COLOR;
|
||||||
packetQueue[queueIndex].module = module;
|
packetQueue[queueIndex].module = htons(module);
|
||||||
packetQueue[queueIndex].data[0] = r;
|
packetQueue[queueIndex].data[0] = r;
|
||||||
packetQueue[queueIndex].data[1] = g;
|
packetQueue[queueIndex].data[1] = g;
|
||||||
packetQueue[queueIndex].data[2] = b;
|
packetQueue[queueIndex].data[2] = b;
|
||||||
|
packetQueue[queueIndex].data[3] = w;
|
||||||
queueIndex++;
|
queueIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws2801_set_fadestep(uint8_t fadestep) {
|
void sk6812_set_fadestep(uint8_t fadestep) {
|
||||||
packetQueue[queueIndex].action = SET_FADESTEP;
|
packetQueue[queueIndex].action = SET_FADESTEP;
|
||||||
packetQueue[queueIndex].data[0] = fadestep;
|
packetQueue[queueIndex].data[0] = fadestep;
|
||||||
queueIndex++;
|
queueIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ws2801_commit(void) {
|
int sk6812_commit(void) {
|
||||||
if(send(ws2801_socket, packetQueue, queueIndex * sizeof(struct WS2801Packet), 0) == -1) {
|
if(send(sk6812_socket, packetQueue, queueIndex * sizeof(struct SK6812Packet), 0) == -1) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +115,6 @@ int ws2801_commit(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws2801_shutdown() {
|
void sk6812_shutdown() {
|
||||||
close(ws2801_socket);
|
close(sk6812_socket);
|
||||||
}
|
}
|
22
sk6812.h
Normal file
22
sk6812.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* vim: sw=2 ts=2 expandtab
|
||||||
|
*
|
||||||
|
* "THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"):
|
||||||
|
* Thomas Kolb <cfr34k@tkolb.de> wrote this file. As long as you retain this
|
||||||
|
* notice you can do whatever you want with this stuff. If we meet some day,
|
||||||
|
* and you think this stuff is worth it, you can buy me a pizza in return.
|
||||||
|
* - Thomas Kolb
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SK6812_H
|
||||||
|
#define SK6812_H
|
||||||
|
|
||||||
|
int sk6812_init(const char *host, unsigned short port);
|
||||||
|
void sk6812_set_color(uint16_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
|
||||||
|
void sk6812_fade_color(uint16_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
|
||||||
|
void sk6812_add_color(uint16_t module, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
|
||||||
|
void sk6812_set_fadestep(uint8_t fadestep);
|
||||||
|
int sk6812_commit(void);
|
||||||
|
void sk6812_shutdown(void);
|
||||||
|
|
||||||
|
#endif // SK6812_H
|
22
ws2801.h
22
ws2801.h
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
* vim: sw=2 ts=2 expandtab
|
|
||||||
*
|
|
||||||
* "THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"):
|
|
||||||
* Thomas Kolb <cfr34k@tkolb.de> wrote this file. As long as you retain this
|
|
||||||
* notice you can do whatever you want with this stuff. If we meet some day,
|
|
||||||
* and you think this stuff is worth it, you can buy me a pizza in return.
|
|
||||||
* - Thomas Kolb
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WS2801_H
|
|
||||||
#define WS2801_H
|
|
||||||
|
|
||||||
int ws2801_init(const char *host, unsigned short port);
|
|
||||||
void ws2801_set_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b);
|
|
||||||
void ws2801_fade_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b);
|
|
||||||
void ws2801_add_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b);
|
|
||||||
void ws2801_set_fadestep(uint8_t fadestep);
|
|
||||||
int ws2801_commit(void);
|
|
||||||
void ws2801_shutdown(void);
|
|
||||||
|
|
||||||
#endif // WS2801_H
|
|
Loading…
Reference in a new issue