From 847f9a9a1a535505ed572413920616dbba66e3ff Mon Sep 17 00:00:00 2001 From: Ewoud Date: Sat, 29 Jul 2023 23:03:48 +0200 Subject: [PATCH] Refactor 2DMatrix generator, add first 2D effect (Frizzkes2D) AppLedsV: - NUM_LEDS_Preview 4096 - projectionNr and ledFixNr as variables - ledFixProjectAndMap without arguments AppEffects - add Frizzles2D (from WLED, modified, no sliders yet, only defaults) AppModLedFixGen: - add width, height and depth to generated ledfix with user defined instead if fixed sizes (wip) - replace 2DMatrix88 with 2DMatrix (using width and height), so we can make up to 64*64 panels (Hub75) - Add generate button - strcat dimension in the name (2DMatrix only yet) AppModLeds - Add Frizzles2D - replace whd by dimensions text only --- platformio.ini | 8 +++++ src/App/AppEffects.h | 24 ++++++++++++- src/App/AppLedsV.cpp | 72 +++++++++++++++++++------------------ src/App/AppLedsV.h | 14 ++++++-- src/App/AppModLedFixGen.h | 76 +++++++++++++++++++++++++-------------- src/App/AppModLeds.h | 46 ++++++------------------ src/Sys/SysJsonRDWS.h | 11 ------ 7 files changed, 141 insertions(+), 110 deletions(-) diff --git a/platformio.ini b/platformio.ini index 0ec89181..69f6b8fc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,3 +1,11 @@ +; @title StarMod +; @file platformio.ini +; @date 20230729 +; @repo https://github.com/ewoudwijma/StarMod +; @Authors https://github.com/ewoudwijma/StarMod/commits/main +; @Copyright (c) 2023 Github StarMod Commit Authors +; @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + ; PlatformIO Project Configuration File ; ; Build options: build flags, source filter diff --git a/src/App/AppEffects.h b/src/App/AppEffects.h index 19adaa40..24b70e2a 100644 --- a/src/App/AppEffects.h +++ b/src/App/AppEffects.h @@ -199,6 +199,28 @@ class SphereMove3DEffect:public Effect { } } } -}; // 3DSphereMove +}; // SphereMove3DEffect + +class Frizzles2D:public Effect { +public: + const char * name() { + return "Frizzles2D"; + } + void setup() {} //not implemented yet + void loop() { + fadeToBlackBy( ledsP, ledsV.nrOfLedsP, 16); + CRGBPalette16 palette = PartyColors_p; + + for (size_t i = 8; i > 0; i--) { + uint8_t x = beatsin8(128/8 + i, 0, ledsV.width - 1); + uint8_t y = beatsin8(128/8 - i, 0, ledsV.height - 1); + CRGB color = ColorFromPalette(palette, beatsin8(12, 0, 255), 255); + ledsV[x + y * ledsV.width] = color; + } + // blur2d(ledsP, ledsV.width, ledsV.height, 255); + // SEGMENT.blur(SEGMENT.custom1>>3); + + } +}; // Frizzles2D static std::vector effects; \ No newline at end of file diff --git a/src/App/AppLedsV.cpp b/src/App/AppLedsV.cpp index 017c5767..317be27e 100644 --- a/src/App/AppLedsV.cpp +++ b/src/App/AppLedsV.cpp @@ -24,11 +24,18 @@ uint16_t LedsV::width = 8; uint16_t LedsV::height = 8; uint16_t LedsV::depth = 1; +enum Projections +{ + p_None, + p_Random, + p_DistanceFromPoint +}; + //load ledfix json file, parse it and depending on the projection, create a mapping for it -void LedsV::ledFixProjectAndMap(JsonObject ledFixObject, JsonObject projectionObject) { +void LedsV::ledFixProjectAndMap() { char fileName[30] = ""; - if (files->seqNrToName(fileName, ledFixObject["value"])) { + if (files->seqNrToName(fileName, ledFixNr)) { JsonRDWS jrdws(fileName); //open fileName for deserialize mappingTableLedCounter = 0; @@ -40,8 +47,7 @@ void LedsV::ledFixProjectAndMap(JsonObject ledFixObject, JsonObject projectionOb jrdws.lookFor("depth", &depth); jrdws.lookFor("nrOfLeds", &nrOfLedsP); - uint8_t projection = mdl->getValue("projection"); - if (true || projectionObject["value"] != 0) { //not None + if (projectionNr > p_Random) { //0 and 1 (none, random have no mapping) jrdws.lookFor("leds", [](std::vector uint16CollectList) { // print->print("funList "); // for (uint16_t num:uint16CollectList) @@ -78,20 +84,20 @@ void LedsV::ledFixProjectAndMap(JsonObject ledFixObject, JsonObject projectionOb } //projection != 0 if (jrdws.deserialize()) { //find all the objects - if (true || projectionObject["value"] != 0) { //not None + if (projectionNr > p_Random) { nrOfLedsV = mappingTable.size(); - uint16_t x=0; - uint16_t y=0; - for (std::vectorphysMap:mappingTable) { - print->print("led %d mapping: ", x); - for (uint16_t pos:physMap) { - print->print(" %d", pos); - y++; - } - print->print("\n"); - x++; - } + // uint16_t x=0; + // uint16_t y=0; + // for (std::vectorphysMap:mappingTable) { + // print->print("led %d mapping: ", x); + // for (uint16_t pos:physMap) { + // print->print(" %d", pos); + // y++; + // } + // print->print("\n"); + // x++; + // } } else nrOfLedsV = nrOfLedsP; @@ -99,26 +105,17 @@ void LedsV::ledFixProjectAndMap(JsonObject ledFixObject, JsonObject projectionOb print->print("jrdws whd %d %d %d and P:%d V:%d\n", width, height, depth, nrOfLedsP, nrOfLedsV); //at page refresh, done before these objects have been initialized... - mdl->setValueI("width", width); - // print->print("1.1\n"); - mdl->setValueI("height", height); - // print->print("1.2\n"); - mdl->setValueI("depth", depth); - // print->print("1.3\n"); + mdl->setValueV("dimensions", "%dx%dx%d", ledsV.width, ledsV.height, ledsV.depth); mdl->setValueV("nrOfLeds", "P:%d V:%d", nrOfLedsP, nrOfLedsV); - // print->print("1\n"); - //send to pview a message to get file filename JsonDocument *responseDoc = web->getResponseDoc(); responseDoc->clear(); //needed for deserializeJson? JsonVariant responseVariant = responseDoc->as(); - // print->print("2\n"); web->addResponse("pview", "file", fileName); web->sendDataWs(responseVariant); print->printJson("ledfix chFun send ws done", responseVariant); //during server startup this is not send to a client, so client refresh should also trigger this - // print->print("3\n"); } // if deserialize } //if fileName } @@ -143,19 +140,26 @@ LedsV& LedsV::operator=(const CRGB color) { // maps the virtual led to the physical led(s) and assign a color to it void LedsV::setPixelColor(int indexV, CRGB color) { - // if (indexV > mappingTable.size()) return; - if (!mappingTable.size() || indexV >= mappingTable.size()) return; - for (uint16_t indexP:mappingTable[indexV]) { - if (indexP < NUM_LEDS_Preview) - ledsP[indexP] = color; + if (mappingTable.size()) { + if (indexV >= mappingTable.size()) return; + for (uint16_t indexP:mappingTable[indexV]) { + if (indexP < NUM_LEDS_Preview) + ledsP[indexP] = color; + } } + else //no projection + ledsP[projectionNr==p_Random?random(nrOfLedsP):indexV] = color; } CRGB LedsV::getPixelColor(int indexV) { - if (!mappingTable.size() || indexV >= mappingTable.size()) return CRGB::Black; - if (!mappingTable[indexV].size() || mappingTable[indexV][0] > NUM_LEDS_Preview) return CRGB::Black; + if (mappingTable.size()) { + if (indexV >= mappingTable.size()) return CRGB::Black; + if (!mappingTable[indexV].size() || mappingTable[indexV][0] > NUM_LEDS_Preview) return CRGB::Black; - return ledsP[mappingTable[indexV][0]]; //any would do as they are all the same + return ledsP[mappingTable[indexV][0]]; //any would do as they are all the same + } + else //no projection + return ledsP[indexV]; } // LedsV& operator+=(const CRGB color) { diff --git a/src/App/AppLedsV.h b/src/App/AppLedsV.h index 3a121d3b..57ea1558 100644 --- a/src/App/AppLedsV.h +++ b/src/App/AppLedsV.h @@ -13,7 +13,7 @@ #include "ArduinoJson.h" #define NUM_LEDS_FastLed 1024 -#define NUM_LEDS_Preview 2000 +#define NUM_LEDS_Preview 4096 //keep them global for the time being as FastLed effects refer to them and want to keep that code as unchanged as possible //(so maybe move there?) @@ -27,6 +27,13 @@ class LedsV { public: // CRGB *leds = nullptr; CRGB ledsP[NUM_LEDS_Preview]; + // if (!leds) + // leds = (CRGB*)calloc(nrOfLeds, sizeof(CRGB)); + // else + // leds = (CRGB*)reallocarray(leds, nrOfLeds, sizeof(CRGB)); + // if (leds) free(leds); + // leds = (CRGB*)malloc(nrOfLeds * sizeof(CRGB)); + // leds = (CRGB*)reallocarray static uint16_t nrOfLedsP; //amount of physical leds static uint16_t nrOfLedsV; //amount of virtual leds (calculated by projection) @@ -39,7 +46,10 @@ class LedsV { static std::vector> mappingTable; static uint16_t mappingTableLedCounter; - void ledFixProjectAndMap(JsonObject ledFixObject, JsonObject projectionObject); + uint8_t projectionNr = -1; + uint8_t ledFixNr = -1; + + void ledFixProjectAndMap(); uint16_t indexVLocal = 0; diff --git a/src/App/AppModLedFixGen.h b/src/App/AppModLedFixGen.h index ff1afeb9..6a4760be 100644 --- a/src/App/AppModLedFixGen.h +++ b/src/App/AppModLedFixGen.h @@ -22,10 +22,22 @@ class AppModLedFixGen:public Module { parentObject = ui->initModule(parentObject, name); + ui->initText(parentObject, "width", nullptr, false, [](JsonObject object) { //uiFun + // web->addResponseV(object["id"], "comment", "Max %dK", 32); + }); + + ui->initText(parentObject, "height", nullptr, false, [](JsonObject object) { //uiFun + // web->addResponseV(object["id"], "comment", "Max %dK", 32); + }); + + ui->initText(parentObject, "depth", nullptr, false, [](JsonObject object) { //uiFun + // web->addResponseV(object["id"], "comment", "Max %dK", 32); + }); + enum Fixtures { f_1DSpiral, - f_2DM88, + f_2DMatrix, f_2DR24, f_2DR35, f_3DC885, @@ -34,11 +46,11 @@ class AppModLedFixGen:public Module { f_3DHumanSizedCube }; - ui->initSelect(parentObject, "ledFixGen", 3, false, [](JsonObject object) { //uiFun + ui->initSelect(parentObject, "ledFixGen", 0, false, [](JsonObject object) { //uiFun web->addResponse(object["id"], "label", "Ledfix generator"); JsonArray select = web->addResponseA(object["id"], "select"); select.add("1DSpiral"); //0 - select.add("2DMatrix88"); //1 + select.add("2DMatrix"); //1 select.add("2DRing24"); //2 select.add("2DRing35"); //3 select.add("3DCube885"); //4 @@ -47,7 +59,15 @@ class AppModLedFixGen:public Module { select.add("3DHumanSizedCube"); //7 }, [](JsonObject object) { //chFun - const char * name = "TT"; + }); //ledFixGen + + ui->initButton(parentObject, "generate", nullptr, [](JsonObject object) { //uiFun + // web->addResponse(object["id"], "comment", "All but model.json"); + }, [](JsonObject object) { + + uint8_t fix = mdl->getValue("ledFixGen").as(); + + char name[32] = "TT"; uint16_t nrOfLeds = 64; //default uint16_t diameter = 100; //in mm @@ -55,38 +75,43 @@ class AppModLedFixGen:public Module { uint16_t height = 0; uint16_t depth = 0; - uint8_t fix = object["value"]; switch (fix) { case f_1DSpiral: - name = "1DSpiral"; + strcpy(name, "1DSpiral"); nrOfLeds = 64; break; - case f_2DM88: - name = "2DMatrix88"; - nrOfLeds = 64; + case f_2DMatrix: + width = mdl->getValue("width"); + height = mdl->getValue("height"); + depth = 1; + nrOfLeds = width * height; + strcpy(name, "2DMatrix"); + char post[10]; + snprintf(post, sizeof(post), "%02d%02d", width, height); + strcat(name, post); break; case f_2DR24: - name = "2DRing24"; + strcpy(name, "2DRing24"); nrOfLeds = 24; break; case f_2DR35: - name = "2DRing35"; + strcpy(name, "2DRing35"); nrOfLeds = 35; break; case f_3DC885: - name = "3DCube885"; + strcpy(name, "3DCube885"); nrOfLeds = 320; break; case f_3DC888: - name = "3DCube888"; + strcpy(name, "3DCube888"); nrOfLeds = 512; break; case f_3DGlobe: - name = "3DGlobe"; + strcpy(name, "3DGlobe"); nrOfLeds = 512; break; case f_3DHumanSizedCube: - name = "3DHumanSizedCube"; + strcpy(name, "3DHumanSizedCube"); nrOfLeds = 2000; break; } @@ -136,23 +161,20 @@ class AppModLedFixGen:public Module { } f.printf("]}]"); break; - case f_2DM88: - diameter = 8; //in cm - - f.printf(",\"scale\":\"%s\"", "cm"); - f.printf(",\"size\":%d", diameter); - - width = 8; - height = 8; - depth = 1; + case f_2DMatrix: f.printf(",\"width\":%d", width); f.printf(",\"height\":%d", height); f.printf(",\"depth\":%d", depth); + diameter = width; //in cm + + f.printf(",\"scale\":\"%s\"", "cm"); + f.printf(",\"size\":%d", diameter); + f.printf(",\"outputs\":[{\"pin\":10,\"leds\":["); strcpy(sep,""); - for (uint8_t y = 0; y<8; y++) - for (uint16_t x = 0; x<8 ; x++) { + for (uint8_t y = 0; yprocessUiFun("ledFix"); - }); //ledFixGen + }); print->print("%s %s %s\n", __PRETTY_FUNCTION__, name, success?"success":"failed"); } diff --git a/src/App/AppModLeds.h b/src/App/AppModLeds.h index d2821dbc..1106e915 100644 --- a/src/App/AppModLeds.h +++ b/src/App/AppModLeds.h @@ -57,27 +57,18 @@ class AppModLeds:public Module { print->print("%s Change %s to %d\n", "initSelect chFun", object["id"].as(), object["value"].as()); }); - ui->initSelect(parentObject, "projection", 1, false, [](JsonObject object) { //uiFun. 1: is default + ui->initSelect(parentObject, "projection", 0, false, [](JsonObject object) { //uiFun. 1: is default // web->addResponse(object["id"], "label", "Effect"); web->addResponse(object["id"], "comment", "How to project fx to fixture"); JsonArray select = web->addResponseA(object["id"], "select"); select.add("None"); - select.add("Distance from point"); select.add("Random"); + select.add("Distance from point"); }, [](JsonObject object) { //chFun - print->print("%s Change %s to %d\n", "initSelect chFun", object["id"].as(), object["value"].as()); - // - uint8_t projection = object["value"]; - switch (projection) { - case 1: - // calculate mapping table - break; - } - - ledsV.ledFixProjectAndMap(mdl->findObject("ledFix"), object); - + ledsV.projectionNr = object["value"]; + ledsV.ledFixProjectAndMap(); }); ui->initCanvas(parentObject, "pview", map(5, 0, 255, 0, 100), [](JsonObject object) { //uiFun @@ -110,21 +101,14 @@ class AppModLeds:public Module { }, [](JsonObject object) { //chFun print->print("%s Change %s to %d\n", "initSelect chFun", object["id"].as(), object["value"].as()); - ledsV.ledFixProjectAndMap(object, mdl->findObject("projection")); + ledsV.ledFixNr = object["value"]; + ledsV.ledFixProjectAndMap(); }); //ledFix - ui->initText(parentObject, "width", nullptr, true, [](JsonObject object) { //uiFun - web->addResponseV(object["id"], "comment", "Max %dK", 32); - }); - - ui->initText(parentObject, "height", nullptr, true, [](JsonObject object) { //uiFun - web->addResponseV(object["id"], "comment", "Max %dK", 32); - }); - - ui->initText(parentObject, "depth", nullptr, true, [](JsonObject object) { //uiFun - web->addResponseV(object["id"], "comment", "Max %dK", 32); + ui->initText(parentObject, "dimensions", nullptr, true, [](JsonObject object) { //uiFun + // web->addResponseV(object["id"], "comment", "Max %dK", 32); }); ui->initText(parentObject, "nrOfLeds", nullptr, true, [](JsonObject object) { //uiFun @@ -132,20 +116,11 @@ class AppModLeds:public Module { }); //set the values by chFun + //to do: add page reload event (as these values should be given each time a page reloads, and they are not included in model.json as they are readonly... print->print("post whd %d %d %d and P:%d V:%d\n", ledsV.width, ledsV.height, ledsV.depth, ledsV.nrOfLedsP, ledsV.nrOfLedsV); - mdl->setValueI("width", ledsV.width); - mdl->setValueI("height", ledsV.height); - mdl->setValueI("depth", ledsV.depth); + mdl->setValueV("dimensions", "%dx%dx%d", ledsV.width, ledsV.height, ledsV.depth); mdl->setValueV("nrOfLeds", "P:%d V:%d", ledsV.nrOfLedsP, ledsV.nrOfLedsV); - // if (!leds) - // leds = (CRGB*)calloc(nrOfLeds, sizeof(CRGB)); - // else - // leds = (CRGB*)reallocarray(leds, nrOfLeds, sizeof(CRGB)); - // if (leds) free(leds); - // leds = (CRGB*)malloc(nrOfLeds * sizeof(CRGB)); - // leds = (CRGB*)reallocarray - ui->initNumber(parentObject, "fps", fps, [](JsonObject object) { //uiFun web->addResponse(object["id"], "comment", "Frames per second"); }, [](JsonObject object) { //chFun @@ -172,6 +147,7 @@ class AppModLeds:public Module { effects.push_back(new JuggleEffect); effects.push_back(new Ripples3DEffect); effects.push_back(new SphereMove3DEffect); + effects.push_back(new Frizzles2D); // FastLED.addLeds(leds, 1); FastLED.addLeds(ledsP, NUM_LEDS_FastLed); diff --git a/src/Sys/SysJsonRDWS.h b/src/Sys/SysJsonRDWS.h index e1727156..93fbaec7 100644 --- a/src/Sys/SysJsonRDWS.h +++ b/src/Sys/SysJsonRDWS.h @@ -142,21 +142,15 @@ class JsonRDWS { // print->print("Array pop %s %d %d\n", lastObjectId, objectStack.size(), uint16CollectList.size()); check(lastObjectId); - // print->print("1\n"); //check the parent array, if exists if (objectStack.size()-2 >=0) { - // print->print("2\n"); // print->print(" Parent check %s\n", objectStack[objectStack.size()-2].c_str()); strcpy(beforeLastObjectId, objectStack[objectStack.size()-2].c_str()); check(beforeLastObjectId); - // print->print("3\n"); } objectStack.pop_back(); //remove objectid of this array - // print->print("4\n"); collectNumbers = false; - // print->print("5\n"); uint16CollectList.clear(); - // print->print("6\n"); f.read(&character, sizeof(byte)); } else if (character=='"') { //parse String @@ -222,25 +216,20 @@ class JsonRDWS { } //next void check(char * objectId, char * value = nullptr) { - // print->print("2.1\n"); for (std::vector::iterator od=objectDetails.begin(); od!=objectDetails.end(); ++od) { - // print->print("2.2\n"); // print->print("check %s %s %s\n", od->id, object, value); if (strcmp(od->id, objectId)==0) { - // print->print("2.3\n"); // print->print("JsonRDWS found %s:%s %d %s\n", objectId, od->type, od->index, value?value:"", uint16CollectList.size()); if (strcmp(od->type, "uint8") ==0) *uint8List[od->index] = atoi(value); if (strcmp(od->type, "uint16") ==0) *uint16List[od->index] = atoi(value); if (strcmp(od->type, "char") ==0) strcpy(charList[od->index], value); if (strcmp(od->type, "fun") ==0) funList[od->index](uint16CollectList); foundCounter++; - // print->print("2.4\n"); } } // foundAll = foundCounter >= objectDetails.size(); // if (foundAll) // print->print("Hooray, LazyJsonRDWS found all what we were looking for, no further search needed\n"); - // print->print("2.5\n"); } //writeJsonVariantToFile calls itself recursively until whole json document has been parsed