Pin manager enhancements (sharing I2C pins).
Effect helpers in UI.
This commit is contained in:
parent
65ac8d4b2b
commit
108fc4a0d8
@ -3,6 +3,14 @@
|
||||
#include "src/dependencies/time/DS1307RTC.h"
|
||||
#include "wled.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#else
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#endif
|
||||
|
||||
//Connect DS1307 to standard I2C pins (ESP32: GPIO 21 (SDA)/GPIO 22 (SCL))
|
||||
|
||||
class RTCUsermod : public Usermod {
|
||||
@ -12,6 +20,8 @@ class RTCUsermod : public Usermod {
|
||||
public:
|
||||
|
||||
void setup() {
|
||||
PinManagerPinType pins[2] = { { HW_PIN_SCL, true }, { HW_PIN_SDA, true } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { disabled = true; return; }
|
||||
time_t rtcTime = RTC.get();
|
||||
if (rtcTime) {
|
||||
toki.setTime(rtcTime,TOKI_NO_MS_ACCURACY,TOKI_TS_RTC);
|
||||
@ -28,6 +38,19 @@ class RTCUsermod : public Usermod {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||
*/
|
||||
void addToConfig(JsonObject& root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject("RTC");
|
||||
JsonArray pins = top.createNestedArray("pin");
|
||||
pins.add(HW_PIN_SCL);
|
||||
pins.add(HW_PIN_SDA);
|
||||
}
|
||||
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_RTC;
|
||||
|
@ -21,6 +21,14 @@
|
||||
#include <Wire.h>
|
||||
#include <VL53L0X.h>
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#else
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#endif
|
||||
|
||||
#ifndef VL53L0X_MAX_RANGE_MM
|
||||
#define VL53L0X_MAX_RANGE_MM 230 // max height in millimiters to react for motions
|
||||
#endif
|
||||
@ -42,6 +50,7 @@ class UsermodVL53L0XGestures : public Usermod {
|
||||
//Private class members. You can declare variables and functions only accessible to your usermod here
|
||||
unsigned long lastTime = 0;
|
||||
VL53L0X sensor;
|
||||
bool enabled = true;
|
||||
|
||||
bool wasMotionBefore = false;
|
||||
bool isLongMotion = false;
|
||||
@ -50,6 +59,8 @@ class UsermodVL53L0XGestures : public Usermod {
|
||||
public:
|
||||
|
||||
void setup() {
|
||||
PinManagerPinType pins[2] = { { HW_PIN_SCL, true }, { HW_PIN_SDA, true } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { enabled = false; return; }
|
||||
Wire.begin();
|
||||
|
||||
sensor.setTimeout(150);
|
||||
@ -63,6 +74,7 @@ class UsermodVL53L0XGestures : public Usermod {
|
||||
|
||||
|
||||
void loop() {
|
||||
if (!enabled) return;
|
||||
if (millis() - lastTime > VL53L0X_DELAY_MS)
|
||||
{
|
||||
lastTime = millis();
|
||||
@ -110,6 +122,19 @@ class UsermodVL53L0XGestures : public Usermod {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||
*/
|
||||
void addToConfig(JsonObject& root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject("VL53L0x");
|
||||
JsonArray pins = top.createNestedArray("pin");
|
||||
pins.add(HW_PIN_SCL);
|
||||
pins.add(HW_PIN_SDA);
|
||||
}
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||
|
@ -42,6 +42,14 @@
|
||||
#include "Wire.h"
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#else
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#endif
|
||||
|
||||
// ================================================================
|
||||
// === INTERRUPT DETECTION ROUTINE ===
|
||||
// ================================================================
|
||||
@ -55,7 +63,8 @@ void IRAM_ATTR dmpDataReady() {
|
||||
class MPU6050Driver : public Usermod {
|
||||
private:
|
||||
MPU6050 mpu;
|
||||
|
||||
bool enabled = true;
|
||||
|
||||
// MPU control/status vars
|
||||
bool dmpReady = false; // set true if DMP init was successful
|
||||
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
|
||||
@ -84,6 +93,8 @@ class MPU6050Driver : public Usermod {
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
*/
|
||||
void setup() {
|
||||
PinManagerPinType pins[2] = { { HW_PIN_SCL, true }, { HW_PIN_SDA, true } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { enabled = false; return; }
|
||||
// join I2C bus (I2Cdev library doesn't do this automatically)
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
|
||||
Wire.begin();
|
||||
@ -93,16 +104,16 @@ class MPU6050Driver : public Usermod {
|
||||
#endif
|
||||
|
||||
// initialize device
|
||||
Serial.println(F("Initializing I2C devices..."));
|
||||
DEBUG_PRINTLN(F("Initializing I2C devices..."));
|
||||
mpu.initialize();
|
||||
pinMode(INTERRUPT_PIN, INPUT);
|
||||
|
||||
// verify connection
|
||||
Serial.println(F("Testing device connections..."));
|
||||
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
|
||||
DEBUG_PRINTLN(F("Testing device connections..."));
|
||||
DEBUG_PRINTLN(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
|
||||
|
||||
// load and configure the DMP
|
||||
Serial.println(F("Initializing DMP..."));
|
||||
DEBUG_PRINTLN(F("Initializing DMP..."));
|
||||
devStatus = mpu.dmpInitialize();
|
||||
|
||||
// supply your own gyro offsets here, scaled for min sensitivity
|
||||
@ -114,16 +125,16 @@ class MPU6050Driver : public Usermod {
|
||||
// make sure it worked (returns 0 if so)
|
||||
if (devStatus == 0) {
|
||||
// turn on the DMP, now that it's ready
|
||||
Serial.println(F("Enabling DMP..."));
|
||||
DEBUG_PRINTLN(F("Enabling DMP..."));
|
||||
mpu.setDMPEnabled(true);
|
||||
|
||||
// enable Arduino interrupt detection
|
||||
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
|
||||
DEBUG_PRINTLN(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
|
||||
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
|
||||
mpuIntStatus = mpu.getIntStatus();
|
||||
|
||||
// set our DMP Ready flag so the main loop() function knows it's okay to use it
|
||||
Serial.println(F("DMP ready! Waiting for first interrupt..."));
|
||||
DEBUG_PRINTLN(F("DMP ready! Waiting for first interrupt..."));
|
||||
dmpReady = true;
|
||||
|
||||
// get expected DMP packet size for later comparison
|
||||
@ -133,9 +144,9 @@ class MPU6050Driver : public Usermod {
|
||||
// 1 = initial memory load failed
|
||||
// 2 = DMP configuration updates failed
|
||||
// (if it's going to break, usually the code will be 1)
|
||||
Serial.print(F("DMP Initialization failed (code "));
|
||||
Serial.print(devStatus);
|
||||
Serial.println(F(")"));
|
||||
DEBUG_PRINT(F("DMP Initialization failed (code "));
|
||||
DEBUG_PRINT(devStatus);
|
||||
DEBUG_PRINTLN(F(")"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +155,7 @@ class MPU6050Driver : public Usermod {
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected() {
|
||||
//Serial.println("Connected to WiFi!");
|
||||
//DEBUG_PRINTLN("Connected to WiFi!");
|
||||
}
|
||||
|
||||
|
||||
@ -153,7 +164,7 @@ class MPU6050Driver : public Usermod {
|
||||
*/
|
||||
void loop() {
|
||||
// if programming failed, don't try to do anything
|
||||
if (!dmpReady) return;
|
||||
if (!enabled || !dmpReady) return;
|
||||
|
||||
// wait for MPU interrupt or extra packet(s) available
|
||||
if (!mpuInterrupt && fifoCount < packetSize) return;
|
||||
@ -169,7 +180,7 @@ class MPU6050Driver : public Usermod {
|
||||
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
|
||||
// reset so we can continue cleanly
|
||||
mpu.resetFIFO();
|
||||
Serial.println(F("FIFO overflow!"));
|
||||
DEBUG_PRINTLN(F("FIFO overflow!"));
|
||||
|
||||
// otherwise, check for DMP data ready interrupt (this should happen frequently)
|
||||
} else if (mpuIntStatus & 0x02) {
|
||||
@ -259,10 +270,23 @@ class MPU6050Driver : public Usermod {
|
||||
*/
|
||||
void readFromJsonState(JsonObject& root)
|
||||
{
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
//if (root["bri"] == 255) DEBUG_PRINTLN(F("Don't burn down your garage!"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||
*/
|
||||
void addToConfig(JsonObject& root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject("MPU6050_IMU");
|
||||
JsonArray pins = top.createNestedArray("pin");
|
||||
pins.add(HW_PIN_SCL);
|
||||
pins.add(HW_PIN_SDA);
|
||||
}
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
*/
|
||||
|
@ -25,6 +25,10 @@
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#define HW_PIN_CLOCKSPI 18
|
||||
#define HW_PIN_DATASPI 23
|
||||
#ifndef FLD_PIN_SCL
|
||||
#define FLD_PIN_SCL 22
|
||||
#endif
|
||||
@ -47,6 +51,10 @@
|
||||
#define FLD_PIN_RESET 26
|
||||
#endif
|
||||
#else
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#define HW_PIN_CLOCKSPI 14
|
||||
#define HW_PIN_DATASPI 13
|
||||
#ifndef FLD_PIN_SCL
|
||||
#define FLD_PIN_SCL 5
|
||||
#endif
|
||||
@ -172,80 +180,64 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
// network here
|
||||
void setup() {
|
||||
if (type == NONE || !enabled) return;
|
||||
|
||||
bool isHW;
|
||||
PinOwner po = PinOwner::UM_FourLineDisplay;
|
||||
if (type == SSD1306_SPI || type == SSD1306_SPI64) {
|
||||
PinManagerPinType pins[5] = { { ioPin[0], true }, { ioPin[1], true}, { ioPin[2], true }, { ioPin[3], true}, { ioPin[4], true }};
|
||||
if (!pinManager.allocateMultiplePins(pins, 5, PinOwner::UM_FourLineDisplay)) { type=NONE; return; }
|
||||
isHW = (ioPin[0]==HW_PIN_CLOCKSPI && ioPin[1]==HW_PIN_DATASPI);
|
||||
PinManagerPinType pins[5] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true }, { ioPin[3], true }, { ioPin[4], true }};
|
||||
if (!pinManager.allocateMultiplePins(pins, 5, po)) { type=NONE; return; }
|
||||
} else {
|
||||
PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true} };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::UM_FourLineDisplay)) { type=NONE; return; }
|
||||
isHW = (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA);
|
||||
PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true } };
|
||||
if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, po)) { type=NONE; return; }
|
||||
}
|
||||
|
||||
DEBUG_PRINTLN(F("Allocating display."));
|
||||
switch (type) {
|
||||
case SSD1306:
|
||||
#ifdef ESP8266
|
||||
if (!(ioPin[0]==5 && ioPin[1]==4))
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else
|
||||
#endif
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
lineHeight = 1;
|
||||
break;
|
||||
case SH1106:
|
||||
#ifdef ESP8266
|
||||
if (!(ioPin[0]==5 && ioPin[1]==4))
|
||||
u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else
|
||||
#endif
|
||||
u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
lineHeight = 2;
|
||||
break;
|
||||
case SSD1306_64:
|
||||
#ifdef ESP8266
|
||||
if (!(ioPin[0]==5 && ioPin[1]==4))
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else
|
||||
#endif
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
lineHeight = 2;
|
||||
break;
|
||||
case SSD1305:
|
||||
#ifdef ESP8266
|
||||
if (!(ioPin[0]==5 && ioPin[1]==4))
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else
|
||||
#endif
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
lineHeight = 1;
|
||||
break;
|
||||
case SSD1305_64:
|
||||
#ifdef ESP8266
|
||||
if (!(ioPin[0]==5 && ioPin[1]==4))
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else
|
||||
#endif
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
||||
else u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
||||
lineHeight = 2;
|
||||
break;
|
||||
case SSD1306_SPI:
|
||||
if (!(ioPin[0]==FLD_PIN_CLOCKSPI && ioPin[1]==FLD_PIN_DATASPI)) // if not overridden these sould be HW accellerated
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]);
|
||||
else
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset
|
||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]);
|
||||
else u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset
|
||||
lineHeight = 1;
|
||||
break;
|
||||
case SSD1306_SPI64:
|
||||
if (!(ioPin[0]==FLD_PIN_CLOCKSPI && ioPin[1]==FLD_PIN_DATASPI)) // if not overridden these sould be HW accellerated
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]);
|
||||
else
|
||||
u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset
|
||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]);
|
||||
else u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset
|
||||
lineHeight = 2;
|
||||
break;
|
||||
default:
|
||||
u8x8 = nullptr;
|
||||
}
|
||||
|
||||
if (nullptr == u8x8) {
|
||||
DEBUG_PRINTLN(F("Display init failed."));
|
||||
for (byte i=0; i<5 && ioPin[i]>=0; i++) pinManager.deallocatePin(ioPin[i], PinOwner::UM_FourLineDisplay);
|
||||
pinManager.deallocateMultiplePins((const uint8_t*)ioPin, (type == SSD1306_SPI || type == SSD1306_SPI64) ? 5 : 2, po);
|
||||
type = NONE;
|
||||
return;
|
||||
}
|
||||
@ -714,10 +706,10 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
for (byte i=0; i<5; i++) if (ioPin[i] != newPin[i]) { pinsChanged = true; break; }
|
||||
if (pinsChanged || type!=newType) {
|
||||
if (type != NONE) delete u8x8;
|
||||
for (byte i=0; i<5; i++) {
|
||||
if (ioPin[i]>=0) pinManager.deallocatePin(ioPin[i], PinOwner::UM_FourLineDisplay);
|
||||
ioPin[i] = newPin[i];
|
||||
}
|
||||
PinOwner po = PinOwner::UM_FourLineDisplay;
|
||||
if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
pinManager.deallocateMultiplePins((const uint8_t *)ioPin, (type == SSD1306_SPI || type == SSD1306_SPI64) ? 5 : 2, po);
|
||||
for (byte i=0; i<5; i++) ioPin[i] = newPin[i];
|
||||
if (ioPin[0]<0 || ioPin[1]<0) { // data & clock must be > -1
|
||||
type = NONE;
|
||||
return true;
|
||||
|
50
wled00/FX.h
50
wled00/FX.h
@ -932,7 +932,7 @@ class WS2812FX {
|
||||
const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Solid",
|
||||
"Blink@;!;!",
|
||||
"Breathe@Speed;,!;!",
|
||||
"Breathe@!,;,!;!",
|
||||
"Wipe",
|
||||
"Wipe Random",
|
||||
"Random Colors",
|
||||
@ -940,13 +940,12 @@ const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Dynamic",
|
||||
"Colorloop",
|
||||
"Rainbow",
|
||||
"Scan@!,# of dots;,!,?;!",
|
||||
"Scan Dual@!,# of dots;,!,?;!",
|
||||
"Fade",
|
||||
"Theater",
|
||||
"Scan@!,# of dots;,!,;!",
|
||||
"Scan Dual@!,# of dots;,!,;!",
|
||||
"Fade","Theater",
|
||||
"Theater Rainbow",
|
||||
"Running",
|
||||
"Saw",
|
||||
"Running@!,Wave width;!,!,;!",
|
||||
"Saw@!,Width;Fx,Bg,;!",
|
||||
"Twinkle",
|
||||
"Dissolve",
|
||||
"Dissolve Rnd",
|
||||
@ -967,24 +966,24 @@ const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Colorful",
|
||||
"Traffic Light",
|
||||
"Sweep Random",
|
||||
"Running 2",
|
||||
"Running 2@!,Width;;!",
|
||||
"Aurora",
|
||||
"Stream",
|
||||
"Scanner",
|
||||
"Lighthouse",
|
||||
"Fireworks",
|
||||
"Rain",
|
||||
"Tetrix@Speed,Width;Fx,BG,;!",
|
||||
"Tetrix@!,Width;Fx,Bg,;!",
|
||||
"Fire Flicker",
|
||||
"Gradient",
|
||||
"Loading",
|
||||
"Police",
|
||||
"Police All",
|
||||
"Two Dots",
|
||||
"Two Areas",
|
||||
"Police@!,Width;;",
|
||||
"Police All@!,Width;;",
|
||||
"Two Dots@!,Dot size;,,Bg;!",
|
||||
"Two Areas@!,Size;,,Bg;!",
|
||||
"Running Dual",
|
||||
"Halloween",
|
||||
"Tri Chase",
|
||||
"Tri Chase@!,Size;;",
|
||||
"Tri Wipe",
|
||||
"Tri Fade",
|
||||
"Lightning",
|
||||
@ -994,9 +993,9 @@ const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Stream 2",
|
||||
"Oscillate",
|
||||
"Pride 2015",
|
||||
"Juggle",
|
||||
"Palette",
|
||||
"Fire 2012",
|
||||
"Juggle@!,Trail;Fx,Bg,;!",
|
||||
"Palette@!,;;!",
|
||||
"Fire 2012@Spark rate,Decay;!;!",
|
||||
"Colorwaves",
|
||||
"Bpm",
|
||||
"Fill Noise",
|
||||
@ -1013,15 +1012,15 @@ const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Twinklefox",
|
||||
"Twinklecat",
|
||||
"Halloween Eyes",
|
||||
"Solid Pattern",
|
||||
"Solid Pattern Tri",
|
||||
"Solid Pattern@Fg size,Bg size;Fg,Bg,;",
|
||||
"Solid Pattern Tri@,Size;;",
|
||||
"Spots",
|
||||
"Spots Fade",
|
||||
"Glitter",
|
||||
"Candle",
|
||||
"Candle@Flicker rate,Flicker intensity;Fx,Bg,;",
|
||||
"Fireworks Starburst",
|
||||
"Fireworks 1D@Gravity,Firing side;;!",
|
||||
"Bouncing Balls",
|
||||
"Bouncing Balls@Gravity,# of balls;Fx,Bg,;!",
|
||||
"Sinelon",
|
||||
"Sinelon Dual",
|
||||
"Sinelon Rainbow",
|
||||
@ -1032,16 +1031,15 @@ const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Ripple Rainbow",
|
||||
"Heartbeat",
|
||||
"Pacifica",
|
||||
"Candle Multi",
|
||||
"Candle Multi@Flicker rate,Flicker intensity;Fx,Bg,;",
|
||||
"Solid Glitter",
|
||||
"Sunrise",
|
||||
"Phased",
|
||||
"Twinkleup@Speed,Intensity,Min;,!;!",
|
||||
"Sunrise@Time [min],;!;",
|
||||
"Phased","Twinkleup@Speed,Intensity;,!;!",
|
||||
"Noise Pal",
|
||||
"Sine",
|
||||
"Phased Noise",
|
||||
"Flow",
|
||||
"Chunchun",
|
||||
"Chunchun@!,Gap size;Fg,Bg,;!",
|
||||
"Dancing Shadows",
|
||||
"Washing Machine",
|
||||
"Candy Cane",
|
||||
|
@ -134,7 +134,8 @@ bool deserializeState(JsonObject root, byte callMode = CALL_MODE_DIRECT_CHANGE,
|
||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
|
||||
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
||||
void serializeInfo(JsonObject root);
|
||||
void serializeSRNames(JsonArray arr, const char *qstring);
|
||||
void serializeModeNames(JsonArray arr, const char *qstring);
|
||||
void serializeModeData(JsonObject root);
|
||||
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
||||
void serveJson(AsyncWebServerRequest* request);
|
||||
bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient = 0);
|
||||
|
@ -813,15 +813,50 @@ void serializeNodes(JsonObject root)
|
||||
}
|
||||
}
|
||||
|
||||
// deserializes mode names string into JsonArray
|
||||
// also removes WLED-SR extensions (@...) from deserialised names
|
||||
void deserializeModeNames(JsonArray arr, const char *qstring) {
|
||||
void serializeModeData(JsonObject root)
|
||||
{
|
||||
JsonArray fxdata = root.createNestedArray("fxdata");
|
||||
String lineBuffer;
|
||||
bool insideQuotes = false;
|
||||
char singleJsonSymbol;
|
||||
size_t len = strlen_P(JSON_mode_names);
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(qstring); i++) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
if (singleJsonSymbol == '\0') break;
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
break;
|
||||
case ']':
|
||||
case ',':
|
||||
if (lineBuffer.length() > 0) {
|
||||
uint8_t endPos = lineBuffer.indexOf('@');
|
||||
if (endPos>0) fxdata.add(lineBuffer.substring(endPos));
|
||||
else fxdata.add("");
|
||||
lineBuffer.clear();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!insideQuotes) break;
|
||||
lineBuffer += singleJsonSymbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deserializes mode names string into JsonArray
|
||||
// also removes WLED-SR extensions (@...) from deserialised names
|
||||
void serializeModeNames(JsonArray arr, const char *qstring) {
|
||||
String lineBuffer;
|
||||
bool insideQuotes = false;
|
||||
char singleJsonSymbol;
|
||||
size_t len = strlen_P(qstring);
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(qstring + i);
|
||||
if (singleJsonSymbol == '\0') break;
|
||||
switch (singleJsonSymbol) {
|
||||
@ -854,9 +889,10 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
size_t len = strlen_P(src);
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(src); i++) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(src + i);
|
||||
if (singleJsonSymbol == '\0') break;
|
||||
switch (singleJsonSymbol) {
|
||||
@ -889,6 +925,7 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
else if (url.indexOf("si") > 0) subJson = 3;
|
||||
else if (url.indexOf("nodes") > 0) subJson = 4;
|
||||
else if (url.indexOf("palx") > 0) subJson = 5;
|
||||
else if (url.indexOf("fxda") > 0) subJson = 6;
|
||||
else if (url.indexOf("live") > 0) {
|
||||
serveLiveLeds(request);
|
||||
return;
|
||||
@ -936,6 +973,8 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
serializeNodes(lDoc); break;
|
||||
case 5: //palettes
|
||||
serializePalettes(lDoc, request); break;
|
||||
case 6: // FX helper data
|
||||
serializeModeData(lDoc); break;
|
||||
default: //all
|
||||
JsonObject state = lDoc.createNestedObject("state");
|
||||
serializeState(state);
|
||||
@ -945,7 +984,7 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
{
|
||||
//lDoc[F("effects")] = serialized((const __FlashStringHelper*)JSON_mode_names);
|
||||
JsonArray effects = lDoc.createNestedArray(F("effects"));
|
||||
deserializeModeNames(effects, JSON_mode_names); // remove WLED-SR extensions from effect names
|
||||
serializeModeNames(effects, JSON_mode_names); // remove WLED-SR extensions from effect names
|
||||
lDoc[F("palettes")] = serialized((const __FlashStringHelper*)JSON_palette_names);
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,48 @@ bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag)
|
||||
return true;
|
||||
}
|
||||
|
||||
// support function for deallocating multiple pins
|
||||
bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag)
|
||||
{
|
||||
bool shouldFail = false;
|
||||
DEBUG_PRINTLN(F("MULTIPIN DEALLOC"));
|
||||
// first verify the pins are OK and allocated by selected owner
|
||||
for (int i = 0; i < arrayElementCount; i++) {
|
||||
byte gpio = pinArray[i];
|
||||
if (gpio == 0xFF) {
|
||||
// explicit support for io -1 as a no-op (no allocation of pin),
|
||||
// as this can greatly simplify configuration arrays
|
||||
continue;
|
||||
}
|
||||
if (isPinAllocated(gpio, tag)) {
|
||||
// if the current pin is allocated by selected owner it is possible to release it
|
||||
continue;
|
||||
}
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN DEALLOC: IO "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" allocated by "));
|
||||
DebugPrintOwnerTag(ownerTag[gpio]);
|
||||
DEBUG_PRINT(F(", but attempted de-allocation by "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
#endif
|
||||
shouldFail = true;
|
||||
}
|
||||
if (shouldFail) {
|
||||
return false; // no pins deallocated
|
||||
}
|
||||
if (tag==PinOwner::HW_I2C) {
|
||||
if (i2cAllocCount && --i2cAllocCount>0) {
|
||||
// no deallocation done until last owner releases pins
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < arrayElementCount; i++) {
|
||||
deallocatePin(pinArray[i], tag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag)
|
||||
{
|
||||
bool shouldFail = false;
|
||||
@ -58,7 +100,10 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
#endif
|
||||
shouldFail = true;
|
||||
}
|
||||
if (isPinAllocated(gpio)) {
|
||||
if (tag==PinOwner::HW_I2C && isPinAllocated(gpio, tag)) {
|
||||
// allow multiple "allocations" of HW I2C bus pins
|
||||
continue;
|
||||
} else if (isPinAllocated(gpio)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: FAIL: IO "));
|
||||
DEBUG_PRINT(gpio);
|
||||
@ -73,6 +118,8 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tag==PinOwner::HW_I2C) i2cAllocCount++;
|
||||
|
||||
// all pins are available .. track each one
|
||||
for (int i = 0; i < arrayElementCount; i++) {
|
||||
byte gpio = mptArray[i].pin;
|
||||
@ -91,7 +138,8 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
|
||||
bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
|
||||
{
|
||||
if (!isPinOk(gpio, output)) return false;
|
||||
// HW I2C pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair
|
||||
if (!isPinOk(gpio, output) || tag==PinOwner::HW_I2C) return false;
|
||||
if (isPinAllocated(gpio)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Pin "));
|
||||
|
@ -21,7 +21,7 @@ typedef struct PinManagerPinType {
|
||||
* 40 bytes on ESP32
|
||||
*/
|
||||
enum struct PinOwner : uint8_t {
|
||||
None = 0, // default == legacy == unspecified owner
|
||||
None = 0, // default == legacy == unspecified owner
|
||||
// High bit is set for all built-in pin owners
|
||||
Ethernet = 0x81,
|
||||
BusDigital = 0x82,
|
||||
@ -33,26 +33,27 @@ enum struct PinOwner : uint8_t {
|
||||
SPI_RAM = 0x88, // 'SpiR' == SPI RAM
|
||||
DebugOut = 0x89, // 'Dbg' == debug output always IO1
|
||||
DMX = 0x8A, // 'DMX' == hard-coded to IO2
|
||||
HW_I2C = 0x8B, // 'I2C' == hardware I2C pins (4&5 on ESP8266, 21&22 on ESP32)
|
||||
// Use UserMod IDs from const.h here
|
||||
UM_Unspecified = USERMOD_ID_UNSPECIFIED, // 0x01
|
||||
UM_Example = USERMOD_ID_EXAMPLE, // 0x02 // Usermod "usermod_v2_example.h"
|
||||
UM_Temperature = USERMOD_ID_TEMPERATURE, // 0x03 // Usermod "usermod_temperature.h"
|
||||
// #define USERMOD_ID_FIXNETSERVICES // 0x04 // Usermod "usermod_Fix_unreachable_netservices.h" -- Does not allocate pins
|
||||
UM_PIR = USERMOD_ID_PIRSWITCH, // 0x05 // Usermod "usermod_PIR_sensor_switch.h"
|
||||
// #define USERMOD_ID_IMU // 0x06 // Usermod "usermod_mpu6050_imu.h" -- Uses "standard" I2C pins ... TODO -- enable shared I2C bus use
|
||||
UM_FourLineDisplay = USERMOD_ID_FOUR_LINE_DISP, // 0x07 // Usermod "usermod_v2_four_line_display.h
|
||||
// #define USERMOD_ID_IMU // 0x06 // Usermod "usermod_mpu6050_imu.h" -- Uses "standard" HW_I2C pins
|
||||
UM_FourLineDisplay = USERMOD_ID_FOUR_LINE_DISP, // 0x07 // Usermod "usermod_v2_four_line_display.h -- May use "standard" HW_I2C pins
|
||||
UM_RotaryEncoderUI = USERMOD_ID_ROTARY_ENC_UI, // 0x08 // Usermod "usermod_v2_rotary_encoder_ui.h"
|
||||
// #define USERMOD_ID_AUTO_SAVE // 0x09 // Usermod "usermod_v2_auto_save.h" -- Does not allocate pins
|
||||
// #define USERMOD_ID_DHT // 0x0A // Usermod "usermod_dht.h" -- Statically allocates pins, not compatible with pinManager?
|
||||
// #define USERMOD_ID_MODE_SORT // 0x0B // Usermod "usermod_v2_mode_sort.h" -- Does not allocate pins
|
||||
// #define USERMOD_ID_VL53L0X // 0x0C // Usermod "usermod_vl53l0x_gestures.h" -- Uses "standard" I2C pins ... TODO -- enable shared I2C bus use
|
||||
// #define USERMOD_ID_VL53L0X // 0x0C // Usermod "usermod_vl53l0x_gestures.h" -- Uses "standard" HW_I2C pins
|
||||
UM_MultiRelay = USERMOD_ID_MULTI_RELAY, // 0x0D // Usermod "usermod_multi_relay.h"
|
||||
UM_AnimatedStaircase = USERMOD_ID_ANIMATED_STAIRCASE, // 0x0E // Usermod "Animated_Staircase.h"
|
||||
// #define USERMOD_ID_RTC // 0x0F // Usermod "usermod_rtc.h" -- Uses "standard" I2C pins ... TODO -- enable shared I2C bus use
|
||||
// #define USERMOD_ID_RTC // 0x0F // Usermod "usermod_rtc.h" -- Uses "standard" HW_I2C pins
|
||||
// #define USERMOD_ID_ELEKSTUBE_IPS // 0x10 // Usermod "usermod_elekstube_ips.h" -- Uses quite a few pins ... see Hardware.h and User_Setup.h
|
||||
// #define USERMOD_ID_SN_PHOTORESISTOR // 0x11 // Usermod "usermod_sn_photoresistor.h" -- Uses hard-coded pin (PHOTORESISTOR_PIN == A0), but could be easily updated to use pinManager
|
||||
UM_RGBRotaryEncoder = USERMOD_RGB_ROTARY_ENCODER, // 0x16 // Usermod "rgb-rotary-encoder.h"
|
||||
UM_QuinLEDAnPenta = USERMOD_ID_QUINLED_AN_PENTA, // 0x17 // Usermod "quinled-an-penta.h"
|
||||
UM_RGBRotaryEncoder = USERMOD_RGB_ROTARY_ENCODER, // 0x16 // Usermod "rgb-rotary-encoder.h"
|
||||
UM_QuinLEDAnPenta = USERMOD_ID_QUINLED_AN_PENTA // 0x17 // Usermod "quinled-an-penta.h"
|
||||
};
|
||||
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");
|
||||
|
||||
@ -66,10 +67,13 @@ class PinManagerClass {
|
||||
uint8_t ledcAlloc[2] = {0x00, 0x00}; //16 LEDC channels
|
||||
PinOwner ownerTag[40] = { PinOwner::None };
|
||||
#endif
|
||||
uint8_t i2cAllocCount = 0; // allow multiple allocation of I2C bus pins but keep track of allocations
|
||||
|
||||
public:
|
||||
// De-allocates a single pin
|
||||
bool deallocatePin(byte gpio, PinOwner tag);
|
||||
// De-allocates multiple pins but only if all can be deallocated (PinOwner has to be specified)
|
||||
bool deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag);
|
||||
// Allocates a single pin, with an owner tag.
|
||||
// De-allocation requires the same owner tag (or override)
|
||||
bool allocatePin(byte gpio, bool output, PinOwner tag);
|
||||
@ -84,7 +88,7 @@ class PinManagerClass {
|
||||
#endif
|
||||
inline bool allocatePin(byte gpio, bool output = true) { return allocatePin(gpio, output, PinOwner::None); }
|
||||
#if !defined(ESP8266) // ESP8266 compiler doesn't understand deprecated attribute
|
||||
[[deprecated("Replaced by three-parameter deallocatePin(gpio, output, ownerTag), for improved debugging")]]
|
||||
[[deprecated("Replaced by two-parameter deallocatePin(gpio, ownerTag), for improved debugging")]]
|
||||
#endif
|
||||
inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); }
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2111171
|
||||
#define VERSION 2111191
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
|
Loading…
Reference in New Issue
Block a user