Compare commits

...

1 commit

Author SHA1 Message Date
901f23feae add slide function 2021-10-08 01:05:50 -04:00

207
lights.js
View file

@ -1,16 +1,20 @@
import ws281x from 'rpi-ws281x'; import ws281x from "rpi-ws281x";
import * as fs from 'fs'; import * as fs from "fs";
import Logger, { levels } from './logger.js'; import Logger, { levels } from "./logger.js";
const cfg = JSON.parse(fs.readFileSync('./config.json')); const cfg = JSON.parse(fs.readFileSync("./config.json"));
const log = new Logger("lights", cfg.log_level ? levels[cfg.log_level] : levels.INFO); const log = new Logger(
"lights",
cfg.log_level ? levels[cfg.log_level] : levels.INFO
);
const fade_ticks = cfg.fade_ticks || 20; const fade_ticks = cfg.fade_ticks || 20;
var num_ticks = 0;
var pixels = new Uint32Array(cfg.leds); var pixels = new Uint32Array(cfg.leds);
var pixel_cache = new Uint32Array(cfg.leds); var pixel_cache = new Uint32Array(cfg.leds);
var next_pattern = new Uint32Array(cfg.leds); var next_pattern = new Uint32Array(cfg.leds);
const targets = {} const targets = {};
var pattern = {} var pattern = {};
function rgb_to_int(r, g, b) { function rgb_to_int(r, g, b) {
let rgb = r; let rgb = r;
@ -19,9 +23,9 @@ function rgb_to_int(r, g, b) {
return rgb; return rgb;
} }
function int_to_rgb(int) { function int_to_rgb(int) {
var r = (int >> 16) & 0xFF; var r = (int >> 16) & 0xff;
var g = (int >> 8) & 0xFF; var g = (int >> 8) & 0xff;
var b = (int) & 0xFF; var b = int & 0xff;
return { r: r, g: g, b: b }; return { r: r, g: g, b: b };
} }
@ -29,11 +33,11 @@ ws281x.configure({
leds: cfg.leds || 300, leds: cfg.leds || 300,
brightness: cfg.brightness || 200, brightness: cfg.brightness || 200,
gpio: cfg.gpio || 18, gpio: cfg.gpio || 18,
stripType: cfg.type || 'grb' stripType: cfg.type || "grb",
}); });
export function set_pattern(pat) { export function set_pattern(pat) {
pattern = pat pattern = pat;
log.debug("pattern set"); log.debug("pattern set");
} }
@ -49,53 +53,92 @@ export class Function {
export const functions = { export const functions = {
random: new Function( random: new Function(
(index, arg1, arg2) => { return Math.floor(Math.random() * 256) }, (index, arg1, arg2) => {
return Math.floor(Math.random() * 256);
},
{ {
requires_arg1: true, requires_arg1: true,
requires_arg2: false, requires_arg2: false,
convert_args: false convert_args: false,
} }
), ),
move: new Function( move: new Function(
(index, arg1, arg2) => { return arg2; }, (index, arg1, arg2) => {
return arg2;
},
{ {
requires_arg1: true, requires_arg1: true,
requires_arg2: true, requires_arg2: true,
convert_args: true convert_args: true,
}), }
),
modulo: new Function( modulo: new Function(
(index, arg1, arg2) => { return arg1 % arg2; }, (index, arg1, arg2) => {
return arg1 % arg2;
},
{ {
requires_arg1: true, requires_arg1: true,
requires_arg2: true, requires_arg2: true,
convert_args: true convert_args: true,
}), }
),
swap: new Function( swap: new Function(
(index, arg1, arg2) => { let temp = targets[arg2]; targets[arg2] = targets[arg1]; return temp; }, (index, arg1, arg2) => {
let temp = targets[arg2];
targets[arg2] = targets[arg1];
return temp;
},
{ {
requires_arg1: true, requires_arg1: true,
requires_arg2: true, requires_arg2: true,
convert_args: false convert_args: false,
}), }
),
add: new Function( add: new Function(
(index, arg1, arg2) => { return arg1 + arg2; }, (index, arg1, arg2) => {
return arg1 + arg2;
},
{ {
requires_arg1: true, requires_arg1: true,
requires_arg2: true, requires_arg2: true,
convert_args: true convert_args: true,
}), }
),
subtract: new Function( subtract: new Function(
(index, arg1, arg2) => { return arg1 - arg2; }, (index, arg1, arg2) => {
return arg1 - arg2;
},
{ {
requires_arg1: true, requires_arg1: true,
requires_arg2: true, requires_arg2: true,
convert_args: true convert_args: true,
}) }
} ),
stagger: new Function(
(index, arg1, arg2) => {
return (index + arg2) % 255;
},
{
requires_arg1: true,
requires_arg2: true,
convert_args: true,
},
slide: new Function(
(index, arg1, arg2) => {
return (num_ticks + arg2) % 255;
},
{
requires_arg1: true,
requires_arg2: true,
convert_args: true
}
)
),
};
function tick_pattern() { function tick_pattern() {
// do the parsing stuff here // do the parsing stuff here
log.debug("TICKING PATTERN") log.debug("TICKING PATTERN");
let parsed = pattern.parsed; let parsed = pattern.parsed;
log.debug(`${JSON.stringify(pattern)} ${JSON.stringify(parsed)}`); log.debug(`${JSON.stringify(pattern)} ${JSON.stringify(parsed)}`);
@ -108,14 +151,18 @@ function tick_pattern() {
let name = command["command"]; let name = command["command"];
log.debug(`${name} matches: ${functions[name]}`); log.debug(`${name} matches: ${functions[name]}`);
if (functions[name] != undefined) { if (functions[name] != undefined) {
if (functions[name].options && functions[name].options["convert_args"]) { if (
functions[name].options &&
functions[name].options["convert_args"]
) {
let param_arg1 = parseInt(command.arg1) || targets[command.arg1]; let param_arg1 = parseInt(command.arg1) || targets[command.arg1];
let param_arg2 = parseInt(command.arg2) || targets[command.arg2]; let param_arg2 = parseInt(command.arg2) || targets[command.arg2];
let result = functions[name].func(i, param_arg1, param_arg2); let result = functions[name].func(i, param_arg1, param_arg2);
log.debug(`convert ${command.arg1} ${param_arg1} ${command.arg2} ${param_arg2} ${result}`); log.debug(
`convert ${command.arg1} ${param_arg1} ${command.arg2} ${param_arg2} ${result}`
);
targets[command.arg1] = result; targets[command.arg1] = result;
} } else {
else {
let result = functions[name].func(i, command.arg1, command.arg2); let result = functions[name].func(i, command.arg1, command.arg2);
log.debug(`no convert ${command.arg1} = ${result}`); log.debug(`no convert ${command.arg1} = ${result}`);
targets[command.arg1] = result; targets[command.arg1] = result;
@ -123,18 +170,24 @@ function tick_pattern() {
} }
} }
log.debug(`next: ${targets["r"]}, ${targets["g"]}, ${targets["b"]}`); log.debug(`next: ${targets["r"]}, ${targets["g"]}, ${targets["b"]}`);
next_pattern[i] = rgb_to_int(targets["r"] || 0, targets["g"] || 0, targets["b"] || 0); next_pattern[i] = rgb_to_int(
targets["r"] = 0; targets["g"] = 0; targets["b"] = 0; targets["r"] || 0,
targets["g"] || 0,
targets["b"] || 0
);
targets["r"] = 0;
targets["g"] = 0;
targets["b"] = 0;
} }
} else {
getRandom();
} }
else { num_ticks++;
getRandom()
}
} }
function getRandom() { function getRandom() {
for (let i = 0; i < cfg.leds; i++) { for (let i = 0; i < cfg.leds; i++) {
var r = Math.floor(Math.random() * 256) var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256); var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256); var b = Math.floor(Math.random() * 256);
next_pattern[i] = rgb_to_int(r, g, b); next_pattern[i] = rgb_to_int(r, g, b);
@ -148,21 +201,18 @@ export function tick() {
if (next_pattern[i] == pixel_cache[i]) { if (next_pattern[i] == pixel_cache[i]) {
log.debug("INCONGRUENCE WITH " + i); log.debug("INCONGRUENCE WITH " + i);
pixels[i] = next_pattern[i]; pixels[i] = next_pattern[i];
} } else {
else {
changed = true; changed = true;
fade(i); fade(i);
} }
} } else if (pixel_cache[i] != pixels[i]) {
else if (pixel_cache[i] != pixels[i]) {
log.debug("PATTERN NOT STORED " + i); log.debug("PATTERN NOT STORED " + i);
pixel_cache[i] = pixels[i]; pixel_cache[i] = pixels[i];
} }
} }
if (!changed) { if (!changed) {
tick_pattern(); tick_pattern();
} } else {
else {
ws281x.render(pixels); ws281x.render(pixels);
} }
//ws281x.sleep(cfg.sleep_time || 500); //ws281x.sleep(cfg.sleep_time || 500);
@ -185,53 +235,74 @@ function fade(index) {
var interval_r = sign_r * Math.ceil(Math.abs(diff_r) / fade_ticks); var interval_r = sign_r * Math.ceil(Math.abs(diff_r) / fade_ticks);
var interval_g = sign_g * Math.ceil(Math.abs(diff_g) / fade_ticks); var interval_g = sign_g * Math.ceil(Math.abs(diff_g) / fade_ticks);
var interval_b = sign_b * Math.ceil(Math.abs(diff_b) / fade_ticks); var interval_b = sign_b * Math.ceil(Math.abs(diff_b) / fade_ticks);
log.debug(`r${Math.abs(diff_r) / fade_ticks} ${Math.ceil(Math.abs(diff_r) / fade_ticks)}` + log.debug(
`g${Math.abs(diff_g) / fade_ticks} ${Math.ceil(Math.abs(diff_g) / fade_ticks)}` + `r${Math.abs(diff_r) / fade_ticks} ${Math.ceil(
`b${Math.abs(diff_b) / fade_ticks} ${Math.ceil(Math.abs(diff_b) / fade_ticks)}`); Math.abs(diff_r) / fade_ticks
)}` +
`g${Math.abs(diff_g) / fade_ticks} ${Math.ceil(
Math.abs(diff_g) / fade_ticks
)}` +
`b${Math.abs(diff_b) / fade_ticks} ${Math.ceil(
Math.abs(diff_b) / fade_ticks
)}`
);
var current_tick_r = Math.floor(Math.abs(diff_cr / diff_r) * fade_ticks); var current_tick_r = Math.floor(Math.abs(diff_cr / diff_r) * fade_ticks);
var current_tick_g = Math.floor(Math.abs(diff_cg / diff_g) * fade_ticks); var current_tick_g = Math.floor(Math.abs(diff_cg / diff_g) * fade_ticks);
var current_tick_b = Math.floor(Math.abs(diff_cb / diff_b) * fade_ticks); var current_tick_b = Math.floor(Math.abs(diff_cb / diff_b) * fade_ticks);
if (diff_r == 0 || if (
diff_r == 0 ||
(sign_r == 1 && current.r + interval_r >= final.r) || (sign_r == 1 && current.r + interval_r >= final.r) ||
(sign_r == -1 && current.r + interval_r <= final.r) || (sign_r == -1 && current.r + interval_r <= final.r) ||
current_tick_r + 1 >= fade_ticks) { current_tick_r + 1 >= fade_ticks
) {
current.r = final.r; current.r = final.r;
interval_r = 0; interval_r = 0;
current_tick_r = fade_ticks; current_tick_r = fade_ticks;
} }
if (diff_g == 0 || if (
diff_g == 0 ||
(sign_g == 1 && current.g + interval_g >= final.g) || (sign_g == 1 && current.g + interval_g >= final.g) ||
(sign_g == -1 && current.g + interval_g <= final.g) || (sign_g == -1 && current.g + interval_g <= final.g) ||
current_tick_g + 1 >= fade_ticks) { current_tick_g + 1 >= fade_ticks
) {
current.g = final.g; current.g = final.g;
interval_g = 0; interval_g = 0;
current_tick_g = fade_ticks; current_tick_g = fade_ticks;
} }
if (diff_b == 0 || if (
diff_b == 0 ||
(sign_b == 1 && current.b + interval_b >= final.b) || (sign_b == 1 && current.b + interval_b >= final.b) ||
(sign_b == -1 && current.b + interval_b <= final.b) || (sign_b == -1 && current.b + interval_b <= final.b) ||
current_tick_b + 1 >= fade_ticks) { current_tick_b + 1 >= fade_ticks
) {
current.b = final.b; current.b = final.b;
interval_b = 0; interval_b = 0;
current_tick_b = fade_ticks; current_tick_b = fade_ticks;
} }
if (current_tick_r + 1 >= fade_ticks && if (
current_tick_r + 1 >= fade_ticks &&
current_tick_g + 1 >= fade_ticks && current_tick_g + 1 >= fade_ticks &&
current_tick_b + 1 >= fade_ticks) { current_tick_b + 1 >= fade_ticks
) {
log.debug("FINISHED"); log.debug("FINISHED");
pixel_cache[index] = next_pattern[index]; pixel_cache[index] = next_pattern[index];
} } else {
else { pixels[index] = rgb_to_int(
pixels[index] = rgb_to_int(current.r + interval_r, current.r + interval_r,
current.g + interval_g, current.g + interval_g,
current.b + interval_b); current.b + interval_b
);
let prev = int_to_rgb(pixel_cache[index]); let prev = int_to_rgb(pixel_cache[index]);
log.debug(`${current_tick_r} ${current_tick_g} ${current_tick_b}: ` log.debug(
+ `CURRENT COLOR: ${current.r} ${current.g} ${current.b} NEW COLOR: ${current.r + interval_r} ${current.g + interval_g} ${current.b + interval_b} ` + `${current_tick_r} ${current_tick_g} ${current_tick_b}: ` +
`FINAL: ${final.r} ${final.g} ${final.b} ` + `CURRENT COLOR: ${current.r} ${current.g} ${current.b} NEW COLOR: ${
`\nINTERVAL: ${interval_r} ${interval_g} ${interval_b} ` + current.r + interval_r
`PREVIOUS: ${prev.r} ${prev.g} ${prev.b}`); } ${current.g + interval_g} ${current.b + interval_b} ` +
`FINAL: ${final.r} ${final.g} ${final.b} ` +
`\nINTERVAL: ${interval_r} ${interval_g} ${interval_b} ` +
`PREVIOUS: ${prev.r} ${prev.g} ${prev.b}`
);
} }
} }