Something works in WASM

This commit is contained in:
cschwinne 2021-07-12 16:33:43 +02:00
parent 301cacc91d
commit 776971db2c
9 changed files with 351 additions and 226 deletions

View File

@ -42,14 +42,22 @@ uint16_t WS2812FX::mode_static(void) {
* Custom mode. Executes WebAssembly fx() function
*/
uint16_t WS2812FX::mode_custom(void) {
wasm.call();
wasmfx.run();
return FRAMETIME;
}
//testing TEMP
uint16_t WS2812FX::mode_benchmark(void) {
wasm.call();
uint32_t i=(now/4);
uint32_t c=0;
while(c<SEGLEN){
uint32_t v=i%256;
setPixelColor(c,v,v/2,0);
c++;
i=(i+SEGMENT.speed/16+1);
}
return FRAMETIME;
}

View File

@ -630,7 +630,8 @@ class WS2812FX {
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
show(void),
setColorOrder(uint8_t co),
setPixelSegment(uint8_t n);
setPixelSegment(uint8_t n),
initWasm(void);
bool
isRgbw = false,
@ -898,7 +899,7 @@ class WS2812FX {
ColorTransition transitions[MAX_NUM_TRANSITIONS]; //12 bytes per element
friend class ColorTransition;
friend class WASMVM;
friend class WASMFX;
uint16_t
realPixelIndex(uint16_t i),
@ -918,7 +919,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([
"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst",
"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow",
"Heartbeat","Pacifica","Candle Multi", "Solid Glitter","Sunrise","Phased","Twinkleup","Noise Pal", "Sine","Phased Noise",
"Flow","Chunchun","Dancing Shadows","Washing Machine","Candy Cane","Blends","TV Simulator","Dynamic Smooth"
"Flow","Chunchun","Dancing Shadows","Washing Machine","Candy Cane","Blends","TV Simulator","Dynamic Smooth","Custom","Benchmark"
])=====";

View File

@ -1085,4 +1085,8 @@ uint32_t WS2812FX::gamma32(uint32_t color)
return ((w << 24) | (r << 16) | (g << 8) | (b));
}
void WS2812FX::initWasm() {
wasmfx.init();
}
WS2812FX* WS2812FX::instance = nullptr;

View File

@ -249,6 +249,25 @@ void userSetup();
void userConnected();
void userLoop();
//wasm.cpp
void wasmInit();
void wasmRun();
class WASMFX {
public:
void init() {
wasmInit();
}
void run() {
wasmRun();
}
uint32_t now();
uint32_t speed();
uint32_t intensity();
};
//wled_eeprom.cpp
void applyMacro(byte index);
void deEEP();

View File

@ -1,5 +1,6 @@
#include <wasm3.h>
#include <m3_env.h>
#include "wled.h"
#define WASM_STACK_SLOTS 1024
#define NATIVE_STACK_SIZE (32*1024)
@ -8,25 +9,81 @@
#define WASM_MEMORY_LIMIT 4096
unsigned char app_wasm[] = {
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60,
0x02, 0x7f, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60,
0x00, 0x01, 0x7f, 0x02, 0x4e, 0x04, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69,
0x6e, 0x6f, 0x09, 0x67, 0x65, 0x74, 0x50, 0x69, 0x6e, 0x4c, 0x45, 0x44,
0x00, 0x03, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x07, 0x70,
0x69, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x00, 0x00, 0x07, 0x61, 0x72, 0x64,
0x75, 0x69, 0x6e, 0x6f, 0x0c, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c,
0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0x00, 0x07, 0x61, 0x72, 0x64, 0x75,
0x69, 0x6e, 0x6f, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x00, 0x02, 0x03,
0x02, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x07, 0x13, 0x02, 0x06,
0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74,
0x61, 0x72, 0x74, 0x00, 0x04, 0x0a, 0x3a, 0x01, 0x38, 0x01, 0x01, 0x7f,
0x41, 0x80, 0x08, 0x10, 0x00, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00,
0x41, 0x01, 0x10, 0x01, 0x03, 0x40, 0x41, 0x80, 0x08, 0x28, 0x02, 0x00,
0x41, 0x01, 0x10, 0x02, 0x41, 0xe4, 0x00, 0x10, 0x03, 0x41, 0x80, 0x08,
0x28, 0x02, 0x00, 0x41, 0x00, 0x10, 0x02, 0x41, 0x84, 0x07, 0x10, 0x03,
0x0c, 0x00, 0x0b, 0x00, 0x0b
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x03, 0x60,
0x00, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x01, 0x7f, 0x01, 0x7f,
0x02, 0x10, 0x01, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x06, 0x5f, 0x70,
0x72, 0x69, 0x6e, 0x74, 0x00, 0x01, 0x03, 0x06, 0x05, 0x02, 0x01, 0x00,
0x00, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x06, 0x01, 0x7f, 0x01,
0x41, 0x00, 0x0b, 0x07, 0x0f, 0x02, 0x02, 0x66, 0x78, 0x00, 0x04, 0x06,
0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x08, 0x01, 0x05, 0x0a,
0xaf, 0x05, 0x05, 0xb1, 0x01, 0x01, 0x06, 0x7f, 0x20, 0x00, 0x41, 0xec,
0xff, 0xff, 0xff, 0x03, 0x4b, 0x04, 0x40, 0x00, 0x0b, 0x20, 0x00, 0x41,
0x10, 0x6a, 0x22, 0x01, 0x41, 0xfc, 0xff, 0xff, 0xff, 0x03, 0x4b, 0x04,
0x40, 0x00, 0x0b, 0x23, 0x00, 0x21, 0x05, 0x23, 0x00, 0x41, 0x04, 0x6a,
0x22, 0x03, 0x20, 0x01, 0x41, 0x13, 0x6a, 0x41, 0x70, 0x71, 0x41, 0x04,
0x6b, 0x22, 0x06, 0x6a, 0x22, 0x01, 0x3f, 0x00, 0x22, 0x04, 0x41, 0x10,
0x74, 0x41, 0x0f, 0x6a, 0x41, 0x70, 0x71, 0x22, 0x02, 0x4b, 0x04, 0x40,
0x20, 0x04, 0x20, 0x01, 0x20, 0x02, 0x6b, 0x41, 0xff, 0xff, 0x03, 0x6a,
0x41, 0x80, 0x80, 0x7c, 0x71, 0x41, 0x10, 0x76, 0x22, 0x02, 0x20, 0x02,
0x20, 0x04, 0x48, 0x1b, 0x40, 0x00, 0x41, 0x00, 0x48, 0x04, 0x40, 0x20,
0x02, 0x40, 0x00, 0x41, 0x00, 0x48, 0x04, 0x40, 0x00, 0x0b, 0x0b, 0x0b,
0x20, 0x01, 0x24, 0x00, 0x20, 0x05, 0x20, 0x06, 0x36, 0x02, 0x00, 0x20,
0x03, 0x41, 0x04, 0x6b, 0x22, 0x01, 0x41, 0x00, 0x36, 0x02, 0x04, 0x20,
0x01, 0x41, 0x00, 0x36, 0x02, 0x08, 0x20, 0x01, 0x41, 0x00, 0x36, 0x02,
0x0c, 0x20, 0x01, 0x20, 0x00, 0x36, 0x02, 0x10, 0x20, 0x03, 0x41, 0x10,
0x6a, 0x0b, 0xbc, 0x02, 0x01, 0x03, 0x7f, 0x41, 0xa0, 0x08, 0x21, 0x02,
0x20, 0x00, 0x41, 0x01, 0x74, 0x41, 0xa0, 0x08, 0x6a, 0x21, 0x03, 0x20,
0x01, 0x21, 0x00, 0x03, 0x40, 0x20, 0x02, 0x20, 0x03, 0x49, 0x04, 0x40,
0x20, 0x02, 0x2f, 0x01, 0x00, 0x22, 0x01, 0x41, 0x80, 0x01, 0x49, 0x04,
0x7f, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0x01,
0x6a, 0x05, 0x20, 0x01, 0x41, 0x80, 0x10, 0x49, 0x04, 0x7f, 0x20, 0x00,
0x20, 0x01, 0x41, 0x06, 0x76, 0x41, 0xc0, 0x01, 0x72, 0x20, 0x01, 0x41,
0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, 0x41, 0x08, 0x74, 0x72, 0x3b, 0x01,
0x00, 0x20, 0x00, 0x41, 0x02, 0x6a, 0x05, 0x20, 0x01, 0x41, 0x80, 0xf0,
0x03, 0x71, 0x41, 0x80, 0xb0, 0x03, 0x46, 0x04, 0x40, 0x20, 0x03, 0x20,
0x02, 0x41, 0x02, 0x6a, 0x4b, 0x41, 0x00, 0x20, 0x01, 0x41, 0x80, 0xb8,
0x03, 0x49, 0x1b, 0x04, 0x40, 0x20, 0x02, 0x2f, 0x01, 0x02, 0x22, 0x04,
0x41, 0x80, 0xf8, 0x03, 0x71, 0x41, 0x80, 0xb8, 0x03, 0x46, 0x04, 0x40,
0x20, 0x00, 0x20, 0x01, 0x41, 0xff, 0x07, 0x71, 0x41, 0x0a, 0x74, 0x41,
0x80, 0x80, 0x04, 0x6a, 0x20, 0x04, 0x41, 0xff, 0x07, 0x71, 0x72, 0x22,
0x01, 0x41, 0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, 0x41, 0x18, 0x74, 0x20,
0x01, 0x41, 0x06, 0x76, 0x41, 0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, 0x41,
0x10, 0x74, 0x72, 0x20, 0x01, 0x41, 0x0c, 0x76, 0x41, 0x3f, 0x71, 0x41,
0x80, 0x01, 0x72, 0x41, 0x08, 0x74, 0x72, 0x20, 0x01, 0x41, 0x12, 0x76,
0x41, 0xf0, 0x01, 0x72, 0x72, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, 0x04,
0x6a, 0x21, 0x00, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x21, 0x02, 0x0c, 0x06,
0x0b, 0x0b, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x41, 0x0c, 0x76, 0x41, 0xe0,
0x01, 0x72, 0x20, 0x01, 0x41, 0x06, 0x76, 0x41, 0x3f, 0x71, 0x41, 0x80,
0x01, 0x72, 0x41, 0x08, 0x74, 0x72, 0x3b, 0x01, 0x00, 0x20, 0x00, 0x20,
0x01, 0x41, 0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, 0x3a, 0x00, 0x02, 0x20,
0x00, 0x41, 0x03, 0x6a, 0x0b, 0x0b, 0x21, 0x00, 0x20, 0x02, 0x41, 0x02,
0x6a, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x0b, 0x0b, 0xae, 0x01, 0x01, 0x04,
0x7f, 0x41, 0xa0, 0x08, 0x21, 0x01, 0x41, 0x9c, 0x08, 0x28, 0x02, 0x00,
0x41, 0xa0, 0x08, 0x6a, 0x21, 0x02, 0x03, 0x40, 0x20, 0x01, 0x20, 0x02,
0x49, 0x04, 0x40, 0x20, 0x01, 0x2f, 0x01, 0x00, 0x22, 0x03, 0x41, 0x80,
0x01, 0x49, 0x04, 0x7f, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x05, 0x20, 0x03,
0x41, 0x80, 0x10, 0x49, 0x04, 0x7f, 0x20, 0x00, 0x41, 0x02, 0x6a, 0x05,
0x20, 0x02, 0x20, 0x01, 0x41, 0x02, 0x6a, 0x4b, 0x41, 0x00, 0x20, 0x03,
0x41, 0x80, 0xf8, 0x03, 0x71, 0x41, 0x80, 0xb0, 0x03, 0x46, 0x1b, 0x04,
0x40, 0x20, 0x01, 0x2f, 0x01, 0x02, 0x41, 0x80, 0xf8, 0x03, 0x71, 0x41,
0x80, 0xb8, 0x03, 0x46, 0x04, 0x40, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x21,
0x00, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x0c, 0x05, 0x0b, 0x0b,
0x20, 0x00, 0x41, 0x03, 0x6a, 0x0b, 0x0b, 0x21, 0x00, 0x20, 0x01, 0x41,
0x02, 0x6a, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x0b, 0x20, 0x00, 0x10, 0x01,
0x21, 0x00, 0x41, 0x9c, 0x08, 0x28, 0x02, 0x00, 0x41, 0x01, 0x76, 0x20,
0x00, 0x10, 0x02, 0x20, 0x00, 0x20, 0x00, 0x41, 0x14, 0x6b, 0x28, 0x02,
0x10, 0x10, 0x00, 0x0b, 0x04, 0x00, 0x10, 0x03, 0x0b, 0x07, 0x00, 0x41,
0xcc, 0x08, 0x24, 0x00, 0x0b, 0x0b, 0x3f, 0x02, 0x00, 0x41, 0x8c, 0x08,
0x0b, 0x01, 0x3c, 0x00, 0x41, 0x98, 0x08, 0x0b, 0x31, 0x01, 0x00, 0x00,
0x00, 0x2a, 0x00, 0x00, 0x00, 0x48, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c,
0x00, 0x6f, 0x00, 0x20, 0x00, 0x57, 0x00, 0x4c, 0x00, 0x45, 0x00, 0x44,
0x00, 0x20, 0x00, 0x66, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x20,
0x00, 0x57, 0x00, 0x41, 0x00, 0x53, 0x00, 0x4d, 0x00, 0x21, 0x00, 0x20,
0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69,
0x6e, 0x67, 0x55, 0x52, 0x4c, 0x0e, 0x2e, 0x2f, 0x61, 0x70, 0x70, 0x2e,
0x77, 0x61, 0x73, 0x6d, 0x2e, 0x6d, 0x61, 0x70
};
unsigned int app_wasm_len = 197;
unsigned int app_wasm_len = 872;
/*
* API bindings
@ -37,18 +94,15 @@ unsigned int app_wasm_len = 197;
* m3ApiTrap(trap) - Returns a trap
*/
class WASMVM {
WS2812FX inst = nullptr;
m3ApiRawFunction(m3_arduino_millis)
{
m3ApiRawFunction(m3_arduino_millis)
{
m3ApiReturnType (uint32_t)
m3ApiReturn(millis());
}
}
m3ApiRawFunction(m3_arduino_delay)
{
m3ApiRawFunction(m3_arduino_delay)
{
m3ApiGetArg (uint32_t, ms)
// You can also trace API calls
@ -57,94 +111,94 @@ class WASMVM {
delay(ms);
m3ApiSuccess();
}
}
// This maps pin modes from arduino_wasm_api.h
// to actual platform-specific values
uint8_t mapPinMode(uint8_t mode)
{
// This maps pin modes from arduino_wasm_api.h
// to actual platform-specific values
uint8_t mapPinMode(uint8_t mode)
{
switch(mode) {
case 0: return INPUT;
case 1: return OUTPUT;
case 2: return INPUT_PULLUP;
}
return INPUT;
}
}
m3ApiRawFunction(m3_arduino_pinMode)
{
m3ApiRawFunction(m3_arduino_pinMode)
{
m3ApiGetArg (uint32_t, pin)
m3ApiGetArg (uint32_t, mode)
pinMode(pin, (uint8_t)mapPinMode(mode));
m3ApiSuccess();
}
}
m3ApiRawFunction(m3_arduino_digitalWrite)
{
m3ApiRawFunction(m3_arduino_digitalWrite)
{
m3ApiGetArg (uint32_t, pin)
m3ApiGetArg (uint32_t, value)
digitalWrite(pin, value);
m3ApiSuccess();
}
}
m3ApiRawFunction(m3_arduino_getPinLED)
{
m3ApiRawFunction(m3_arduino_getPinLED)
{
m3ApiReturnType (uint32_t)
m3ApiReturn(LED_PIN);
}
m3ApiReturn(2);
}
m3ApiRawFunction(m3_arduino_print)
{
m3ApiRawFunction(m3_arduino_print)
{
m3ApiGetArgMem (const uint8_t *, buf)
m3ApiGetArg (uint32_t, len)
Serial.write(buf, len);
m3ApiSuccess();
}
}
m3ApiRawFunction(m3_led_now) {
m3ApiRawFunction(m3_led_now) {
m3ApiReturnType(uint32_t)
m3ApiReturn(strip.now());
}
m3ApiReturn(wasmfx.now());
}
m3ApiRawFunction(m3_led_speed) {
m3ApiRawFunction(m3_led_speed) {
m3ApiReturnType(uint32_t)
m3ApiReturn(strip._segments[strip._segment_index].speed);
}
m3ApiReturn(0);//strip._segments[strip._segment_index].speed);
}
m3ApiRawFunction(m3_led_intensity) {
m3ApiRawFunction(m3_led_intensity) {
m3ApiReturnType(uint32_t)
m3ApiReturn(strip._segments[strip._segment_index].intensity);
}
m3ApiReturn(0);//strip._segments[strip._segment_index].intensity);
}
m3ApiRawFunction(m3_led_len) {
m3ApiRawFunction(m3_led_len) {
m3ApiReturnType(uint32_t)
m3ApiReturn(strip._virtualSegmentLength);
}
m3ApiReturn(0);//strip._virtualSegmentLength);
}
m3ApiRawFunction(m3_led_fill) {
m3ApiRawFunction(m3_led_fill) {
m3ApiGetArg (uint32_t, color)
strip.fill(color);
m3ApiSuccess();
}
}
m3ApiRawFunction(m3_led_set) {
m3ApiRawFunction(m3_led_set) {
m3ApiGetArg (uint32_t, index)
m3ApiGetArg (uint32_t, color)
strip.setPixelColor(index, color);
m3ApiSuccess();
}
}
m3ApiRawFunction(m3_led_rgb) {
m3ApiRawFunction(m3_led_rgb) {
m3ApiGetArg (uint32_t, r)
m3ApiGetArg (uint32_t, g)
m3ApiGetArg (uint32_t, b)
@ -152,10 +206,10 @@ class WASMVM {
m3ApiReturnType(uint32_t)
uint32_t c = (r << 16) + (g << 8) + b;
m3ApiReturn(c);
}
}
M3Result LinkArduino (IM3Runtime runtime)
{
M3Result LinkArduino (IM3Runtime runtime)
{
IM3Module module = runtime->modules;
const char* arduino = "arduino";
const char* led = "led";
@ -179,16 +233,16 @@ class WASMVM {
m3_LinkRawFunction (module, led, "rgb", "i(iii)", &m3_led_rgb);
return m3Err_none;
}
}
/*
* Engine start, liftoff!
*/
/*
* Engine start, liftoff!
*/
#define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); return; }
#define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); return; }
void wasm_task(void*)
{
void wasm_task(void*)
{
M3Result result = m3Err_none;
IM3Environment env = m3_NewEnvironment ();
@ -197,9 +251,9 @@ class WASMVM {
IM3Runtime runtime = m3_NewRuntime (env, WASM_STACK_SLOTS, NULL);
if (!runtime) FATAL("NewRt", "failed");
#ifdef WASM_MEMORY_LIMIT
#ifdef WASM_MEMORY_LIMIT
runtime->memoryLimit = WASM_MEMORY_LIMIT;
#endif
#endif
IM3Module module;
result = m3_ParseModule (env, &module, app_wasm, app_wasm_len);
@ -212,7 +266,7 @@ class WASMVM {
if (result) FATAL("LinkArd", result);
IM3Function f;
result = m3_FindFunction (&f, runtime, "_start");
result = m3_FindFunction (&f, runtime, "fx");
if (result) FATAL("FindFunc", result);
Serial.println("Run WASM...");
@ -236,20 +290,24 @@ class WASMVM {
Serial.println(info.line);
}
}
}
public void setup(WS2812FX* instance)
{
if (!instance) return;
inst = instance;
//while (true) {}
}
void wasmInit()
{
Serial.println("\nWasm3 v" M3_VERSION " (" M3_ARCH "), build " __DATE__ " " __TIME__);
#ifdef ESP32
/*
#ifdef ESP32
// On ESP32, we can launch in a separate thread
xTaskCreate(&wasm_task, "wasm3", NATIVE_STACK_SIZE, NULL, 5, NULL);
#else
#else
wasm_task(NULL);
#endif
}
#endif
*/
wasm_task(NULL);
}
void wasmRun() {
}

13
wled00/wasmfx.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "wled.h"
uint32_t WASMFX::now() {
return strip.now;
}
uint32_t WASMFX::speed() {
return strip._segments[strip._segment_index].speed;
}
uint32_t WASMFX::intensity() {
return strip._segments[strip._segment_index].intensity;
}

17
wled00/wasmfx.h Normal file
View File

@ -0,0 +1,17 @@
/*#pragma once
#include "wled.h"
class WASMFX {
public:
void init() {
wasmInit();
}
void run() {
wasmRun();
}
uint32_t now();
uint32_t speed();
uint32_t intensity();
};*/

View File

@ -313,6 +313,7 @@ void WLED::setup()
if (!pinManager.isPinAllocated(STATUSLED)) pinMode(STATUSLED, OUTPUT);
#endif
wasmfx.init();
DEBUG_PRINTLN(F("Initializing strip"));
beginStrip();

View File

@ -144,6 +144,7 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument<PSRAM_Allocator>;
#include "NodeStruct.h"
#include "pin_manager.h"
#include "bus_manager.h"
//#include "wasmfx.h"
#ifndef CLIENT_SSID
#define CLIENT_SSID DEFAULT_CLIENT_SSID
@ -588,6 +589,9 @@ WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
WLED_GLOBAL BusConfig* busConfigs[WLED_MAX_BUSSES] _INIT({nullptr}); //temporary, to remember values from network callback until after
WLED_GLOBAL bool doInitBusses _INIT(false);
// WASM
WLED_GLOBAL WASMFX wasmfx _INIT(WASMFX());
// Usermod manager
WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager());