diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aabf97f..a2949a60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### Development versions after 0.11.1 release +#### Build 2101310 + +- First alpha configurable multipin + #### Build 2101130 - Added color transitions for all segments and slots and for segment brightness diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/usermod_temperature.h index d72be934..1ce0322e 100644 --- a/usermods/Temperature/usermod_temperature.h +++ b/usermods/Temperature/usermod_temperature.h @@ -5,11 +5,13 @@ #include //DS18B20 //Pin defaults for QuinLed Dig-Uno +#ifndef TEMPERATURE_PIN #ifdef ARDUINO_ARCH_ESP32 #define TEMPERATURE_PIN 18 #else //ESP8266 boards #define TEMPERATURE_PIN 14 #endif +#endif // the frequency to check temperature, 1 minute #ifndef USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL @@ -58,6 +60,7 @@ class UsermodTemperature : public Usermod { } void getTemperature() { + if (strip.isUpdating()) return; #ifdef USERMOD_DALLASTEMPERATURE_CELSIUS temperature = sensor.getTempC(sensorDeviceAddress); #else @@ -80,30 +83,28 @@ class UsermodTemperature : public Usermod { disabled = !sensor.getAddress(sensorDeviceAddress, 0); if (!disabled) { - DEBUG_PRINTLN("Dallas Temperature found"); + DEBUG_PRINTLN(F("Dallas Temperature found")); // set the resolution for this specific device sensor.setResolution(sensorDeviceAddress, 9, true); // do not block waiting for reading - sensor.setWaitForConversion(false); + sensor.setWaitForConversion(false); + // allocate pin & prevent other use + if (!pinManager.allocatePin(TEMPERATURE_PIN,false)) + disabled = true; } else { - DEBUG_PRINTLN("Dallas Temperature not found"); + DEBUG_PRINTLN(F("Dallas Temperature not found")); } } void loop() { - if (disabled) { - return; - } + if (disabled || strip.isUpdating()) return; unsigned long now = millis(); // check to see if we are due for taking a measurement // lastMeasurement will not be updated until the conversion // is complete the the reading is finished - if (now - lastMeasurement < USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL) - { - return; - } + if (now - lastMeasurement < USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL) return; // we are due for a measurement, if we are not already waiting // for a conversion to complete, then make a new request for temps @@ -125,7 +126,7 @@ class UsermodTemperature : public Usermod { // dont publish super low temperature as the graph will get messed up // the DallasTemperature library returns -127C or -196.6F when problem // reading the sensor - strcat(subuf, "/temperature"); + strcat_P(subuf, PSTR("/temperature")); mqtt->publish(subuf, 0, true, String(temperature).c_str()); } else { // publish something else to indicate status? @@ -136,34 +137,32 @@ class UsermodTemperature : public Usermod { void addToJsonInfo(JsonObject& root) { // dont add temperature to info if we are disabled - if (disabled) { - return; - } + if (disabled) return; - JsonObject user = root["u"]; - if (user.isNull()) user = root.createNestedObject("u"); + JsonObject user = root[F("u")]; + if (user.isNull()) user = root.createNestedObject(F("u")); - JsonArray temp = user.createNestedArray("Temperature"); + JsonArray temp = user.createNestedArray(F("Temperature")); if (!getTemperatureComplete) { // if we haven't read the sensor yet, let the user know // that we are still waiting for the first measurement temp.add((USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT - millis()) / 1000); - temp.add(" sec until read"); + temp.add(F(" sec until read")); return; } if (temperature <= -100) { temp.add(0); - temp.add(" Sensor Error!"); + temp.add(F(" Sensor Error!")); return; } temp.add(temperature); #ifdef USERMOD_DALLASTEMPERATURE_CELSIUS - temp.add("°C"); + temp.add(F("°C")); #else - temp.add("°F"); + temp.add(F("°F")); #endif } diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 27bd730d..6852674e 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1265,7 +1265,7 @@ uint16_t WS2812FX::police_base(uint32_t color1, uint32_t color2, bool all) for (uint16_t i = idexB; i < idexR; i++) setPixelColor(i, color2); } } else { //regular dot-only mode - uint8_t size = 1 + SEGMENT.intensity >> 3; + uint8_t size = 1 + (SEGMENT.intensity >> 3); if (size > SEGLEN/2) size = 1+ SEGLEN/2; for (uint8_t i=0; i <= size; i++) { setPixelColor(idexR+i, color1); diff --git a/wled00/FX.h b/wled00/FX.h index ab90e4bd..e6c7cbd8 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -29,42 +29,6 @@ #ifndef WS2812FX_h #define WS2812FX_h -//TEMPORARY DEFINES FOR TESTING - MAKE THESE RUNTIME CONFIGURABLE TOO! -#ifndef LEDPIN -#define LEDPIN 2 -#endif - -#ifndef BTNPIN -#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended) -#endif - -#ifndef TOUCHPIN -//#define TOUCHPIN T0 //touch pin. Behaves the same as button. ESP32 only. -#endif - -#ifndef IRPIN -#define IRPIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0 -#endif - -#ifndef RLYPIN -#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,... -#endif - -#ifndef AUXPIN -#define AUXPIN -1 //debug auxiliary output pin (-1 to disable) -#endif - -#ifndef RLYMDE -#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on -#endif -//END OF TEMP DEFINES - -#ifdef ESP32_MULTISTRIP - #include "../usermods/esp32_multistrip/NpbWrapper.h" -#else - #include "bus_manager.h" -#endif - #include "const.h" #define FASTLED_INTERNAL //remove annoying pragma messages @@ -616,12 +580,11 @@ class WS2812FX { ablMilliampsMax = 850; currentMilliamps = 0; timebase = 0; - busses = new BusManager(); resetSegments(); } void - init(bool supportWhite, uint16_t countPixels, bool skipFirst), + finalizeInit(bool supportWhite, uint16_t countPixels, bool skipFirst), service(void), blur(uint8_t), fill(uint32_t), @@ -661,6 +624,8 @@ class WS2812FX { paletteFade = 0, paletteBlend = 0, milliampsPerLed = 55, +// getStripType(uint8_t strip=0), +// setStripType(uint8_t type, uint8_t strip=0), getBrightness(void), getMode(void), getSpeed(void), @@ -675,11 +640,17 @@ class WS2812FX { get_random_wheel_index(uint8_t); int8_t +// setStripPin(uint8_t strip, int8_t pin), +// getStripPin(uint8_t strip=0), +// setStripPinClk(uint8_t strip, int8_t pin), +// getStripPinClk(uint8_t strip=0), tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec); uint16_t ablMilliampsMax, currentMilliamps, +// setStripLen(uint8_t strip, uint16_t len), +// getStripLen(uint8_t strip=0), triwave16(uint16_t); uint32_t @@ -826,8 +797,6 @@ class WS2812FX { mode_dynamic_smooth(void); private: - BusManager *busses; - uint32_t crgb_to_col(CRGB fastled); CRGB col_to_crgb(uint32_t); CRGBPalette16 currentPalette; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 26181805..98d0131d 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -49,7 +49,7 @@ const uint16_t customMappingSize = sizeof(customMappingTable)/sizeof(uint16_t); #endif //do not call this method from system context (network callback) -void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst) +void WS2812FX::finalizeInit(bool supportWhite, uint16_t countPixels, bool skipFirst) { if (supportWhite == _useRgbw && countPixels == _length && _skipFirstMode == skipFirst) return; RESET_RUNTIME; @@ -62,11 +62,12 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst) _lengthRaw += LED_SKIP_AMOUNT; } - uint8_t pins[] = {LEDPIN}; - - while (!busses->canAllShow()) yield(); - busses->removeAll(); - busses->add(supportWhite? TYPE_SK6812_RGBW : TYPE_WS2812_RGB, pins, 0, countPixels, COL_ORDER_GRB); + //if busses failed to load, add default (FS issue...) + if (busses.getNumBusses() == 0) { + uint8_t defPin[] = {LEDPIN}; + BusConfig defCfg = BusConfig(TYPE_WS2812_RGB, defPin, 0, _lengthRaw, COL_ORDER_GRB); + busses.add(defCfg); + } _segments[0].start = 0; _segments[0].stop = _length; @@ -74,8 +75,8 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst) setBrightness(_brightness); #ifdef ESP8266 - for (uint8_t i = 0; i < busses->getNumBusses(); i++) { - Bus* b = busses->getBus(i); + for (uint8_t i = 0; i < busses.getNumBusses(); i++) { + Bus* b = busses.getBus(i); if ((!IS_DIGITAL(b->getType()) || IS_2PIN(b->getType()))) continue; uint8_t pins[5]; b->getPins(pins); @@ -205,12 +206,12 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet]; #endif if (indexSetRev >= SEGMENT.start && indexSetRev < SEGMENT.stop) { - busses->setPixelColor(indexSet + skip, col); + busses.setPixelColor(indexSet + skip, col); if (IS_MIRROR) { //set the corresponding mirrored pixel if (reverseMode) { - busses->setPixelColor(REV(SEGMENT.start) - indexSet + skip + REV(SEGMENT.stop) + 1, col); + busses.setPixelColor(REV(SEGMENT.start) - indexSet + skip + REV(SEGMENT.stop) + 1, col); } else { - busses->setPixelColor(SEGMENT.stop - indexSet + skip + SEGMENT.start - 1, col); + busses.setPixelColor(SEGMENT.stop - indexSet + skip + SEGMENT.start - 1, col); } } } @@ -221,11 +222,11 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) if (i < customMappingSize) i = customMappingTable[i]; #endif uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b)); - busses->setPixelColor(i + skip, col); + busses.setPixelColor(i + skip, col); } if (skip && i == 0) { for (uint16_t j = 0; j < skip; j++) { - busses->setPixelColor(j, BLACK); + busses.setPixelColor(j, BLACK); } } } @@ -276,7 +277,7 @@ void WS2812FX::show(void) { for (uint16_t i = 0; i < _length; i++) //sum up the usage of each LED { - RgbwColor c = busses->getPixelColor(i); + RgbwColor c = busses.getPixelColor(i); if(useWackyWS2815PowerModel) { @@ -305,24 +306,24 @@ void WS2812FX::show(void) { uint16_t scaleI = scale * 255; uint8_t scaleB = (scaleI > 255) ? 255 : scaleI; uint8_t newBri = scale8(_brightness, scaleB); - busses->setBrightness(newBri); + busses.setBrightness(newBri); currentMilliamps = (powerSum0 * newBri) / puPerMilliamp; } else { currentMilliamps = powerSum / puPerMilliamp; - busses->setBrightness(_brightness); + busses.setBrightness(_brightness); } currentMilliamps += MA_FOR_ESP; //add power of ESP back to estimate currentMilliamps += _length; //add standby power back to estimate } else { currentMilliamps = 0; - busses->setBrightness(_brightness); + busses.setBrightness(_brightness); } // some buses send asynchronously and this method will return before // all of the data has been sent. // See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods - busses->show(); + busses.show(); _lastShow = millis(); } @@ -331,7 +332,7 @@ void WS2812FX::show(void) { * On some hardware (ESP32), strip updates are done asynchronously. */ bool WS2812FX::isUpdating() { - return !busses->canAllShow(); + return !busses.canAllShow(); } /** @@ -492,7 +493,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i) if (i >= _lengthRaw) return 0; - return busses->getPixelColor(i); + return busses.getPixelColor(i); } WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) { diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index c92d24ec..265da36c 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -10,6 +10,23 @@ #include "bus_wrapper.h" #include +//temporary struct for passing bus configuration to bus +struct BusConfig { + uint8_t type = TYPE_WS2812_RGB; + uint16_t count = 1; + uint16_t start = 0; + uint8_t colorOrder = COL_ORDER_GRB; + bool reversed = false; + uint8_t pins[5] = {LEDPIN, 255, 255, 255, 255}; + BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false) { + type = busType; count = len; start = pstart; colorOrder = pcolorOrder; reversed = rev; + uint8_t nPins = 1; + if (type > 47) nPins = 2; + else if (type > 41 && type < 46) nPins = NUM_PWM_PINS(type); + for (uint8_t i = 0; i < nPins; i++) pins[i] = ppins[i]; + } +}; + //parent class of BusDigital and BusPwm class Bus { public: @@ -73,23 +90,23 @@ class Bus { class BusDigital : public Bus { public: - BusDigital(uint8_t type, uint8_t* pins, uint16_t start, uint16_t len, uint8_t colorOrder, uint8_t nr, bool rev) : Bus(type, start) { - if (!IS_DIGITAL(type) || !len) return; - _pins[0] = pins[0]; + BusDigital(BusConfig &bc, uint8_t nr) : Bus(bc.type, bc.start) { + if (!IS_DIGITAL(bc.type) || !bc.count) return; + _pins[0] = bc.pins[0]; if (!pinManager.allocatePin(_pins[0])) return; - if (IS_2PIN(type)) { - _pins[1] = pins[1]; + if (IS_2PIN(bc.type)) { + _pins[1] = bc.pins[1]; if (!pinManager.allocatePin(_pins[1])) { cleanup(); return; } } - _len = len; - reversed = rev; - _iType = PolyBus::getI(type, _pins, nr); + _len = bc.count; + reversed = bc.reversed; + _iType = PolyBus::getI(bc.type, _pins, nr); if (_iType == I_NONE) return; _busPtr = PolyBus::create(_iType, _pins, _len); _valid = (_busPtr != nullptr); - _colorOrder = colorOrder; + _colorOrder = bc.colorOrder; //Serial.printf("Successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n",nr, len, type, pins[0],pins[1],_iType); }; @@ -170,9 +187,9 @@ class BusDigital : public Bus { class BusPwm : public Bus { public: - BusPwm(uint8_t type, uint8_t* pins, uint16_t start) : Bus(type, start) { - if (!IS_PWM(type)) return; - uint8_t numPins = NUM_PWM_PINS(type); + BusPwm(BusConfig &bc) : Bus(bc.type, bc.start) { + if (!IS_PWM(bc.type)) return; + uint8_t numPins = NUM_PWM_PINS(bc.type); #ifdef ESP8266 analogWriteRange(255); //same range as one RGB channel @@ -185,7 +202,7 @@ class BusPwm : public Bus { #endif for (uint8_t i = 0; i < numPins; i++) { - _pins[i] = pins[i]; + _pins[i] = bc.pins[i]; if (!pinManager.allocatePin(_pins[i])) { deallocatePins(); return; } @@ -281,19 +298,22 @@ class BusManager { }; - int add(uint8_t busType, uint8_t* pins, uint16_t start, uint16_t len = 1, uint8_t colorOrder = COL_ORDER_GRB, bool rev = false) { + int add(BusConfig &bc) { if (numBusses >= WLED_MAX_BUSSES) return -1; - if (IS_DIGITAL(busType)) { - busses[numBusses] = new BusDigital(busType, pins, start, len, colorOrder, numBusses, rev); + if (IS_DIGITAL(bc.type)) { + busses[numBusses] = new BusDigital(bc, numBusses); } else { - busses[numBusses] = new BusPwm(busType, pins, start); + busses[numBusses] = new BusPwm(bc); } numBusses++; return numBusses -1; } + //do not call this method from system context (network callback) void removeAll() { //Serial.println("Removing all."); + //prevents crashes due to deleting busses while in use. + while (!canAllShow()) yield(); for (uint8_t i = 0; i < numBusses; i++) delete busses[i]; numBusses = 0; } @@ -346,6 +366,12 @@ class BusManager { return numBusses; } + static bool isRgbw(uint8_t type) { + if (type == TYPE_SK6812_RGBW || type == TYPE_TM1814) return true; + if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; + return false; + } + private: uint8_t numBusses = 0; Bus* busses[WLED_MAX_BUSSES]; diff --git a/wled00/button.cpp b/wled00/button.cpp index 7adbf68b..458ff22a 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -17,9 +17,7 @@ void shortPressAction() bool isButtonPressed() { - #if defined(BTNPIN) && BTNPIN > -1 - if (digitalRead(BTNPIN) == LOW) return true; - #endif + if (btnPin>=0 && digitalRead(btnPin) == LOW) return true; #ifdef TOUCHPIN if (touchRead(TOUCHPIN) <= TOUCH_THRESHOLD) return true; #endif @@ -29,8 +27,7 @@ bool isButtonPressed() void handleButton() { -#if (defined(BTNPIN) && BTNPIN > -1) || defined(TOUCHPIN) - if (!buttonEnabled) return; + if (btnPin<0 || !buttonEnabled) return; if (isButtonPressed()) //pressed { @@ -75,7 +72,6 @@ void handleButton() buttonWaitTime = 0; shortPressAction(); } -#endif } void handleIO() @@ -88,37 +84,39 @@ void handleIO() lastOnTime = millis(); if (offMode) { - #if RLYPIN >= 0 - digitalWrite(RLYPIN, RLYMDE); - #endif + if (rlyPin>=0) { + pinMode(rlyPin, OUTPUT); + digitalWrite(rlyPin, rlyMde); + } offMode = false; } } else if (millis() - lastOnTime > 600) { - if (!offMode) { - #if LEDPIN == LED_BUILTIN - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, HIGH); + if (!offMode) { + #ifdef ESP8266 + //turn off built-in LED if strip is turned off + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, HIGH); #endif - #if RLYPIN >= 0 - digitalWrite(RLYPIN, !RLYMDE); - #endif - } + if (rlyPin>=0) { + pinMode(rlyPin, OUTPUT); + digitalWrite(rlyPin, !rlyMde); + } + } offMode = true; } - #if AUXPIN >= 0 //output - if (auxActive || auxActiveBefore) + if (auxPin>=1 && (auxActive || auxActiveBefore)) { if (!auxActiveBefore) { auxActiveBefore = true; switch (auxTriggeredState) { - case 0: pinMode(AUXPIN, INPUT); break; - case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break; - case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break; + case 0: pinMode(auxPin, INPUT); break; + case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break; + case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break; } auxStartTime = millis(); } @@ -128,11 +126,10 @@ void handleIO() auxActiveBefore = false; switch (auxDefaultState) { - case 0: pinMode(AUXPIN, INPUT); break; - case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break; - case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break; + case 0: pinMode(auxPin, INPUT); break; + case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break; + case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break; } } } - #endif } diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 43d2615e..2175c97b 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -30,8 +30,6 @@ void deserializeConfig() { return; } - //deserializeJson(doc, json); - //int rev_major = doc[F("rev")][0]; // 1 //int rev_minor = doc[F("rev")][1]; // 0 @@ -89,7 +87,9 @@ void deserializeConfig() { JsonObject hw = doc[F("hw")]; + // initialize LED pins and lengths prior to other HW JsonObject hw_led = hw[F("led")]; + CJSON(ledCount, hw_led[F("total")]); if (ledCount > MAX_LEDS) ledCount = MAX_LEDS; @@ -98,22 +98,51 @@ void deserializeConfig() { CJSON(strip.reverseMode, hw_led[F("rev")]); CJSON(strip.rgbwMode, hw_led[F("rgbwm")]); - JsonObject hw_led_ins_0 = hw_led[F("ins")][0]; - //bool hw_led_ins_0_en = hw_led_ins_0[F("en")]; // true - //int hw_led_ins_0_start = hw_led_ins_0[F("start")]; // 0 - //int hw_led_ins_0_len = hw_led_ins_0[F("len")]; // 1200 + JsonArray ins = hw_led["ins"]; + uint8_t s = 0; + useRGBW = false; + busses.removeAll(); + for (JsonObject elm : ins) { + if (s >= WLED_MAX_BUSSES) break; + uint8_t pins[5] = {255, 255, 255, 255, 255}; + JsonArray pinArr = elm[F("pin")]; + if (pinArr.size() == 0) continue; + pins[0] = pinArr[0]; + uint8_t i = 0; + for (int p : pinArr) { + pins[i] = p; + i++; + if (i>4) break; + } - //int hw_led_ins_0_pin_0 = hw_led_ins_0[F("pin")][0]; // 2 - - strip.setColorOrder(hw_led_ins_0[F("order")]); - //bool hw_led_ins_0_rev = hw_led_ins_0[F("rev")]; // false - skipFirstLed = hw_led_ins_0[F("skip")]; // 0 - useRGBW = (hw_led_ins_0[F("type")] == TYPE_SK6812_RGBW); + uint16_t length = elm[F("len")]; + if (length==0) continue; + uint8_t colorOrder = (int)elm[F("order")]; + //only use skip from the first strip (this shouldn't have been in ins obj. but remains here for compatibility) + if (s==0) skipFirstLed = elm[F("skip")]; + uint16_t start = elm[F("start")] | 0; + if (start >= ledCount) continue; + //limit length of strip if it would exceed total configured LEDs + if (start + length > ledCount) length = ledCount - start; + uint8_t ledType = elm[F("type")] | TYPE_WS2812_RGB; + bool reversed = elm[F("rev")]; + //RGBW mode is enabled if at least one of the strips is RGBW + useRGBW = (useRGBW || BusManager::isRgbw(ledType)); + s++; + BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed); + busses.add(bc); + } + strip.finalizeInit(useRGBW, ledCount, skipFirstLed); JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0]; - buttonEnabled = hw_btn_ins_0[F("en")] | buttonEnabled; - - //int hw_btn_ins_0_pin_0 = hw_btn_ins_0[F("pin")][0]; // 0 + CJSON(buttonEnabled, hw_btn_ins_0[F("type")]); + int hw_btn_pin = hw_btn_ins_0[F("pin")][0]; + if (pinManager.allocatePin(hw_btn_pin,false)) { + btnPin = hw_btn_pin; + pinMode(btnPin, INPUT_PULLUP); + } else { + btnPin = -1; + } JsonArray hw_btn_ins_0_macros = hw_btn_ins_0[F("macros")]; CJSON(macroButton, hw_btn_ins_0_macros[0]); @@ -122,11 +151,24 @@ void deserializeConfig() { //int hw_btn_ins_0_type = hw_btn_ins_0[F("type")]; // 0 - //int hw_ir_pin = hw[F("ir")][F("pin")]; // 4 - CJSON(irEnabled, hw[F("ir")][F("type")]); // 0 + #ifndef WLED_DISABLE_INFRARED + int hw_ir_pin = hw[F("ir")][F("pin")]; // 4 + if (pinManager.allocatePin(hw_ir_pin,false)) { + irPin = hw_ir_pin; + } else { + irPin = -1; + } + #endif + CJSON(irEnabled, hw[F("ir")][F("type")]); - //int hw_relay_pin = hw[F("relay")][F("pin")]; // 12 - //bool hw_relay_rev = hw[F("relay")][F("rev")]; // false + int hw_relay_pin = hw[F("relay")][F("pin")]; + if (pinManager.allocatePin(hw_relay_pin,true)) { + rlyPin = hw_relay_pin; + pinMode(rlyPin, OUTPUT); + } else { + rlyPin = -1; + } + CJSON(rlyMde, hw[F("relay")][F("rev")]); //int hw_status_pin = hw[F("status")][F("pin")]; // -1 @@ -404,70 +446,57 @@ void serializeConfig() { JsonArray hw_led_ins = hw_led.createNestedArray("ins"); - JsonObject hw_led_ins_0 = hw_led_ins.createNestedObject(); - hw_led_ins_0[F("en")] = true; - hw_led_ins_0[F("start")] = 0; - hw_led_ins_0[F("len")] = ledCount; - JsonArray hw_led_ins_0_pin = hw_led_ins_0.createNestedArray("pin"); - hw_led_ins_0_pin.add(LEDPIN); - #ifdef DATAPIN - hw_led_ins_0_pin.add(DATAPIN); - #endif - hw_led_ins_0[F("order")] = strip.getColorOrder(); - hw_led_ins_0[F("rev")] = false; - hw_led_ins_0[F("skip")] = skipFirstLed ? 1 : 0; - - //this is very crude and temporary - byte ledType = TYPE_WS2812_RGB; - if (useRGBW) ledType = TYPE_SK6812_RGBW; - #ifdef USE_WS2801 - ledType = TYPE_WS2801; - #endif - #ifdef USE_APA102 - ledType = TYPE_APA102; - #endif - #ifdef USE_LPD8806 - ledType = TYPE_LPD8806; - #endif - #ifdef USE_P9813 - ledType = TYPE_P9813; - #endif - #ifdef USE_TM1814 - ledType = TYPE_TM1814; - #endif - - hw_led_ins_0[F("type")] = ledType; + uint16_t start = 0; + for (uint8_t s = 0; s < busses.getNumBusses(); s++) { + Bus *bus = busses.getBus(s); + if (!bus || bus->getLength()==0) break; + JsonObject ins = hw_led_ins.createNestedObject(); + ins[F("en")] = true; + ins[F("start")] = bus->getStart(); + ins[F("len")] = bus->getLength(); + JsonArray ins_pin = ins.createNestedArray("pin"); + uint8_t pins[5]; + uint8_t nPins = bus->getPins(pins); + for (uint8_t i = 0; i < nPins; i++) ins_pin.add(pins[i]); + ins[F("order")] = bus->getColorOrder(); + ins[F("rev")] = bus->reversed; + ins[F("skip")] = (skipFirstLed && s == 0) ? 1 : 0; + ins[F("type")] = bus->getType(); + } JsonObject hw_btn = hw.createNestedObject("btn"); JsonArray hw_btn_ins = hw_btn.createNestedArray("ins"); - #if defined(BTNPIN) && BTNPIN > -1 + // button BTNPIN JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject(); hw_btn_ins_0[F("type")] = (buttonEnabled) ? BTN_TYPE_PUSH : BTN_TYPE_NONE; JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin"); - hw_btn_ins_0_pin.add(BTNPIN); + hw_btn_ins_0_pin.add(btnPin); JsonArray hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros"); hw_btn_ins_0_macros.add(macroButton); hw_btn_ins_0_macros.add(macroLongPress); hw_btn_ins_0_macros.add(macroDoublePress); + + #ifndef WLED_DISABLE_INFRARED + if (irPin>=0) { + JsonObject hw_ir = hw.createNestedObject("ir"); + hw_ir[F("pin")] = irPin; + hw_ir[F("type")] = irEnabled; // the byte 'irEnabled' does contain the IR-Remote Type ( 0=disabled ) + } #endif - #if defined(IRPIN) && IRPIN > -1 - JsonObject hw_ir = hw.createNestedObject("ir"); - hw_ir[F("pin")] = IRPIN; - hw_ir[F("type")] = irEnabled; // the byte 'irEnabled' does contain the IR-Remote Type ( 0=disabled ) - #endif - - #if defined(RLYPIN) && RLYPIN > -1 JsonObject hw_relay = hw.createNestedObject("relay"); - hw_relay[F("pin")] = RLYPIN; - hw_relay[F("rev")] = (RLYMDE) ? false : true; - JsonObject hw_status = hw.createNestedObject("status"); - hw_status[F("pin")] = -1; - #endif + hw_relay[F("pin")] = rlyPin; + hw_relay[F("rev")] = rlyMde; + + //JsonObject hw_status = hw.createNestedObject("status"); + //hw_status[F("pin")] = -1; + + JsonObject hw_aux = hw.createNestedObject("aux"); + hw_aux[F("pin")] = auxPin; JsonObject light = doc.createNestedObject("light"); light[F("scale-bri")] = briMultiplier; diff --git a/wled00/const.h b/wled00/const.h index 326d3e85..afc235af 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -95,8 +95,8 @@ #define TYPE_WS2812_RGB 22 #define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern) #define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units -#define TYPE_TM1814 25 #define TYPE_SK6812_RGBW 30 +#define TYPE_TM1814 31 //"Analog" types (PWM) (32-47) #define TYPE_ONOFF 40 //binary output (relays etc.) #define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel @@ -163,6 +163,9 @@ #define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached #define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist #define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured +#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented) +#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented) +#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented) //Timer mode types #define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness @@ -205,4 +208,9 @@ #define JSON_BUFFER_SIZE 16384 #endif +//this is merely a default now and can be changed at runtime +#ifndef LEDPIN +#define LEDPIN 2 +#endif + #endif diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 6a0dee0a..4671f4e3 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -5,7 +5,7 @@ LED Settings