Enhanced usermods. (#2522)
This commit is contained in:
parent
6e0e5c102e
commit
0a5a0bef48
@ -9,16 +9,17 @@ The LED strip is switched [using a relay](https://github.com/Aircoookie/WLED/wik
|
||||
|
||||
## Webinterface
|
||||
|
||||
The info page in the web interface shows the remaining time of the off timer.
|
||||
The info page in the web interface shows the remaining time of the off timer. Usermod can also be temporarily disbled/enabled from the info page by clicking PIR button.
|
||||
|
||||
## Sensor connection
|
||||
|
||||
My setup uses an HC-SR501 sensor, a HC-SR505 should also work.
|
||||
My setup uses an HC-SR501 or HC-SR602 sensor, a HC-SR505 should also work.
|
||||
|
||||
The usermod uses GPIO13 (D1 mini pin D7) by default for the sensor signal but can be changed in the Usermod settings page.
|
||||
[This example page](http://www.esp8266learning.com/wemos-mini-pir-sensor-example.php) describes how to connect the sensor.
|
||||
|
||||
Use the potentiometers on the sensor to set the time-delay to the minimum and the sensitivity to about half, or slightly above.
|
||||
You can also use usermod's off timer instead of sensor's. In such case rotate the potentiometer to its shortest time possible (or use SR602 which lacks such potentiometer).
|
||||
|
||||
## Usermod installation
|
||||
|
||||
@ -59,6 +60,8 @@ void registerUsermods()
|
||||
}
|
||||
```
|
||||
|
||||
**NOTE:** Usermod has been included in master branch of WLED so it can be compiled in directly just by defining `-D USERMOD_PIRSWITCH` and optionaly `-D PIR_SENSOR_PIN=16` to override default pin.
|
||||
|
||||
## API to enable/disable the PIR sensor from outside. For example from another usermod.
|
||||
|
||||
To query or change the PIR sensor state the methods `bool PIRsensorEnabled()` and `void EnablePIRsensor(bool enable)` are available.
|
||||
@ -95,8 +98,27 @@ class MyUsermod : public Usermod {
|
||||
};
|
||||
```
|
||||
|
||||
Have fun - @gegu
|
||||
### Configuration options
|
||||
|
||||
Usermod can be configured in Usermods settings page.
|
||||
|
||||
* `PIRenabled` - enable/disable usermod
|
||||
* `pin` - dynamically change GPIO pin where PIR sensor is attached to ESP
|
||||
* `PIRoffSec` - number of seconds after PIR sensor deactivates when usermod triggers Off preset (or turns WLED off)
|
||||
* `on-preset` - preset triggered when PIR activates (if this is 0 it will just turn WLED on)
|
||||
* `off-preset` - preset triggered when PIR deactivates (if this is 0 it will just turn WLED off)
|
||||
* `nighttime-only` - enable triggering only between sunset and sunrise (you will need to set up _NTP_, _Lat_ & _Lon_ in Time & Macro settings)
|
||||
* `mqtt-only` - only send MQTT messages, do not interact with WLED
|
||||
* `off-only` - only trigger presets or turn WLED on/off in WLED is not already on (displaying effect)
|
||||
* `notifications` - enable or disable sending notifications to other WLED instances using Sync button
|
||||
|
||||
|
||||
Have fun - @gegu & @blazoncek
|
||||
|
||||
## Change log
|
||||
2021-04
|
||||
* Adaptation for runtime configuration.
|
||||
* Adaptation for runtime configuration.
|
||||
|
||||
2021-11
|
||||
* Added information about dynamic configuration options
|
||||
* Added option to temporary enable/disble usermod from WLED UI (Info dialog)
|
@ -55,33 +55,29 @@ public:
|
||||
bool PIRsensorEnabled() { return enabled; }
|
||||
|
||||
private:
|
||||
// PIR sensor pin
|
||||
int8_t PIRsensorPin = PIR_SENSOR_PIN;
|
||||
// notification mode for colorUpdated()
|
||||
const byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // CALL_MODE_DIRECT_CHANGE
|
||||
// delay before switch off after the sensor state goes LOW
|
||||
uint32_t m_switchOffDelay = 600000; // 10min
|
||||
// off timer start time
|
||||
uint32_t m_offTimerStart = 0;
|
||||
// current PIR sensor pin state
|
||||
byte sensorPinState = LOW;
|
||||
// PIR sensor enabled
|
||||
bool enabled = true;
|
||||
// status of initialisation
|
||||
bool initDone = false;
|
||||
// on and off presets
|
||||
uint8_t m_onPreset = 0;
|
||||
uint8_t m_offPreset = 0;
|
||||
// flag to indicate that PIR sensor should activate WLED during nighttime only
|
||||
bool m_nightTimeOnly = false;
|
||||
// flag to send MQTT message only (assuming it is enabled)
|
||||
bool m_mqttOnly = false;
|
||||
// flag to enable triggering only if WLED is initially off (LEDs are not on, preventing running effect being overwritten by PIR)
|
||||
bool m_offOnly = false;
|
||||
bool PIRtriggered = false;
|
||||
|
||||
byte prevPreset = 0;
|
||||
byte prevPlaylist = 0;
|
||||
bool savedState = false;
|
||||
|
||||
uint32_t offTimerStart = 0; // off timer start time
|
||||
byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // notification mode for colorUpdated(): CALL_MODE_NO_NOTIFY or CALL_MODE_DIRECT_CHANGE
|
||||
byte sensorPinState = LOW; // current PIR sensor pin state
|
||||
bool initDone = false; // status of initialization
|
||||
bool PIRtriggered = false;
|
||||
unsigned long lastLoop = 0;
|
||||
|
||||
// configurable parameters
|
||||
bool enabled = true; // PIR sensor enabled
|
||||
int8_t PIRsensorPin = PIR_SENSOR_PIN; // PIR sensor pin
|
||||
uint32_t m_switchOffDelay = 600000; // delay before switch off after the sensor state goes LOW (10min)
|
||||
uint8_t m_onPreset = 0; // on preset
|
||||
uint8_t m_offPreset = 0; // off preset
|
||||
bool m_nightTimeOnly = false; // flag to indicate that PIR sensor should activate WLED during nighttime only
|
||||
bool m_mqttOnly = false; // flag to send MQTT message only (assuming it is enabled)
|
||||
// flag to enable triggering only if WLED is initially off (LEDs are not on, preventing running effect being overwritten by PIR)
|
||||
bool m_offOnly = false;
|
||||
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
static const char _name[];
|
||||
static const char _switchOffDelay[];
|
||||
@ -91,30 +87,30 @@ private:
|
||||
static const char _nightTime[];
|
||||
static const char _mqttOnly[];
|
||||
static const char _offOnly[];
|
||||
static const char _notify[];
|
||||
|
||||
/**
|
||||
* check if it is daytime
|
||||
* if sunrise/sunset is not defined (no NTP or lat/lon) default to nighttime
|
||||
*/
|
||||
bool isDayTime() {
|
||||
bool isDayTime = false;
|
||||
updateLocalTime();
|
||||
uint8_t hr = hour(localTime);
|
||||
uint8_t mi = minute(localTime);
|
||||
|
||||
if (sunrise && sunset) {
|
||||
if (hour(sunrise)<hr && hour(sunset)>hr) {
|
||||
isDayTime = true;
|
||||
return true;
|
||||
} else {
|
||||
if (hour(sunrise)==hr && minute(sunrise)<mi) {
|
||||
isDayTime = true;
|
||||
return true;
|
||||
}
|
||||
if (hour(sunset)==hr && minute(sunset)>mi) {
|
||||
isDayTime = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isDayTime;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,17 +120,47 @@ private:
|
||||
{
|
||||
if (m_offOnly && bri && (switchOn || (!PIRtriggered && !switchOn))) return;
|
||||
PIRtriggered = switchOn;
|
||||
if (switchOn && m_onPreset) {
|
||||
applyPreset(m_onPreset);
|
||||
} else if (!switchOn && m_offPreset) {
|
||||
applyPreset(m_offPreset);
|
||||
} else if (switchOn && bri == 0) {
|
||||
bri = briLast;
|
||||
colorUpdated(NotifyUpdateMode);
|
||||
} else if (!switchOn && bri != 0) {
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
colorUpdated(NotifyUpdateMode);
|
||||
if (switchOn) {
|
||||
if (m_onPreset) {
|
||||
if (currentPlaylist>0) prevPlaylist = currentPlaylist;
|
||||
else if (currentPreset>0) prevPreset = currentPreset;
|
||||
else {
|
||||
saveTemporaryPreset();
|
||||
savedState = true;
|
||||
prevPlaylist = 0;
|
||||
prevPreset = 0;
|
||||
}
|
||||
applyPreset(m_onPreset, NotifyUpdateMode);
|
||||
return;
|
||||
}
|
||||
// preset not assigned
|
||||
if (bri == 0) {
|
||||
bri = briLast;
|
||||
colorUpdated(NotifyUpdateMode);
|
||||
}
|
||||
} else {
|
||||
if (m_offPreset) {
|
||||
applyPreset(m_offPreset, NotifyUpdateMode);
|
||||
return;
|
||||
} else if (prevPlaylist) {
|
||||
applyPreset(prevPlaylist, NotifyUpdateMode);
|
||||
prevPlaylist = 0;
|
||||
return;
|
||||
} else if (prevPreset) {
|
||||
applyPreset(prevPreset, NotifyUpdateMode);
|
||||
prevPreset = 0;
|
||||
return;
|
||||
} else if (savedState) {
|
||||
applyTemporaryPreset();
|
||||
savedState = false;
|
||||
return;
|
||||
}
|
||||
// preset not assigned
|
||||
if (bri != 0) {
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
colorUpdated(NotifyUpdateMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,12 +186,12 @@ private:
|
||||
sensorPinState = pinState; // change previous state
|
||||
|
||||
if (sensorPinState == HIGH) {
|
||||
m_offTimerStart = 0;
|
||||
offTimerStart = 0;
|
||||
if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()))) switchStrip(true);
|
||||
publishMqtt("on");
|
||||
} else /*if (bri != 0)*/ {
|
||||
// start switch off timer
|
||||
m_offTimerStart = millis();
|
||||
offTimerStart = millis();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -177,14 +203,14 @@ private:
|
||||
*/
|
||||
bool handleOffTimer()
|
||||
{
|
||||
if (m_offTimerStart > 0 && millis() - m_offTimerStart > m_switchOffDelay)
|
||||
if (offTimerStart > 0 && millis() - offTimerStart > m_switchOffDelay)
|
||||
{
|
||||
if (enabled == true)
|
||||
{
|
||||
if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()))) switchStrip(false);
|
||||
publishMqtt("off");
|
||||
}
|
||||
m_offTimerStart = 0;
|
||||
offTimerStart = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -248,15 +274,25 @@ public:
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
// off timer
|
||||
String uiDomString = F("PIR <i class=\"icons\"></i>");
|
||||
JsonArray infoArr = user.createNestedArray(uiDomString); // timer value
|
||||
if (m_offTimerStart > 0)
|
||||
String uiDomString = F("<button class=\"btn\" onclick=\"requestJson({");
|
||||
uiDomString += FPSTR(_name);
|
||||
uiDomString += F(":{");
|
||||
uiDomString += FPSTR(_enabled);
|
||||
if (enabled) {
|
||||
uiDomString += F(":false}});\">");
|
||||
uiDomString += F("PIR <i class=\"icons\"></i>");
|
||||
} else {
|
||||
uiDomString += F(":true}});\">");
|
||||
uiDomString += F("PIR <i class=\"icons\"></i>");
|
||||
}
|
||||
uiDomString += F("</button>");
|
||||
JsonArray infoArr = user.createNestedArray(uiDomString); // timer value
|
||||
|
||||
if (enabled) {
|
||||
if (offTimerStart > 0)
|
||||
{
|
||||
uiDomString = "";
|
||||
unsigned int offSeconds = (m_switchOffDelay - (millis() - m_offTimerStart)) / 1000;
|
||||
unsigned int offSeconds = (m_switchOffDelay - (millis() - offTimerStart)) / 1000;
|
||||
if (offSeconds >= 3600)
|
||||
{
|
||||
uiDomString += (offSeconds / 3600);
|
||||
@ -282,8 +318,6 @@ public:
|
||||
infoArr.add(sensorPinState ? F("sensor on") : F("inactive"));
|
||||
}
|
||||
} else {
|
||||
String uiDomString = F("PIR sensor");
|
||||
JsonArray infoArr = user.createNestedArray(uiDomString);
|
||||
infoArr.add(F("disabled"));
|
||||
}
|
||||
}
|
||||
@ -302,11 +336,18 @@ public:
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
/*
|
||||
|
||||
void readFromJsonState(JsonObject &root)
|
||||
{
|
||||
if (!initDone) return; // prevent crash on boot applyPreset()
|
||||
JsonObject usermod = root[FPSTR(_name)];
|
||||
if (!usermod.isNull()) {
|
||||
if (usermod[FPSTR(_enabled)].is<bool>()) {
|
||||
enabled = usermod[FPSTR(_enabled)].as<bool>();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* provide the changeable values
|
||||
@ -314,14 +355,15 @@ public:
|
||||
void addToConfig(JsonObject &root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||
top[FPSTR(_enabled)] = enabled;
|
||||
top[FPSTR(_enabled)] = enabled;
|
||||
top[FPSTR(_switchOffDelay)] = m_switchOffDelay / 1000;
|
||||
top["pin"] = PIRsensorPin;
|
||||
top[FPSTR(_onPreset)] = m_onPreset;
|
||||
top[FPSTR(_offPreset)] = m_offPreset;
|
||||
top[FPSTR(_nightTime)] = m_nightTimeOnly;
|
||||
top[FPSTR(_mqttOnly)] = m_mqttOnly;
|
||||
top[FPSTR(_offOnly)] = m_offOnly;
|
||||
top["pin"] = PIRsensorPin;
|
||||
top[FPSTR(_onPreset)] = m_onPreset;
|
||||
top[FPSTR(_offPreset)] = m_offPreset;
|
||||
top[FPSTR(_nightTime)] = m_nightTimeOnly;
|
||||
top[FPSTR(_mqttOnly)] = m_mqttOnly;
|
||||
top[FPSTR(_offOnly)] = m_offOnly;
|
||||
top[FPSTR(_notify)] = (NotifyUpdateMode != CALL_MODE_NO_NOTIFY);
|
||||
DEBUG_PRINTLN(F("PIR config saved."));
|
||||
}
|
||||
|
||||
@ -336,9 +378,9 @@ public:
|
||||
bool oldEnabled = enabled;
|
||||
int8_t oldPin = PIRsensorPin;
|
||||
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
JsonObject top = root[FPSTR(_name)];
|
||||
if (top.isNull()) {
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
||||
return false;
|
||||
}
|
||||
@ -351,7 +393,6 @@ public:
|
||||
|
||||
m_onPreset = top[FPSTR(_onPreset)] | m_onPreset;
|
||||
m_onPreset = max(0,min(250,(int)m_onPreset));
|
||||
|
||||
m_offPreset = top[FPSTR(_offPreset)] | m_offPreset;
|
||||
m_offPreset = max(0,min(250,(int)m_offPreset));
|
||||
|
||||
@ -359,7 +400,8 @@ public:
|
||||
m_mqttOnly = top[FPSTR(_mqttOnly)] | m_mqttOnly;
|
||||
m_offOnly = top[FPSTR(_offOnly)] | m_offOnly;
|
||||
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
NotifyUpdateMode = top[FPSTR(_notify)] ? CALL_MODE_DIRECT_CHANGE : CALL_MODE_NO_NOTIFY;
|
||||
|
||||
if (!initDone) {
|
||||
// reading config prior to setup()
|
||||
DEBUG_PRINTLN(F(" config loaded."));
|
||||
@ -385,7 +427,7 @@ public:
|
||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||
}
|
||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
||||
return !top[FPSTR(_offOnly)].isNull();
|
||||
return !top[FPSTR(_notify)].isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -407,3 +449,4 @@ const char PIRsensorSwitch::_offPreset[] PROGMEM = "off-preset";
|
||||
const char PIRsensorSwitch::_nightTime[] PROGMEM = "nighttime-only";
|
||||
const char PIRsensorSwitch::_mqttOnly[] PROGMEM = "mqtt-only";
|
||||
const char PIRsensorSwitch::_offOnly[] PROGMEM = "off-only";
|
||||
const char PIRsensorSwitch::_notify[] PROGMEM = "notifications";
|
||||
|
@ -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);
|
||||
@ -22,12 +32,26 @@ class RTCUsermod : public Usermod {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (strip.isUpdating()) return;
|
||||
if (!disabled && toki.isTick()) {
|
||||
time_t t = toki.second();
|
||||
if (t != RTC.get()) RTC.set(t); //set RTC to NTP/UI-provided value
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
@ -37,12 +37,12 @@ class UsermodTemperature : public Usermod {
|
||||
// used to determine when we can read the sensors temperature
|
||||
// we have to wait at least 93.75 ms after requestTemperatures() is called
|
||||
unsigned long lastTemperaturesRequest;
|
||||
float temperature = -100; // default to -100, DS18B20 only goes down to -50C
|
||||
float temperature;
|
||||
// indicates requestTemperatures has been called but the sensor measurement is not complete
|
||||
bool waitingForConversion = false;
|
||||
// flag set at startup if DS18B20 sensor not found, avoids trying to keep getting
|
||||
// temperature if flashed to a board without a sensor attached
|
||||
bool sensorFound = false;
|
||||
byte sensorFound;
|
||||
|
||||
bool enabled = true;
|
||||
|
||||
@ -54,27 +54,47 @@ class UsermodTemperature : public Usermod {
|
||||
|
||||
//Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013
|
||||
float readDallas() {
|
||||
byte i;
|
||||
byte data[2];
|
||||
byte data[9];
|
||||
int16_t result; // raw data from sensor
|
||||
if (!oneWire->reset()) return -127.0f; // send reset command and fail fast
|
||||
oneWire->skip(); // skip ROM
|
||||
oneWire->write(0xBE); // read (temperature) from EEPROM
|
||||
for (i=0; i < 2; i++) data[i] = oneWire->read(); // first 2 bytes contain temperature
|
||||
for (i=2; i < 8; i++) oneWire->read(); // read unused bytes
|
||||
result = (data[1]<<4) | (data[0]>>4); // we only need whole part, we will add fraction when returning
|
||||
if (data[1]&0x80) result |= 0xFF00; // fix negative value
|
||||
oneWire->reset();
|
||||
oneWire->skip(); // skip ROM
|
||||
oneWire->write(0x44,parasite); // request new temperature reading (without parasite power)
|
||||
return (float)result + ((data[0]&0x0008) ? 0.5f : 0.0f);
|
||||
float retVal = -127.0f;
|
||||
if (oneWire->reset()) { // if reset() fails there are no OneWire devices
|
||||
oneWire->skip(); // skip ROM
|
||||
oneWire->write(0xBE); // read (temperature) from EEPROM
|
||||
oneWire->read_bytes(data, 9); // first 2 bytes contain temperature
|
||||
#ifdef WLED_DEBUG
|
||||
if (OneWire::crc8(data,8) != data[8]) {
|
||||
DEBUG_PRINTLN(F("CRC error reading temperature."));
|
||||
for (byte i=0; i < 9; i++) DEBUG_PRINTF("0x%02X ", data[i]);
|
||||
DEBUG_PRINT(F(" => "));
|
||||
DEBUG_PRINTF("0x%02X\n", OneWire::crc8(data,8));
|
||||
}
|
||||
#endif
|
||||
switch(sensorFound) {
|
||||
case 0x10: // DS18S20 has 9-bit precision
|
||||
result = (data[1] << 8) | data[0];
|
||||
retVal = float(result) * 0.5f;
|
||||
break;
|
||||
case 0x22: // DS18B20
|
||||
case 0x28: // DS1822
|
||||
case 0x3B: // DS1825
|
||||
case 0x42: // DS28EA00
|
||||
result = (data[1]<<4) | (data[0]>>4); // we only need whole part, we will add fraction when returning
|
||||
if (data[1] & 0x80) result |= 0xF000; // fix negative value
|
||||
retVal = float(result) + ((data[0] & 0x08) ? 0.5f : 0.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (byte i=1; i<9; i++) data[0] &= data[i];
|
||||
return data[0]==0xFF ? -127.0f : retVal;
|
||||
}
|
||||
|
||||
void requestTemperatures() {
|
||||
readDallas();
|
||||
DEBUG_PRINTLN(F("Requesting temperature."));
|
||||
oneWire->reset();
|
||||
oneWire->skip(); // skip ROM
|
||||
oneWire->write(0x44,parasite); // request new temperature reading (TODO: parasite would need special handling)
|
||||
lastTemperaturesRequest = millis();
|
||||
waitingForConversion = true;
|
||||
DEBUG_PRINTLN(F("Requested temperature."));
|
||||
}
|
||||
|
||||
void readTemperature() {
|
||||
@ -102,10 +122,13 @@ class UsermodTemperature : public Usermod {
|
||||
case 0x3B: // DS1825
|
||||
case 0x42: // DS28EA00
|
||||
DEBUG_PRINTLN(F("Sensor found."));
|
||||
sensorFound = deviceAddress[0];
|
||||
DEBUG_PRINTF("0x%02X\n", sensorFound);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG_PRINTLN(F("Sensor NOT found."));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -113,16 +136,16 @@ class UsermodTemperature : public Usermod {
|
||||
|
||||
void setup() {
|
||||
int retries = 10;
|
||||
sensorFound = 0;
|
||||
temperature = -127.0f; // default to -127, DS18B20 only goes down to -50C
|
||||
if (enabled) {
|
||||
// config says we are enabled
|
||||
DEBUG_PRINTLN(F("Allocating temperature pin..."));
|
||||
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
||||
if (temperaturePin >= 0 && pinManager.allocatePin(temperaturePin, true, PinOwner::UM_Temperature)) {
|
||||
oneWire = new OneWire(temperaturePin);
|
||||
if (!oneWire->reset()) {
|
||||
sensorFound = false; // resetting 1-Wire bus yielded an error
|
||||
} else {
|
||||
while ((sensorFound=findSensor()) && retries--) {
|
||||
if (oneWire->reset()) {
|
||||
while (!findSensor() && retries--) {
|
||||
delay(25); // try to find sensor
|
||||
}
|
||||
}
|
||||
@ -131,7 +154,6 @@ class UsermodTemperature : public Usermod {
|
||||
DEBUG_PRINTLN(F("Temperature pin allocation failed."));
|
||||
}
|
||||
temperaturePin = -1; // allocation failed
|
||||
sensorFound = false;
|
||||
}
|
||||
}
|
||||
lastMeasurement = millis() - readingInterval + 10000;
|
||||
@ -139,8 +161,9 @@ class UsermodTemperature : public Usermod {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (!enabled || strip.isUpdating()) return;
|
||||
if (!enabled || !sensorFound || strip.isUpdating()) return;
|
||||
|
||||
static uint8_t errorCount = 0;
|
||||
unsigned long now = millis();
|
||||
|
||||
// check to see if we are due for taking a measurement
|
||||
@ -156,20 +179,26 @@ class UsermodTemperature : public Usermod {
|
||||
}
|
||||
|
||||
// we were waiting for a conversion to complete, have we waited log enough?
|
||||
if (now - lastTemperaturesRequest >= 100 /* 93.75ms per the datasheet but can be up to 750ms */) {
|
||||
if (now - lastTemperaturesRequest >= 750 /* 93.75ms per the datasheet but can be up to 750ms */) {
|
||||
readTemperature();
|
||||
if (getTemperatureC() < -100.0f) {
|
||||
if (++errorCount > 10) sensorFound = 0;
|
||||
lastMeasurement = now - readingInterval + 300; // force new measurement in 300ms
|
||||
return;
|
||||
}
|
||||
errorCount = 0;
|
||||
|
||||
if (WLED_MQTT_CONNECTED) {
|
||||
char subuf[64];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
if (-100 <= temperature) {
|
||||
if (temperature > -100.0f) {
|
||||
// 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_P(subuf, PSTR("/temperature"));
|
||||
mqtt->publish(subuf, 0, false, String(temperature).c_str());
|
||||
mqtt->publish(subuf, 0, false, String(getTemperatureC()).c_str());
|
||||
strcat_P(subuf, PSTR("_f"));
|
||||
mqtt->publish(subuf, 0, false, String((float)temperature * 1.8f + 32).c_str());
|
||||
mqtt->publish(subuf, 0, false, String(getTemperatureF()).c_str());
|
||||
} else {
|
||||
// publish something else to indicate status?
|
||||
}
|
||||
@ -202,13 +231,13 @@ class UsermodTemperature : public Usermod {
|
||||
JsonArray temp = user.createNestedArray(FPSTR(_name));
|
||||
//temp.add(F("Loaded."));
|
||||
|
||||
if (temperature <= -100.0 || (!sensorFound && temperature == -1.0)) {
|
||||
if (temperature <= -100.0f) {
|
||||
temp.add(0);
|
||||
temp.add(F(" Sensor Error!"));
|
||||
return;
|
||||
}
|
||||
|
||||
temp.add(degC ? temperature : (float)temperature * 1.8f + 32);
|
||||
temp.add(degC ? getTemperatureC() : getTemperatureF());
|
||||
if (degC) temp.add(F("°C"));
|
||||
else temp.add(F("°F"));
|
||||
}
|
||||
@ -252,23 +281,21 @@ class UsermodTemperature : public Usermod {
|
||||
bool readFromConfig(JsonObject &root) {
|
||||
// we look for JSON object: {"Temperature": {"pin": 0, "degC": true}}
|
||||
int8_t newTemperaturePin = temperaturePin;
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
|
||||
JsonObject top = root[FPSTR(_name)];
|
||||
if (top.isNull()) {
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
||||
return false;
|
||||
}
|
||||
|
||||
enabled = top[FPSTR(_enabled)] | enabled;
|
||||
newTemperaturePin = top["pin"] | newTemperaturePin;
|
||||
// newTemperaturePin = min(33,max(-1,(int)newTemperaturePin)); // bounds check
|
||||
degC = top["degC"] | degC;
|
||||
readingInterval = top[FPSTR(_readInterval)] | readingInterval/1000;
|
||||
readingInterval = min(120,max(10,(int)readingInterval)) * 1000; // convert to ms
|
||||
parasite = top[FPSTR(_parasite)] | parasite;
|
||||
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
if (!initDone) {
|
||||
// first run: reading from cfg.json
|
||||
temperaturePin = newTemperaturePin;
|
||||
|
@ -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 || strip.isUpdating()) 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 || strip.isUpdating()) 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!).
|
||||
*/
|
||||
|
@ -5,31 +5,35 @@ This usermod-v2 modification allows the connection of multiple relays each with
|
||||
## HTTP API
|
||||
All responses are returned as JSON.
|
||||
|
||||
Status Request: `http://[device-ip]/relays`
|
||||
Switch Command: `http://[device-ip]/relays?switch=1,0,1,1`
|
||||
* Status Request: `http://[device-ip]/relays`
|
||||
* Switch Command: `http://[device-ip]/relays?switch=1,0,1,1`
|
||||
|
||||
The number of numbers behind the switch parameter must correspond to the number of relays. The number 1 switches the relay on. The number 0 switches the relay off.
|
||||
|
||||
Toggle Command: `http://[device-ip]/relays?toggle=1,0,1,1`
|
||||
* Toggle Command: `http://[device-ip]/relays?toggle=1,0,1,1`
|
||||
|
||||
The number of numbers behind the parameter switch must correspond to the number of relays. The number 1 causes a toggling of the relay. The number 0 leaves the state of the device.
|
||||
|
||||
Examples
|
||||
1. 4 relays at all, relay 2 will be toggled: `http://[device-ip]/relays?toggle=0,1,0,0`
|
||||
2. 3 relays at all, relay 1&3 will be switched on: `http://[device-ip]/relays?switch=1,0,1`
|
||||
1. total of 4 relays, relay 2 will be toggled: `http://[device-ip]/relays?toggle=0,1,0,0`
|
||||
2. total of 3 relays, relay 1&3 will be switched on: `http://[device-ip]/relays?switch=1,0,1`
|
||||
|
||||
## JSON API
|
||||
You can switch relay state using the following JSON object transmitted to: `http://[device-ip]/json`
|
||||
|
||||
|
||||
Switch relay 0 on: `{"MultiRelay":{"relay":0,"on":true}}`
|
||||
|
||||
Switch relay4 3 & 4 off: `{"MultiRelay":[{"relay":2,"on":false},{"relay":3,"on":false}]}`
|
||||
|
||||
## MQTT API
|
||||
|
||||
wled/deviceMAC/relay/0/command on|off|toggle
|
||||
wled/deviceMAC/relay/1/command on|off|toggle
|
||||
* `wled`/_deviceMAC_/`relay`/`0`/`command` `on`|`off`|`toggle`
|
||||
* `wled`/_deviceMAC_/`relay`/`1`/`command` `on`|`off`|`toggle`
|
||||
|
||||
When relay is switched it will publish a message:
|
||||
|
||||
wled/deviceMAC/relay/0 on|off
|
||||
* `wled`/_deviceMAC_/`relay`/`0` `on`|`off`
|
||||
|
||||
|
||||
## Usermod installation
|
||||
@ -76,10 +80,21 @@ void registerUsermods()
|
||||
|
||||
Usermod can be configured in Usermods settings page.
|
||||
|
||||
* `enabled` - enable/disable usermod
|
||||
* `pin` - GPIO pin where relay is attached to ESP
|
||||
* `delay-s` - delay in seconds after on/off command is received
|
||||
* `active-high` - toggle high/low activation of relay (can be used to reverse relay states)
|
||||
* `external` - if enabled WLED does not control relay, it can only be triggered by external command (MQTT, HTTP, JSON or button)
|
||||
* `button` - button (from LED Settings) that controls this relay
|
||||
|
||||
If there is no MultiRelay section, just save current configuration and re-open Usermods settings page.
|
||||
|
||||
Have fun - @blazoncek
|
||||
|
||||
## Change log
|
||||
2021-04
|
||||
* First implementation.
|
||||
* First implementation.
|
||||
|
||||
2021-11
|
||||
* Added information about dynamic configuration options
|
||||
* Added button support.
|
477
usermods/usermod_v2_four_line_display_ALT/4LD_wled_fonts.c
Normal file
477
usermods/usermod_v2_four_line_display_ALT/4LD_wled_fonts.c
Normal file
@ -0,0 +1,477 @@
|
||||
#pragma once
|
||||
|
||||
//WLED custom fonts, curtesy of @Benji (https://github.com/Proto-molecule)
|
||||
|
||||
|
||||
/*
|
||||
Fontname: wled_logo_akemi_4x4
|
||||
Copyright: Benji (https://github.com/proto-molecule)
|
||||
Glyphs: 3/3
|
||||
BBX Build Mode: 3
|
||||
* this logo ...WLED/images/wled_logo_akemi.png
|
||||
* encode map = 1, 2, 3
|
||||
*/
|
||||
const uint8_t u8x8_wled_logo_akemi_4x4[388] U8X8_FONT_SECTION("u8x8_wled_logo_akemi_4x4") =
|
||||
"\1\3\4\4\0\0\0\0\0\0\0\0\0\340\360\10\350\10\350\210\270\210\350\210\270\350\10\360\340\0\0\0"
|
||||
"\0\0\200\200\0\0@\340\300\340@\0\0\377\377\377\377\377\377\37\37\207\207\371\371\371\377\377\377\0\0\374"
|
||||
"\374\7\7\371\0\0\6\4\15\34x\340\200\177\177\377\351yy\376\356\357\217\177\177\177o\377\377\0\70\77"
|
||||
"\277\376~\71\0\0\0\0\0\0\0\1\3\3\3\1\0\0\37\77\353\365\77\37\0\0\0\0\5\7\2\3"
|
||||
"\7\4\0\0\300\300\300\300\200\200\200\0\0\0\0\0\0\0\200\200\300\300\300\300\200\200\0\0\0\0\0\0"
|
||||
"\0\200\200\300\371\37\37\371\371\7\7\377\374\0\0\0\374\377\377\37\37\341\341\377\377\377\377\374\0\0\0\374"
|
||||
"\377\7\7\231\371\376>\371\371>~\377\277\70\0\270\377\177\77\376\376\71\371\371\71\177\377\277\70\0\70\377"
|
||||
"\177>\376\371\377\377\0\77\77\0\0\4\7\2\7\5\0\0\0\377\377\0\77\77\0\0\0\5\7\2\7\5"
|
||||
"\0\0\377\377\300\300\300\200\200\0\0\0\0\0\0\0\200\200\300\300\300\300\300\200\200\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\231\231\231\371\377\377\374\0\0\0\374\377\347\347\371\1\1\371\371\7\7\377\374\0\0\0@\340"
|
||||
"\300\340@\0\71\371\371\71\177\377\277\70\0\70\277\377\177\71\371\370\70\371\371~\376\377\77\70\200\340x\34"
|
||||
"\15\4\6\0\0\77\77\0\0\0\5\7\2\7\5\0\0\0\377\377\0\77\77\0\0\1\3\3\1\1\0\0"
|
||||
"\0\0\0";
|
||||
|
||||
|
||||
/*
|
||||
Fontname: wled_logo_akemi_5x5
|
||||
Copyright: Benji (https://github.com/proto-molecule)
|
||||
Glyphs: 3/3
|
||||
BBX Build Mode: 3
|
||||
* this logo ...WLED/images/wled_logo_akemi.png
|
||||
* encoded = 1, 2, 3
|
||||
*/
|
||||
/*
|
||||
const uint8_t u8x8_wled_logo_akemi_5x5[604] U8X8_FONT_SECTION("u8x8_wled_logo_akemi_5x5") =
|
||||
"\1\3\5\5\0\0\0\0\0\0\0\0\0\0\0\0\340\340\374\14\354\14\354\14|\14\354\14||\14\354"
|
||||
"\14\374\340\340\0\0\0\0\0\0\0\200\0\0\0\200\200\0\200\200\0\0\0\0\377\377\377\376\377\376\377\377"
|
||||
"\377\377\77\77\307\307\307\307\306\377\377\377\0\0\0\360\374>\77\307\0\0\61cg\357\347\303\301\200\0\0"
|
||||
"\377\377\377\317\317\317\317\360\360\360\374\374\377\377\377\377\377\377\377\377\0\0\200\377\377\340\340\37\0\0\0\0"
|
||||
"\0\0\1\3\17\77\374\360\357\357\177\36\14\17\357\377\376\376>\376\360\357\17\17\14>\177o\340\300\343c"
|
||||
"{\77\17\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\17\37\37\362\375\37\37\17\0\0"
|
||||
"\0\0\1\1\1\0\1\1\1\0\0\0\200\300\300\300\300\200\200\0\0\0\0\0\0\0\0\0\0\0\200\200"
|
||||
"\300\300\300\300\200\200\0\0\0\0\0\0\0\0\0\0\0\0\200\200\307\307\377\377\307\307\307\77>\374\360\0"
|
||||
"\0\0\360\374\376\377\377\377\7\7\7\377\377\377\377\376\374\360\0\0\0\0\360\374\36\37\37\343\37\37\340\340"
|
||||
"\37\37\37\340\340\377\377\200\0\200\377\377\377\340\340\340\37\37\37\37\37\37\37\377\377\377\200\0\0\200\377\377"
|
||||
"\340\340\340\34\377\377\3\3\377\377\3\17\77{\343\303\300\303\343s\77\37\3\377\377\3\3\377\377\3\17\77"
|
||||
"{\343\303\300\300\343{\37\17\3\377\377\377\377\0\0\37\37\0\0\1\1\1\1\0\1\1\1\1\0\0\377"
|
||||
"\377\0\0\37\37\0\0\1\1\1\1\0\0\1\1\1\0\0\377\377\300\300\300\200\200\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\200\200\300\300\300\300\200\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\343\343\343\343"
|
||||
"\343\377\376\374\360\0\0\0\360\374\376\77\77\307\307\7\7\307\307\307\77>\374\360\0\0\0\0\0\200\200\0"
|
||||
"\200\200\0\0\34\34\34\37\37\377\377\377\377\200\0\200\377\377\377\377\37\37\37\0\0\37\37\37\340\340\377\377"
|
||||
"\200\0\0\0\1\303\347\357gc\61\0\3\3\377\377\3\7\37\177s\343\300\303s{\37\17\7\3\377\377"
|
||||
"\3\3\377\377\3\37\77scp<\36\17\3\1\0\0\0\0\0\0\0\37\37\0\0\0\1\1\1\0\1"
|
||||
"\1\1\0\0\0\0\377\377\0\0\37\37\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
*/
|
||||
|
||||
/*
|
||||
Fontname: wled_logo_2x2
|
||||
Copyright: Benji (https://github.com/proto-molecule)
|
||||
Glyphs: 4/4
|
||||
BBX Build Mode: 3
|
||||
* this logo https://cdn.discordapp.com/attachments/706623245935444088/927361780613799956/wled_scaled.png
|
||||
* encode map = 1, 2, 3, 4
|
||||
*/
|
||||
const uint8_t u8x8_wled_logo_2x2[133] U8X8_FONT_SECTION("u8x8_wled_logo_2x2") =
|
||||
"\1\4\2\2\0\0\0\0\0\200\200\360\360\16\16\16\16\0\0\0\340\340\340\340\340\37\37\1\1\0\0\0"
|
||||
"\0\0\0\0\360\360\16\16\16\200\200\16\16\16\360\360\0\0\0\200\37\37\340\340\340\37\37\340\340\340\37\37"
|
||||
"\0\0\0\37\200~~\0\0\0\0\0\0\0\360\360\216\216\216\216\37\340\340\340\340\340\340\340\0\0\37\37"
|
||||
"\343\343\343\343\16\16\0\0ppp\16\16\376\376\16\16\16\360\360\340\340\0\0\0\0\0\340\340\377\377\340"
|
||||
"\340\340\37\37";
|
||||
|
||||
|
||||
/*
|
||||
Fontname: wled_logo_4x4
|
||||
Copyright: Created with Fony 1.4.7
|
||||
Glyphs: 4/4
|
||||
BBX Build Mode: 3
|
||||
* this logo https://cdn.discordapp.com/attachments/706623245935444088/927361780613799956/wled_scaled.png
|
||||
* encode map = 1, 2, 3, 4
|
||||
*/
|
||||
/*
|
||||
const uint8_t u8x8_wled_logo_4x4[517] U8X8_FONT_SECTION("u8x8_wled_logo_4x4") =
|
||||
"\1\4\4\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\374\374\374\374\374\374\374\374\374"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\300\300\300\300\300\377\377\377\377\377\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\17\17\17\17\17\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\370\370\370\370\370\370\370\370\370\7\7\7\7\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\374\374\374\374\374\0\0\0\0\0\374\374\374\374\374\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\377\377\377\377\377\0\0\0\0\0\300\300\300\300\300\0\0\0\0\0\377\377\377\377\377\0\0"
|
||||
"\0\0\300\300\0\377\377\377\377\377\0\0\0\0\0\377\377\377\377\377\0\0\0\0\0\377\377\377\377\377\0\0"
|
||||
"\0\0\377\377\0\7\7\7\7\7\370\370\370\370\370\7\7\7\7\7\370\370\370\370\370\7\7\7\7\7\0\0"
|
||||
"\0\0\7\7\0\0\0\374\374\374\374\374\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\374\374\374"
|
||||
"\374\374\374\374\300\300\300\77\77\77\77\77\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\300\300\300"
|
||||
"\300\300\300\300\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\37\37\37"
|
||||
"\37\37\37\37\7\7\7\370\370\370\370\370\370\370\370\370\370\370\370\370\0\0\0\0\7\7\7\7\7\370\370\370"
|
||||
"\370\370\370\370\374\374\374\374\374\374\0\0\0\0\0\0\0\0\374\374\374\374\374\374\374\374\374\374\374\374\374\374"
|
||||
"\0\0\0\0\300\300\0\0\0\0\0\0\0\77\77\77\77\77\0\0\0\0\377\377\377\377\377\0\0\0\0\377"
|
||||
"\377\377\377\377\37\37\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\0\0\0\0\377"
|
||||
"\377\377\377\377\370\370\370\370\370\370\0\0\0\0\0\0\0\0\370\370\370\370\377\377\377\377\377\370\370\370\370\377"
|
||||
"\7\7\7\7";
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Fontname: 4LineDisplay_WLED_icons_1x
|
||||
Copyright: Benji (https://github.com/proto-molecule)
|
||||
Glyphs: 13/13
|
||||
BBX Build Mode: 3
|
||||
* 1 = sun
|
||||
* 2 = skip forward
|
||||
* 3 = fire
|
||||
* 4 = custom palette
|
||||
* 5 = puzzle piece
|
||||
* 6 = moon
|
||||
* 7 = brush
|
||||
* 8 = contrast
|
||||
* 9 = power-standby
|
||||
* 10 = star
|
||||
* 11 = heart
|
||||
* 12 = Akemi
|
||||
*-----------
|
||||
* 20 = wifi
|
||||
* 21 = media-play
|
||||
*/
|
||||
const uint8_t u8x8_4LineDisplay_WLED_icons_1x1[172] U8X8_FONT_SECTION("u8x8_4LineDisplay_WLED_icons_1x1") =
|
||||
"\1\25\1\1\0B\30<<\30B\0~<\30\0~<\30\0p\374\77\216\340\370\360\0<n\372\377"
|
||||
"\275\277\26\34\374\374\77\77\374\374\60\60<~~\360\340``\0\200\340\360p\14\16\6\1<~\377\377"
|
||||
"\201\201B<\70D\200\217\200D\70\0\0\10x<<x\10\0\14\36>||>\36\14\64 \336\67"
|
||||
";\336 \64\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\1\11\311"
|
||||
"\311\1\2\0\0~<<\30\30\0";
|
||||
|
||||
|
||||
/*
|
||||
Fontname: 4LineDisplay_WLED_icons_2x1
|
||||
Copyright: Benji (https://github.com/proto-molecule)
|
||||
Glyphs: 11/11
|
||||
BBX Build Mode: 3
|
||||
* 1 = sun
|
||||
* 2 = skip forward
|
||||
* 3 = fire
|
||||
* 4 = custom palette
|
||||
* 5 = puzzle piece
|
||||
* 6 = moon
|
||||
* 7 = brush
|
||||
* 8 = contrast
|
||||
* 9 = power-standby
|
||||
* 10 = star
|
||||
* 11 = heart
|
||||
* 12 = Akemi
|
||||
*/
|
||||
const uint8_t u8x8_4LineDisplay_WLED_icons_2x1[196] U8X8_FONT_SECTION("u8x8_4LineDisplay_WLED_icons_2x1") =
|
||||
"\1\14\2\1\20\20BB\30\30<\275\275<\30\30BB\20\20\377~<<\70\30\20\0\377~<<"
|
||||
"\70\30\20\0\60p\370\374\77>\236\214\300\340\370\360\360\340\0\0\34<v\326\336\375\375\377\277\275=>"
|
||||
"\66\66<\34\374\374\374\374~\77\77~\374\374\374\374 pp \30<~~\377\370\360\360\340\340\340\340"
|
||||
"@@ \0\200\300\340\360\360p`\10\34\34\16\6\6\3\0\0\70|~\376\376\377\377\377\201\201\203\202"
|
||||
"\302Fl\70\70xL\204\200\200\217\217\200\200\204Lx\70\0\0\10\10\30\330x|\77\77|x\330\30"
|
||||
"\10\10\0\0\14\36\37\77\77\177~\374\374~\177\77\77\37\36\14\24\64 \60>\26\367\33\375\36>\60"
|
||||
" \64\24";
|
||||
|
||||
|
||||
/*
|
||||
Fontname: 4LineDisplay_WLED_icons_2x
|
||||
Copyright:
|
||||
Glyphs: 11/11
|
||||
BBX Build Mode: 3
|
||||
* 1 = sun
|
||||
* 2 = skip forward
|
||||
* 3 = fire
|
||||
* 4 = custom palette
|
||||
* 5 = puzzle piece
|
||||
* 6 = moon
|
||||
* 7 = brush
|
||||
* 8 = contrast
|
||||
* 9 = power-standby
|
||||
* 10 = star
|
||||
* 11 = heart
|
||||
* 12 = Akemi
|
||||
*/
|
||||
const uint8_t u8x8_4LineDisplay_WLED_icons_2x2[389] U8X8_FONT_SECTION("u8x8_4LineDisplay_WLED_icons_2x2") =
|
||||
"\1\14\2\2\200\200\14\14\300\340\360\363\363\360\340\300\14\14\200\200\1\1\60\60\3\7\17\317\317\17\7\3"
|
||||
"\60\60\1\1\374\370\360\340\340\300\200\0\374\370\360\340\340\300\200\0\77\37\17\7\7\3\1\0\77\37\17\7"
|
||||
"\7\3\1\0\0\200\340\360\377\376\374\360\0\0\300\200\0\0\0\0\17\77\177\377\17\7\301\340\370\374\377\377"
|
||||
"\377|\0\0\360\370\234\236\376\363\363\377\377\363\363\376><\370\360\3\17\77yy\377\377\377\377\317\17\17"
|
||||
"\17\17\7\3\360\360\360\360\366\377\377\366\360\360\360\360\0\0\0\0\377\377\377\377\237\17\17\237\377\377\377\377"
|
||||
"\6\17\17\6\340\370\374\376\377\340\200\0\0\0\0\0\0\0\0\0\3\17\37\77\177\177\177\377\376|||"
|
||||
"\70\30\14\0\0\0\0\0\0\0\0``\360\370|<\36\7\2\0\300\360\376\377\177\77\36\0\1\1\0"
|
||||
"\0\0\0\0\340\370\374\376\376\377\377\377\3\3\7\6\16<\370\340\7\37\77\177\177\377\377\377\300\300\340`"
|
||||
"p<\37\7\300\340p\30\0\0\377\377\0\0\30p\340\300\0\0\17\37\70`\340\300\300\300\300\340`\70"
|
||||
"\37\17\0\0\0@\300\300\300\300\340\374\374\340\300\300\300\300@\0\0\0\0\1s\77\37\17\17\37\77s"
|
||||
"\1\0\0\0\360\370\374\374\374\374\370\360\360\370\374\374\374\374\370\360\0\1\3\7\17\37\77\177\177\77\37\17"
|
||||
"\7\3\1\0\200\200\0\0\0\360\370\374<\334\330\360\0\0\200\200\2\2\14\30\24\37\6~\7\177\7\37"
|
||||
"\24\30\16\2";
|
||||
|
||||
/*
|
||||
Fontname: 4LineDisplay_WLED_icons_3x
|
||||
Copyright: Benji (https://github.com/proto-molecule)
|
||||
Glyphs: 11/11
|
||||
BBX Build Mode: 3
|
||||
* 1 = sun
|
||||
* 2 = skip forward
|
||||
* 3 = fire
|
||||
* 4 = custom palette
|
||||
* 5 = puzzle piece
|
||||
* 6 = moon
|
||||
* 7 = brush
|
||||
* 8 = contrast
|
||||
* 9 = power-standby
|
||||
* 10 = star
|
||||
* 11 = heart
|
||||
* 12 = Akemi
|
||||
*/
|
||||
const uint8_t u8x8_4LineDisplay_WLED_icons_3x3[868] U8X8_FONT_SECTION("u8x8_4LineDisplay_WLED_icons_3x3") =
|
||||
"\1\14\3\3\0\0\34\34\34\0\200\300\300\340\347\347\347\340\300\300\200\0\34\34\34\0\0\0\34\34\34\0"
|
||||
"\0>\377\377\377\377\377\377\377\377\377\377\377>\0\0\34\34\34\0\0\0\16\16\16\0\0\1\1\3ss"
|
||||
"s\3\1\1\0\0\34\34\34\0\0\0\370\360\340\300\300\200\0\0\0\0\0\0\370\360\340\300\300\200\0\0"
|
||||
"\0\0\0\0\377\377\377\377\377\377\377\376~<\70\20\377\377\377\377\377\377\377\376~<\70\20\37\17\17\7"
|
||||
"\3\1\1\0\0\0\0\0\37\17\17\7\3\1\1\0\0\0\0\0\0\0\0\0\0\300\361\376\374\370\360\300"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\300\370\374\376\377\377\377\377\377\177\77\17\6\0\200\342\374\370\360\340"
|
||||
"\200\0\0\0\1\17\37\77\177\377\7\3\0\200\360\370\374\376\377\377\377\377\377\377\77\0\0\0\0\200\340\360"
|
||||
"\370\370\374\316\206\206\317\377\377\377\317\206\206\316\374\374\370\360\340\200<\377\377\371\360py\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\363\341\341\363\377\177\0\1\7\17\34\70x|\377\377\377\377\367\363c\3\3\3\3\1"
|
||||
"\1\1\0\0\300\300\300\300\300\300\300\316\377\377\377\316\300\300\300\300\300\300\0\0\0\0\0\0\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\300\300\340\340\340\300\377\377\377\377\377\377\377\307\3\3\3\307"
|
||||
"\377\377\377\377\377\377\1\1\3\3\3\1\0\300\340\370\374\374\376\377\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0>\377\377\377\377\377\377\377\377\374\360\340\300\300\200\200\0\0\0\0\0\0\200\200\0\1\7\17"
|
||||
"\37\37\77\177\177\177\177\377\377\377\177\177\177\77\77\37\17\7\3\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\200\200\300\340\340\360\370\374|>\17\6\0\0\0\0\0\340\340\360\360\360\342\303\7\17\37\77\37\7\3\1"
|
||||
"\0\0\0\0\0\200\340\360\377\377\377\377\177\77\37\17\0\0\0\0\0\0\0\0\0\0\0\0\0\200\340\360"
|
||||
"\370\374\374\376\376\376\377\377\7\7\7\6\16\16\34\70\360\340\300\0|\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\0\0\0\0\0\0\0\0\0\377\377\377\0\3\7\17\37\77\177\177\377\377\377\377\340\340\340\340pp\70<"
|
||||
"\37\17\3\0\0\0\200\300\340\340\300\0\0\377\377\377\0\0\300\340\340\300\200\0\0\0\0\0\370\376\377\17"
|
||||
"\3\0\0\0\0\17\17\17\0\0\0\0\0\3\17\377\376\370\0\0\0\7\17\37<xp\340\340\340\340\340"
|
||||
"\340\340\340px<\37\17\3\0\0\0\0\0\0\0\0\0\0\0\0\0\300\370\376\370\200\0\0\0\0\0"
|
||||
"\0\0\0\0\0\2\6\16\36\36>~\376\376\377\377\377\377\377\376\376~>\36\16\6\6\2\0\0\0\0"
|
||||
"\0\300x<\37\17\17\7\3\7\17\17\37<x\300\0\0\0\0\200\300\340\360\360\370\370\370\360\360\340\300"
|
||||
"\200\300\340\360\360\370\370\370\360\360\340\200\17\37\77\177\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\177\77\37\17\0\0\0\0\0\1\3\7\17\37\77\177\177\77\37\17\7\3\1\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\200\300\340\360\370\370\370p`\300\200\0\0\0\0\0\0&,f\300\0\0\300\377\377\357\357\357"
|
||||
"\363\370\377\377\377\377\300\0\0\306l&\0\0\0\1\7\16\14\6\7\1\177\177\0\177\177\1\7\6\14\16"
|
||||
"\7\1\0";
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Fontname: 4LineDisplay_WLED_icons_4x
|
||||
Copyright: Benji (https://github.com/proto-molecule)
|
||||
Glyphs: 11/11
|
||||
BBX Build Mode: 3
|
||||
* 1 = sun
|
||||
* 2 = skip forward
|
||||
* 3 = fire
|
||||
* 4 = custom palette
|
||||
* 5 = puzzle piece
|
||||
* 6 = moon
|
||||
* 7 = brush
|
||||
* 8 = contrast
|
||||
* 9 = power-standby
|
||||
* 10 = star
|
||||
* 11 = heart
|
||||
* 12 = Akemi
|
||||
*/
|
||||
/*
|
||||
const uint8_t u8x8_4LineDisplay_WLED_icons_4x4[1540] U8X8_FONT_SECTION("u8x8_4LineDisplay_WLED_icons_4x4") =
|
||||
"\1\14\4\4\0\0\0\0`\360\360`\0\0\0\0\0\0\6\17\17\6\0\0\0\0\0\0`\360\360`"
|
||||
"\0\0\0\0\200\300\300\200\0\0\0\0\340\370\374\376\376\377\377\377\377\377\377\376\376\374\370\340\0\0\0\0"
|
||||
"\200\300\300\200\1\3\3\1\0\0\0\0\7\37\77\177\177\377\377\377\377\377\377\177\177\77\37\7\0\0\0\0"
|
||||
"\1\3\3\1\0\0\0\0\6\17\17\6\0\0\0\0\0\0`\360\360`\0\0\0\0\0\0\6\17\17\6"
|
||||
"\0\0\0\0\360\340\300\200\200\0\0\0\0\0\0\0\0\0\0\0\360\340\300\200\200\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\377\377\377\377\377\377\376\374\374\370\360\340\340\300\200\0\377\377\377\377\377\377\376\374\374\370\360\340"
|
||||
"\340\300\200\0\377\377\377\377\377\377\177\77\77\37\17\7\7\3\1\0\377\377\377\377\377\377\177\77\77\37\17\7"
|
||||
"\7\3\1\0\17\7\3\1\1\0\0\0\0\0\0\0\0\0\0\0\17\7\3\1\1\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\200\341\376\374\370\360\340\300\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\200\300\360\370\374\376\377\377\377\377\377\377\377\377~\0\0\0\0\20\340\300\200\0\0\0\0"
|
||||
"\0\0\0\0~\377\377\377\377\377\377\377\377\177\77\37\17\3\1\0\200\300\340\370\376\377\377\377\377\376\374\340"
|
||||
"\0\0\0\0\0\3\7\17\37\77\177\207\1\0\0\0\340\370\374\377\377\377\377\377\377\377\377\377\377\177\77\17"
|
||||
"\0\0\0\0\0\0\0\200\300\360\370\370\374\34\16\16\16\36\377\377\377\377\37\16\16\16\36\374\374\370\370\360"
|
||||
"\340\300\0\0\340\374\377\377\217\7\7\7\217\377\376\376\376\377\377\377\377\377\377\376\376\376\377\377\217\7\7\7"
|
||||
"\217\377\377\374\17\177\377\377\377\37\17\17\17\37\377\377\377\377\377\377\377\377\377\377\377\377\177\177\177\177\77\77"
|
||||
"\77\37\17\7\0\0\0\3\7\17\36>>\177\177\377\377\377\377\377\377\371p\60\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0<\376\377\377\377\377\376<\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0"
|
||||
"\0\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377~~\377\377"
|
||||
"\377\377~<\377\377\377\377\377\377\377\377\303\1\0\0\0\0\1\303\377\377\377\377\377\377\377\377\0\0\0\0"
|
||||
"\0\0\0\0\0\0\200\340\360\370\374\374\376\376\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\370\377\377\377\377\377\377\377\377\377\376\360\300\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\7\77\377\377\377\377\377\377\377\377\377\377\377\377\377\376\374\370\370\360\360\360\340\340\340\340\340\340"
|
||||
"\340\340\60\0\0\0\0\1\3\7\17\37\37\77\77\77\177\177\177\177\177\177\177\177\77\77\77\37\37\17\7\3"
|
||||
"\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\200\200\300\340\340\360\370\374\374"
|
||||
"~\77\16\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\30\34>~\377\377\377\377\177\77\37\7\3\0"
|
||||
"\0\0\0\0\0\0\0\0\0\360\374\376\377\377\377\377\377\376\374\370\0\0\0\3\3\1\0\0\0\0\0\0"
|
||||
"\0\0\0\0@@\340\370\374\377\377\377\177\177\177\77\37\17\7\1\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\200\300\340\360\370\374\374\376\376\376\377\377\377\377\17\17\17\37\36\36>|\374\370\360\340"
|
||||
"\300\200\0\0\360\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\1\3\37"
|
||||
"\377\377\376\360\17\177\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\200\300\370"
|
||||
"\377\377\177\17\0\0\1\3\7\17\37\77\77\177\177\177\377\377\377\377\360\360\360\370xx|>\77\37\17\7"
|
||||
"\3\1\0\0\0\0\0\0\0\200\300\200\0\0\0\0\377\377\377\377\0\0\0\0\200\300\200\0\0\0\0\0"
|
||||
"\0\0\0\0\300\360\374\376\177\37\7\3\3\0\0\0\377\377\377\377\0\0\0\3\3\7\37\177\376\374\360\300"
|
||||
"\0\0\0\0\77\377\377\377\340\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\200\340\377\377\377\77"
|
||||
"\0\0\0\0\0\0\3\7\17\37><|x\370\360\360\360\360\360\360\370x|<>\37\17\7\3\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\340\374\374\340\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\20\60p\360\360\360\360\360\360\360\360\370\377\377\377\377\377\377\370\360\360\360\360\360\360\360\360"
|
||||
"p\60\20\0\0\0\0\0\0\0\1\3\7\317\377\377\377\377\377\377\377\377\377\377\377\377\317\7\3\1\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0p>\37\17\17\7\3\1\0\0\1\3\7\17\17\37>p\0\0\0"
|
||||
"\0\0\0\0\0\200\300\340\340\360\360\360\360\360\360\340\340\300\200\0\0\200\300\340\340\360\360\360\360\360\360\340"
|
||||
"\340\300\200\0~\377\377\377\377\377\377\377\377\377\377\377\377\377\377\376\376\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377~\0\1\3\7\17\37\77\177\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\177\77\37\17"
|
||||
"\7\3\1\0\0\0\0\0\0\0\0\0\0\1\3\7\17\37\77\177\177\77\37\17\7\3\1\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\200\300\340\340\360\360\360\360\340\340\300\200\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0@\340\300\340@\0\0\0\376\377\377\177\177\177\237\207\347\371\371\371\377\376\0\0\0\0@"
|
||||
"\340\300\340@\2\4\4\35x\340\200\0\30\237\377\177\36\376\376\37\37\377\377\37\177\377\237\30\0\200\340x"
|
||||
"\34\5\4\2\0\0\0\0\0\1\3\3\3\1\0\0\0\17\17\0\0\17\17\0\0\0\1\3\3\3\1\0"
|
||||
"\0\0\0";
|
||||
*/
|
||||
|
||||
/*
|
||||
Fontname: 4LineDisplay_WLED_icons_6x
|
||||
Copyright: Benji (https://github.com/proto-molecule)
|
||||
Glyphs: 11/11
|
||||
BBX Build Mode: 3
|
||||
* 1 = sun
|
||||
* 2 = skip forward
|
||||
* 3 = fire
|
||||
* 4 = custom palette
|
||||
* 5 = puzzle piece
|
||||
* 6 = moon
|
||||
* 7 = brush
|
||||
* 8 = contrast
|
||||
* 9 = power-standby
|
||||
* 10 = star
|
||||
* 11 = heart
|
||||
* 12 = Akemi
|
||||
*/
|
||||
// you can replace this (wasteful) font by using 3x3 variant with draw2x2Glyph()
|
||||
const uint8_t u8x8_4LineDisplay_WLED_icons_6x6[3460] U8X8_FONT_SECTION("u8x8_4LineDisplay_WLED_icons_6x6") =
|
||||
"\1\14\6\6\0\0\0\0\0\0\200\300\300\300\300\200\0\0\0\0\0\0\0\0\0\36\77\77\77\77\36\0"
|
||||
"\0\0\0\0\0\0\0\0\200\300\300\300\300\200\0\0\0\0\0\0\0\0\0\0\0\0\7\17\17\17\17\7"
|
||||
"\0\0\0\0\200\300\340\340\340\360\360\360\360\360\360\340\340\340\300\200\0\0\0\0\7\17\17\17\17\7\0\0"
|
||||
"\0\0\0\0\300\340\340\340\340\300\0\0\0\0\0\0\340\374\376\377\377\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\376\374\340\0\0\0\0\0\0\300\340\340\340\340\300\3\7\7\7\7\3\0\0\0\0\0\0"
|
||||
"\7\77\177\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\177\77\7\0\0\0\0\0\0\3\7"
|
||||
"\7\7\7\3\0\0\0\0\0\0\340\360\360\360\360\340\0\0\0\0\1\3\7\7\7\17\17\17\17\17\17\7"
|
||||
"\7\7\3\1\0\0\0\0\340\360\360\360\360\340\0\0\0\0\0\0\0\0\0\0\0\0\1\3\3\3\3\1"
|
||||
"\0\0\0\0\0\0\0\0\0x\374\374\374\374x\0\0\0\0\0\0\0\0\0\1\3\3\3\3\1\0\0"
|
||||
"\0\0\0\0\300\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\200\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\376\376\374\370\360\360\340\300\200"
|
||||
"\200\0\0\0\0\0\0\0\0\0\0\0\377\377\377\376\376\374\370\360\360\340\300\200\200\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\376\374\374\370\360\340\340\300\200\0\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\376\374\374\370\360\340\340\300\200\0\377\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\177\77\77\37\17\7\7\3\1\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\177\77\77\37\17\7"
|
||||
"\7\3\1\0\377\377\377\177\177\77\37\17\17\7\3\1\1\0\0\0\0\0\0\0\0\0\0\0\377\377\377\177"
|
||||
"\177\77\37\17\17\7\3\1\1\0\0\0\0\0\0\0\0\0\0\0\3\1\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\3\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\376\374\374\370\360\340\300\200\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\200\340\360\374"
|
||||
"\377\377\377\377\377\377\377\377\377\376\370\300\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\300\340\360\374\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\37\0\0\0\0"
|
||||
"\0\0\4\370\360\360\340\300\200\0\0\0\0\0\0\0\0\0\0\0\370\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\177\77\37\7\3\0\0\0\0\0\200\300\360\374\377\377\377\377\377\377\377\376\370\340\0\0\0"
|
||||
"\0\0\0\0\3\37\177\377\377\377\377\377\377\377\377\377\77\17\7\1\0\0\0\0\0\200\300\360\370\374\376\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\1\3\7\17\37\77\77\177\200"
|
||||
"\0\0\0\0\0\0\340\374\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\177\77\17\1\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\200\300\340\340\360\360\370|<>>>~\377\377\377\377\377\377\377\177"
|
||||
"\77\36\36\36\36<|\370\370\360\360\340\340\200\0\0\0\0\0\0\0\0\300\360\374\376\377\377\377\377\377\377"
|
||||
"\377\360\340\300\300\300\300\340\360\377\377\377\377\377\377\370\360\340\340\340\340\360\370\377\377\377\377\377\377\377\377\377"
|
||||
"\374\360\340\200\360\377\377\377\377\377\207\3\1\1\1\1\3\207\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\207\3\1\1\1\1\3\207\377\377\377\377\377\17\377\377\377\377\377\377\377\376~>>"
|
||||
"\77\77\177\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\376\376\376\376\377\377\377"
|
||||
"\177\77\37\7\0\0\3\17\77\177\377\377\360\340\300\300\300\300\340\360\377\377\377\377\377\377\377\377\377\377\77\17"
|
||||
"\17\7\7\7\7\7\7\7\7\7\3\3\3\3\1\0\0\0\0\0\0\0\0\0\0\0\0\1\3\7\17\37"
|
||||
"\37\77\77\177\177\177\377\377\377\377\377\377\377\377\377~\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\370\374\376\377\377\377\377\377\377\376\374\360\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\360\360\360\360\360\360\360\360\360\360\360\360"
|
||||
"\360\363\377\377\377\377\377\377\377\377\363\360\360\360\360\360\360\360\360\360\360\360\360\360\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\374\374\376\376\377\377\377\377"
|
||||
"\377\376\374\360\377\377\377\377\377\377\377\377\377\377\377\377\177\77\37\17\17\17\17\17\17\37\77\177\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\3\3\7\7\17\17\17\17\7\7\3\0\377\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\360\300\0\0\0\0\0\0\0\0\300\360\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\200\300\340\360\360\370\374\374\376\376\7\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\360\374\376\377\377\377\377\377\377\377"
|
||||
"\377\377\377\340\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\374\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\374\360\300\200\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\17\177\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\376\374\370\360\360\340\340\300\300\300\200\200\200\200\0\0\0\0\0\0\200\200"
|
||||
"\200\200\0\0\0\0\1\7\37\77\177\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\377\377\377\177\77\37\7\1\0\0\0\0\0\0\0\0\0\0\1\3\3\7"
|
||||
"\17\17\37\37\37\77\77\77\77\177\177\177\177\177\177\77\77\77\77\37\37\37\17\17\7\3\3\1\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\200\200\300\340\360\360\370\374\374\376\377~\34\10\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\200\300\300\340\360\360\370\374\376\376\377\377\377\377\377\377\177\77\17\7\3"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\6\17\17\37\77\177\377"
|
||||
"\377\377\377\377\377\377\77\37\7\3\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\370\374\376"
|
||||
"\376\377\377\377\377\377\377\376\376\374\370\340\0\0\0\0\3\17\7\3\1\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\200\360\377\377\377\377\377\377\377\377\377\377\377\377\377\377\177\17\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`px\374\376\377\377\377\377\377\377"
|
||||
"\177\177\177\77\77\37\17\7\3\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\200\300\340\360\360\370\374\374\374\376\376\376\377\377\377\377\377\77\77\77\77"
|
||||
"\177~~\376\374\374\374\370\360\360\340\300\200\0\0\0\0\0\0\0\0\0\340\360\374\376\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\1\1\3\7\17\37\177\377\377\376\374"
|
||||
"\360\340\0\0\370\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\1\17\377\377\377\377\377\370\37\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\200\360\377\377"
|
||||
"\377\377\377\37\0\0\7\17\77\177\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0"
|
||||
"\0\0\0\0\0\200\200\300\340\360\370\376\377\377\177\77\17\7\0\0\0\0\0\0\0\0\0\1\3\7\17\17"
|
||||
"\37\77\77\77\177\177\177\377\377\377\377\377\374\374\374\374\376~~\177\77\77\77\37\17\17\7\3\1\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\200\300\340\360\370\374\376\376|"
|
||||
"x \0\0\0\0\377\377\377\377\377\377\0\0\0\0 x|\376\376\374\370\360\340\300\200\0\0\0\0\0"
|
||||
"\0\0\0\0\300\370\376\377\377\377\177\17\7\1\0\0\0\0\0\0\0\0\377\377\377\377\377\377\0\0\0\0"
|
||||
"\0\0\0\0\1\7\37\177\377\377\377\376\370\200\0\0\0\0\0\0\177\377\377\377\377\377\200\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\200\377\377\377\377\377\177\0\0"
|
||||
"\0\0\0\0\0\7\37\177\377\377\377\374\370\340\300\200\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\200\200\300\340\370\374\377\377\377\177\37\7\0\0\0\0\0\0\0\0\0\0\0\0\1\3\7\17\37\37\77"
|
||||
"\77\177~~~\374\374\374\374\374\374\374\374~~~\177\77\77\37\37\17\7\3\1\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\340\374\374\340\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\300\370\377\377\377\377\377\377\370\300\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\4\14\34<<|\374\374\374\374\374\374\374\374\374\374\374\376\377\377\377\377\377\377\377\377\377"
|
||||
"\377\376\374\374\374\374\374\374\374\374\374\374\374|<<\34\14\4\0\0\0\0\0\0\0\0\0\1\3\3\7"
|
||||
"\17\37\77\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\77\37\17\7\3\3\1\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\370\377\377\377\377\377\377\177\77\37\17\17\37\77\177"
|
||||
"\377\377\377\377\377\377\370\300\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0p>"
|
||||
"\37\17\17\7\3\1\0\0\0\0\0\0\0\0\0\0\0\0\1\3\7\17\17\37>p\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\200\200\200\300\300\300\300\300\300\200\200\200\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\200\200\200\300\300\300\300\300\300\200\200\200\0\0\0\0\0\0\200\360\370\374\376\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\376\374\370\360\200\200\360\370\374\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\376"
|
||||
"\374\370\360\200\37\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\37\0\0\1\3\7\17\37\77\177\377\377\377"
|
||||
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\177\77\37\17\7"
|
||||
"\3\1\0\0\0\0\0\0\0\0\0\0\0\0\1\3\7\17\37\77\177\377\377\377\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\177\77\37\17\7\3\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\1\3\7\17\37\77\77\37\17\7\3\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\300\300\300\300\300\300"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\340\370\370\376\376\377\377\377\377\377\377\377\377\77\77\77>\376\370\370\340\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0 p\360\340\360p \0\0\0\0\0\0\377\377\377\377\177\177\177\177\177\207\207\340\340\377"
|
||||
"\377\377\377\377\377\377\377\0\0\0\0\0 p\360\340\360p \0\6\4\14\14\15|x\360\200\200\0\0"
|
||||
"pp\177\177\377\377\374|\374\374\374\177\177\177\377\377\377\177\377\377\377\377\177pp\0\0\200\200\360x}"
|
||||
"\14\14\4\6\0\0\0\0\0\0\0\3\37\37|ppp\34\34\37\3\3\0\377\377\377\0\0\0\377\377"
|
||||
"\377\0\3\3\37\37\34ppp~\37\37\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\7\7\7\0\0\0\7\7\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0";
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Fontname: akemi_8x8
|
||||
Copyright: Benji (https://github.com/proto-molecule)
|
||||
Glyphs: 1/1
|
||||
BBX Build Mode: 3
|
||||
* 12 = Akemi
|
||||
*/
|
||||
/*
|
||||
const uint8_t u8x8_akemi_8x8[516] U8X8_FONT_SECTION("u8x8_akemi_8x8") =
|
||||
"\14\14\10\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\200\200\200\200\200\200\200\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\340\340\370\370\376\376\376\376"
|
||||
"\377\377\377\377\377\377\377\377\376\376\376\376\370\370\340\340\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\376\376\377\377\377\377\377\377\377\377"
|
||||
"\377\377\377\377\37\37\37\343\343\343\343\343\343\377\377\377\376\376\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\30\30~~\370\370~~\30\30\0\0\0\0\0\0\0\377\377\377\377\377\77\77\77\77\77"
|
||||
"\77\300\300\300\370\370\370\377\377\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\30\0f\0\200\0\0"
|
||||
"\0\0\0\0\6\6\30\30\30\31\371\370\370\340\340\0\0\0\0\0\340\340\377\377\377\377\377\376\376\376\376\376"
|
||||
"\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\371\346\346\6\6\6\6\6\0\340\340\340\341\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\1\1\37\37\377\376\376\340\340\200\201\201\341\341\177\177\37\37\1\1\377\377"
|
||||
"\377\377\1\1\1\1\377\377\377\377\1\1\37\37\177\177\341\341\201\201\200\200\370\370\376\376\37\37\1\1\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\1\7\7\7\7\7\7\1\1\0\0\0\0\0\0\377\377"
|
||||
"\377\377\0\0\0\0\377\377\377\377\0\0\0\0\0\0\1\1\7\7\7\7\7\7\1\1\0\0\0\0\0\0"
|
||||
"\0\0\0";
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
@ -19,17 +19,20 @@
|
||||
// Change between modes by pressing a button.
|
||||
//
|
||||
// Dependencies
|
||||
// * This usermod REQURES the ModeSortUsermod
|
||||
// * This Usermod works best coupled with
|
||||
// FourLineDisplayUsermod.
|
||||
//
|
||||
// If FourLineDisplayUsermod is used the folowing options are also inabled
|
||||
// If FourLineDisplayUsermod is used the folowing options are also enabled
|
||||
//
|
||||
// * main color
|
||||
// * saturation of main color
|
||||
// * display network (long press buttion)
|
||||
//
|
||||
|
||||
#ifdef USERMOD_MODE_SORT
|
||||
#error "Usermod Mode Sort is no longer required. Remove -D USERMOD_MODE_SORT from platformio.ini"
|
||||
#endif
|
||||
|
||||
#ifndef ENCODER_DT_PIN
|
||||
#define ENCODER_DT_PIN 18
|
||||
#endif
|
||||
@ -44,27 +47,90 @@
|
||||
|
||||
// The last UI state, remove color and saturation option if diplay not active(too many options)
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
#define LAST_UI_STATE 6
|
||||
#define LAST_UI_STATE 8
|
||||
#else
|
||||
#define LAST_UI_STATE 4
|
||||
#endif
|
||||
|
||||
// Number of modes at the start of the list to not sort
|
||||
#define MODE_SORT_SKIP_COUNT 1
|
||||
|
||||
// Which list is being sorted
|
||||
static char **listBeingSorted;
|
||||
|
||||
/**
|
||||
* Modes and palettes are stored as strings that
|
||||
* end in a quote character. Compare two of them.
|
||||
* We are comparing directly within either
|
||||
* JSON_mode_names or JSON_palette_names.
|
||||
*/
|
||||
static int re_qstringCmp(const void *ap, const void *bp) {
|
||||
char *a = listBeingSorted[*((byte *)ap)];
|
||||
char *b = listBeingSorted[*((byte *)bp)];
|
||||
int i = 0;
|
||||
do {
|
||||
char aVal = pgm_read_byte_near(a + i);
|
||||
if (aVal >= 97 && aVal <= 122) {
|
||||
// Lowercase
|
||||
aVal -= 32;
|
||||
}
|
||||
char bVal = pgm_read_byte_near(b + i);
|
||||
if (bVal >= 97 && bVal <= 122) {
|
||||
// Lowercase
|
||||
bVal -= 32;
|
||||
}
|
||||
// Relly we shouldn't ever get to '\0'
|
||||
if (aVal == '"' || bVal == '"' || aVal == '\0' || bVal == '\0') {
|
||||
// We're done. one is a substring of the other
|
||||
// or something happenend and the quote didn't stop us.
|
||||
if (aVal == bVal) {
|
||||
// Same value, probably shouldn't happen
|
||||
// with this dataset
|
||||
return 0;
|
||||
}
|
||||
else if (aVal == '"' || aVal == '\0') {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (aVal == bVal) {
|
||||
// Same characters. Move to the next.
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// We're done
|
||||
if (aVal < bVal) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
} while (true);
|
||||
// We shouldn't get here.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
class RotaryEncoderUIUsermod : public Usermod {
|
||||
private:
|
||||
int fadeAmount = 5; // Amount to change every step (brightness)
|
||||
unsigned long currentTime;
|
||||
int8_t fadeAmount = 5; // Amount to change every step (brightness)
|
||||
unsigned long loopTime;
|
||||
unsigned long buttonHoldTIme;
|
||||
|
||||
unsigned long buttonPressedTime = 0;
|
||||
unsigned long buttonWaitTime = 0;
|
||||
bool buttonPressedBefore = false;
|
||||
bool buttonLongPressed = false;
|
||||
|
||||
int8_t pinA = ENCODER_DT_PIN; // DT from encoder
|
||||
int8_t pinB = ENCODER_CLK_PIN; // CLK from encoder
|
||||
int8_t pinC = ENCODER_SW_PIN; // SW from encoder
|
||||
unsigned char select_state = 0; // 0: brightness, 1: effect, 2: effect speed
|
||||
unsigned char button_state = HIGH;
|
||||
unsigned char prev_button_state = HIGH;
|
||||
bool networkShown = false;
|
||||
uint16_t currentHue1 = 6425; // default reboot color
|
||||
byte currentSat1 = 255;
|
||||
|
||||
unsigned char select_state = 0; // 0: brightness, 1: effect, 2: effect speed, ...
|
||||
|
||||
uint16_t currentHue1 = 16; // default boot color
|
||||
byte currentSat1 = 255;
|
||||
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
FourLineDisplayUsermod *display;
|
||||
@ -72,7 +138,16 @@ private:
|
||||
void* display = nullptr;
|
||||
#endif
|
||||
|
||||
// Pointers the start of the mode names within JSON_mode_names
|
||||
char **modes_qstrings = nullptr;
|
||||
|
||||
// Array of mode indexes in alphabetical order.
|
||||
byte *modes_alpha_indexes = nullptr;
|
||||
|
||||
// Pointers the start of the palette names within JSON_palette_names
|
||||
char **palettes_qstrings = nullptr;
|
||||
|
||||
// Array of palette indexes in alphabetical order.
|
||||
byte *palettes_alpha_indexes = nullptr;
|
||||
|
||||
unsigned char Enc_A;
|
||||
@ -85,6 +160,14 @@ private:
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
uint8_t currentCCT = 128;
|
||||
bool isRgbw = false;
|
||||
|
||||
byte presetHigh = 0;
|
||||
byte presetLow = 0;
|
||||
|
||||
bool applyToAll = true;
|
||||
|
||||
bool initDone = false;
|
||||
bool enabled = true;
|
||||
|
||||
@ -94,14 +177,94 @@ private:
|
||||
static const char _DT_pin[];
|
||||
static const char _CLK_pin[];
|
||||
static const char _SW_pin[];
|
||||
static const char _presetHigh[];
|
||||
static const char _presetLow[];
|
||||
static const char _applyToAll[];
|
||||
|
||||
/**
|
||||
* Sort the modes and palettes to the index arrays
|
||||
* modes_alpha_indexes and palettes_alpha_indexes.
|
||||
*/
|
||||
void sortModesAndPalettes() {
|
||||
modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount());
|
||||
modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
|
||||
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
|
||||
|
||||
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount());
|
||||
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount());
|
||||
|
||||
// How many palette names start with '*' and should not be sorted?
|
||||
// (Also skipping the first one, 'Default').
|
||||
int skipPaletteCount = 1;
|
||||
while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount++]) == '*') ;
|
||||
re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount(), skipPaletteCount);
|
||||
}
|
||||
|
||||
byte *re_initIndexArray(int numModes) {
|
||||
byte *indexes = (byte *)malloc(sizeof(byte) * numModes);
|
||||
for (byte i = 0; i < numModes; i++) {
|
||||
indexes[i] = i;
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of mode or palette names from the JSON string.
|
||||
* They don't end in '\0', they end in '"'.
|
||||
*/
|
||||
char **re_findModeStrings(const char json[], int numModes) {
|
||||
char **modeStrings = (char **)malloc(sizeof(char *) * numModes);
|
||||
uint8_t modeIndex = 0;
|
||||
bool insideQuotes = false;
|
||||
// advance past the mark for markLineNum that may exist.
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
bool complete = false;
|
||||
for (size_t i = 0; i < strlen_P(json); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(json + i);
|
||||
if (singleJsonSymbol == '\0') break;
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
if (insideQuotes) {
|
||||
// We have a new mode or palette
|
||||
modeStrings[modeIndex] = (char *)(json + i + 1);
|
||||
}
|
||||
break;
|
||||
case '[':
|
||||
break;
|
||||
case ']':
|
||||
if (!insideQuotes) complete = true;
|
||||
break;
|
||||
case ',':
|
||||
if (!insideQuotes) modeIndex++;
|
||||
default:
|
||||
if (!insideQuotes) break;
|
||||
}
|
||||
if (complete) break;
|
||||
}
|
||||
return modeStrings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort either the modes or the palettes using quicksort.
|
||||
*/
|
||||
void re_sortModes(char **modeNames, byte *indexes, int count, int numSkip) {
|
||||
listBeingSorted = modeNames;
|
||||
qsort(indexes + numSkip, count - numSkip, sizeof(byte), re_qstringCmp);
|
||||
listBeingSorted = nullptr;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
DEBUG_PRINTLN(F("Usermod Rotary Encoder init."));
|
||||
PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) {
|
||||
// BUG: configuring this usermod with conflicting pins
|
||||
@ -117,12 +280,17 @@ public:
|
||||
pinMode(pinA, INPUT_PULLUP);
|
||||
pinMode(pinB, INPUT_PULLUP);
|
||||
pinMode(pinC, INPUT_PULLUP);
|
||||
currentTime = millis();
|
||||
loopTime = currentTime;
|
||||
loopTime = millis();
|
||||
|
||||
ModeSortUsermod *modeSortUsermod = (ModeSortUsermod*) usermods.lookup(USERMOD_ID_MODE_SORT);
|
||||
modes_alpha_indexes = modeSortUsermod->getModesAlphaIndexes();
|
||||
palettes_alpha_indexes = modeSortUsermod->getPalettesAlphaIndexes();
|
||||
for (uint8_t s = 0; s < busses.getNumBusses(); s++) {
|
||||
Bus *bus = busses.getBus(s);
|
||||
if (!bus || bus->getLength()==0) break;
|
||||
isRgbw |= bus->isRgbw();
|
||||
}
|
||||
|
||||
currentCCT = (approximateKelvinFromRGB(RGBW32(col[0], col[1], col[2], col[3])) - 1900) >> 5;
|
||||
|
||||
if (!initDone) sortModesAndPalettes();
|
||||
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
// This Usermod uses FourLineDisplayUsermod for the best experience.
|
||||
@ -140,91 +308,87 @@ public:
|
||||
}
|
||||
|
||||
/*
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected()
|
||||
{
|
||||
//Serial.println("Connected to WiFi!");
|
||||
}
|
||||
|
||||
/*
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*
|
||||
* Tips:
|
||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
||||
*
|
||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||
*
|
||||
* Tips:
|
||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
||||
*
|
||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
void loop()
|
||||
{
|
||||
currentTime = millis(); // get the current elapsed time
|
||||
if (!enabled || strip.isUpdating()) return;
|
||||
unsigned long currentTime = millis(); // get the current elapsed time
|
||||
|
||||
// Initialize effectCurrentIndex and effectPaletteIndex to
|
||||
// current state. We do it here as (at least) effectCurrent
|
||||
// is not yet initialized when setup is called.
|
||||
|
||||
if (!currentEffectAndPaletteInitialized) {
|
||||
findCurrentEffectAndPalette();}
|
||||
findCurrentEffectAndPalette();
|
||||
}
|
||||
|
||||
if(modes_alpha_indexes[effectCurrentIndex] != effectCurrent
|
||||
|| palettes_alpha_indexes[effectPaletteIndex] != effectPalette){
|
||||
if (modes_alpha_indexes[effectCurrentIndex] != effectCurrent || palettes_alpha_indexes[effectPaletteIndex] != effectPalette) {
|
||||
currentEffectAndPaletteInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz
|
||||
{
|
||||
button_state = digitalRead(pinC);
|
||||
if (prev_button_state != button_state)
|
||||
{
|
||||
if (button_state == HIGH && (millis()-buttonHoldTIme < 3000))
|
||||
{
|
||||
prev_button_state = button_state;
|
||||
loopTime = currentTime; // Updates loopTime
|
||||
|
||||
char newState = select_state + 1;
|
||||
if (newState > LAST_UI_STATE) newState = 0;
|
||||
|
||||
bool changedState = true;
|
||||
if (display != nullptr) {
|
||||
switch(newState) {
|
||||
case 0:
|
||||
changedState = changeState(" Brightness", 1, 0, 1);
|
||||
break;
|
||||
case 1:
|
||||
changedState = changeState(" Speed", 1, 4, 2);
|
||||
break;
|
||||
case 2:
|
||||
changedState = changeState(" Intensity", 1 ,8, 3);
|
||||
break;
|
||||
case 3:
|
||||
changedState = changeState(" Color Palette", 2, 0, 4);
|
||||
break;
|
||||
case 4:
|
||||
changedState = changeState(" Effect", 3, 0, 5);
|
||||
break;
|
||||
case 5:
|
||||
changedState = changeState(" Main Color", 255, 255, 7);
|
||||
break;
|
||||
case 6:
|
||||
changedState = changeState(" Saturation", 255, 255, 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (changedState) {
|
||||
select_state = newState;
|
||||
bool buttonPressed = !digitalRead(pinC); //0=pressed, 1=released
|
||||
if (buttonPressed) {
|
||||
if (!buttonPressedBefore) buttonPressedTime = currentTime;
|
||||
buttonPressedBefore = true;
|
||||
if (currentTime-buttonPressedTime > 3000) {
|
||||
if (!buttonLongPressed) displayNetworkInfo(); //long press for network info
|
||||
buttonLongPressed = true;
|
||||
}
|
||||
} else if (!buttonPressed && buttonPressedBefore) {
|
||||
bool doublePress = buttonWaitTime;
|
||||
buttonWaitTime = 0;
|
||||
if (!buttonLongPressed) {
|
||||
if (doublePress) {
|
||||
toggleOnOff();
|
||||
lampUdated();
|
||||
} else {
|
||||
buttonWaitTime = currentTime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_button_state = button_state;
|
||||
networkShown = false;
|
||||
if(!prev_button_state)buttonHoldTIme = millis();
|
||||
}
|
||||
buttonLongPressed = false;
|
||||
buttonPressedBefore = false;
|
||||
}
|
||||
if (buttonWaitTime && currentTime-buttonWaitTime>350 && !buttonPressedBefore) { //same speed as in button.cpp
|
||||
buttonWaitTime = 0;
|
||||
char newState = select_state + 1;
|
||||
bool changedState = true;
|
||||
if (newState > LAST_UI_STATE || (newState == 8 && presetHigh==0 && presetLow == 0)) newState = 0;
|
||||
if (display != nullptr) {
|
||||
switch (newState) {
|
||||
case 0: changedState = changeState(PSTR("Brightness"), 1, 0, 1); break; //1 = sun
|
||||
case 1: changedState = changeState(PSTR("Speed"), 1, 4, 2); break; //2 = skip forward
|
||||
case 2: changedState = changeState(PSTR("Intensity"), 1, 8, 3); break; //3 = fire
|
||||
case 3: changedState = changeState(PSTR("Color Palette"), 2, 0, 4); break; //4 = custom palette
|
||||
case 4: changedState = changeState(PSTR("Effect"), 3, 0, 5); break; //5 = puzzle piece
|
||||
case 5: changedState = changeState(PSTR("Main Color"), 255, 255, 7); break; //7 = brush
|
||||
case 6: changedState = changeState(PSTR("Saturation"), 255, 255, 8); break; //8 = contrast
|
||||
case 7: changedState = changeState(PSTR("CCT"), 255, 255, 10); break; //10 = star
|
||||
case 8: changedState = changeState(PSTR("Preset"), 255, 255, 11); break; //11 = heart
|
||||
}
|
||||
}
|
||||
if (changedState) select_state = newState;
|
||||
}
|
||||
|
||||
if (!prev_button_state && (millis()-buttonHoldTIme > 3000) && !networkShown) displayNetworkInfo(); //long press for network info
|
||||
|
||||
Enc_A = digitalRead(pinA); // Read encoder pins
|
||||
Enc_B = digitalRead(pinB);
|
||||
@ -233,65 +397,39 @@ public:
|
||||
if (Enc_B == LOW) //changes to LOW so that then encoder registers a change at the very end of a pulse
|
||||
{ // B is high so clockwise
|
||||
switch(select_state) {
|
||||
case 0:
|
||||
changeBrightness(true);
|
||||
break;
|
||||
case 1:
|
||||
changeEffectSpeed(true);
|
||||
break;
|
||||
case 2:
|
||||
changeEffectIntensity(true);
|
||||
break;
|
||||
case 3:
|
||||
changePalette(true);
|
||||
break;
|
||||
case 4:
|
||||
changeEffect(true);
|
||||
break;
|
||||
case 5:
|
||||
changeHue(true);
|
||||
break;
|
||||
case 6:
|
||||
changeSat(true);
|
||||
break;
|
||||
case 0: changeBrightness(true); break;
|
||||
case 1: changeEffectSpeed(true); break;
|
||||
case 2: changeEffectIntensity(true); break;
|
||||
case 3: changePalette(true); break;
|
||||
case 4: changeEffect(true); break;
|
||||
case 5: changeHue(true); break;
|
||||
case 6: changeSat(true); break;
|
||||
case 7: changeCCT(true); break;
|
||||
case 8: changePreset(true); break;
|
||||
}
|
||||
}
|
||||
else if (Enc_B == HIGH)
|
||||
{ // B is low so counter-clockwise
|
||||
switch(select_state) {
|
||||
case 0:
|
||||
changeBrightness(false);
|
||||
break;
|
||||
case 1:
|
||||
changeEffectSpeed(false);
|
||||
break;
|
||||
case 2:
|
||||
changeEffectIntensity(false);
|
||||
break;
|
||||
case 3:
|
||||
changePalette(false);
|
||||
break;
|
||||
case 4:
|
||||
changeEffect(false);
|
||||
break;
|
||||
case 5:
|
||||
changeHue(false);
|
||||
break;
|
||||
case 6:
|
||||
changeSat(false);
|
||||
break;
|
||||
case 0: changeBrightness(false); break;
|
||||
case 1: changeEffectSpeed(false); break;
|
||||
case 2: changeEffectIntensity(false); break;
|
||||
case 3: changePalette(false); break;
|
||||
case 4: changeEffect(false); break;
|
||||
case 5: changeHue(false); break;
|
||||
case 6: changeSat(false); break;
|
||||
case 7: changeCCT(false); break;
|
||||
case 8: changePreset(false); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Enc_A_prev = Enc_A; // Store value of A for next time
|
||||
loopTime = currentTime; // Updates loopTime
|
||||
}
|
||||
}
|
||||
|
||||
void displayNetworkInfo(){
|
||||
void displayNetworkInfo() {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->networkOverlay(" NETWORK INFO", 15000);
|
||||
networkShown = true;
|
||||
display->networkOverlay(PSTR("NETWORK INFO"), 10000);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -313,180 +451,293 @@ public:
|
||||
}
|
||||
|
||||
boolean changeState(const char *stateName, byte markedLine, byte markedCol, byte glyph) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display != nullptr) {
|
||||
if (display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return false;
|
||||
}
|
||||
display->overlay(stateName, 750, glyph);
|
||||
display->setMarkLine(markedLine, markedCol);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display != nullptr) {
|
||||
if (display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
display->redraw(true);
|
||||
return false;
|
||||
}
|
||||
display->overlay(stateName, 750, glyph);
|
||||
display->setMarkLine(markedLine, markedCol);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void lampUdated() {
|
||||
//bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette);
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
setValuesFromMainSeg(); //to make transition work on main segment
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
updateInterfaces(CALL_MODE_DIRECT_CHANGE);
|
||||
}
|
||||
|
||||
void changeBrightness(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (increase) bri = (bri + fadeAmount <= 255) ? (bri + fadeAmount) : 255;
|
||||
else bri = (bri - fadeAmount >= 0) ? (bri - fadeAmount) : 0;
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->updateBrightness();
|
||||
#endif
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
bri = max(min((increase ? bri+fadeAmount : bri-fadeAmount), 255), 0);
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->updateBrightness();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void changeEffect(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (increase) effectCurrentIndex = (effectCurrentIndex + 1 >= strip.getModeCount()) ? 0 : (effectCurrentIndex + 1);
|
||||
else effectCurrentIndex = (effectCurrentIndex - 1 < 0) ? (strip.getModeCount() - 1) : (effectCurrentIndex - 1);
|
||||
effectCurrent = modes_alpha_indexes[effectCurrentIndex];
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->showCurrentEffectOrPalette(effectCurrent, JSON_mode_names, 3);
|
||||
#endif
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
effectCurrentIndex = max(min((increase ? effectCurrentIndex+1 : effectCurrentIndex-1), strip.getModeCount()-1), 0);
|
||||
effectCurrent = modes_alpha_indexes[effectCurrentIndex];
|
||||
effectChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
strip.setMode(i, effectCurrent);
|
||||
}
|
||||
} else {
|
||||
//WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
strip.setMode(strip.getMainSegmentId(), effectCurrent);
|
||||
}
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->showCurrentEffectOrPalette(effectCurrent, JSON_mode_names, 3);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void changeEffectSpeed(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (increase) effectSpeed = (effectSpeed + fadeAmount <= 255) ? (effectSpeed + fadeAmount) : 255;
|
||||
else effectSpeed = (effectSpeed - fadeAmount >= 0) ? (effectSpeed - fadeAmount) : 0;
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->updateSpeed();
|
||||
#endif
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
effectSpeed = max(min((increase ? effectSpeed+fadeAmount : effectSpeed-fadeAmount), 255), 0);
|
||||
effectChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.speed = effectSpeed;
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.speed = effectSpeed;
|
||||
}
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->updateSpeed();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void changeEffectIntensity(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (increase) effectIntensity = (effectIntensity + fadeAmount <= 255) ? (effectIntensity + fadeAmount) : 255;
|
||||
else effectIntensity = (effectIntensity - fadeAmount >= 0) ? (effectIntensity - fadeAmount) : 0;
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->updateIntensity();
|
||||
#endif
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
effectIntensity = max(min((increase ? effectIntensity+fadeAmount : effectIntensity-fadeAmount), 255), 0);
|
||||
effectChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.intensity = effectIntensity;
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.intensity = effectIntensity;
|
||||
}
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->updateIntensity();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void changePalette(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (increase) effectPaletteIndex = (effectPaletteIndex + 1 >= strip.getPaletteCount()) ? 0 : (effectPaletteIndex + 1);
|
||||
else effectPaletteIndex = (effectPaletteIndex - 1 < 0) ? (strip.getPaletteCount() - 1) : (effectPaletteIndex - 1);
|
||||
effectPalette = palettes_alpha_indexes[effectPaletteIndex];
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->showCurrentEffectOrPalette(effectPalette, JSON_palette_names, 2);
|
||||
#endif
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
effectPaletteIndex = max(min((increase ? effectPaletteIndex+1 : effectPaletteIndex-1), strip.getPaletteCount()-1), 0);
|
||||
effectPalette = palettes_alpha_indexes[effectPaletteIndex];
|
||||
effectChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.palette = effectPalette;
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.palette = effectPalette;
|
||||
}
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->showCurrentEffectOrPalette(effectPalette, JSON_palette_names, 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void changeHue(bool increase){
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(increase) currentHue1 += 321;
|
||||
else currentHue1 -= 321;
|
||||
colorHStoRGB(currentHue1, currentSat1, col);
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
currentHue1 = max(min((increase ? currentHue1+fadeAmount : currentHue1-fadeAmount), 255), 0);
|
||||
colorHStoRGB(currentHue1*256, currentSat1, col);
|
||||
colorChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||
}
|
||||
lampUdated();
|
||||
}
|
||||
|
||||
void changeSat(bool increase){
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0);
|
||||
colorHStoRGB(currentHue1*256, currentSat1, col);
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||
}
|
||||
lampUdated();
|
||||
}
|
||||
|
||||
if(increase) currentSat1 = (currentSat1 + 5 <= 255 ? (currentSat1 + 5) : 255);
|
||||
else currentSat1 = (currentSat1 - 5 >= 0 ? (currentSat1 - 5) : 0);
|
||||
colorHStoRGB(currentHue1, currentSat1, col);
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
void changePreset(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
if (presetHigh && presetLow && presetHigh > presetLow) {
|
||||
String apireq = F("win&PL=~");
|
||||
if (!increase) apireq += '-';
|
||||
apireq += F("&P1=");
|
||||
apireq += presetLow;
|
||||
apireq += F("&P2=");
|
||||
apireq += presetHigh;
|
||||
handleSet(nullptr, apireq, false);
|
||||
lampUdated();
|
||||
}
|
||||
}
|
||||
|
||||
void changeCCT(bool increase){
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0);
|
||||
// if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.setCCT(currentCCT, i);
|
||||
}
|
||||
// } else {
|
||||
// WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
// seg.setCCT(currentCCT, strip.getMainSegmentId());
|
||||
// }
|
||||
lampUdated();
|
||||
}
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
/*
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
int reading = 20;
|
||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
JsonArray lightArr = user.createNestedArray("Light"); //name
|
||||
lightArr.add(reading); //value
|
||||
lightArr.add(" lux"); //unit
|
||||
}
|
||||
*/
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
int reading = 20;
|
||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
JsonArray lightArr = user.createNestedArray("Light"); //name
|
||||
lightArr.add(reading); //value
|
||||
lightArr.add(" lux"); //unit
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
/*
|
||||
void addToJsonState(JsonObject &root)
|
||||
{
|
||||
//root["user0"] = userVar0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
/*
|
||||
void readFromJsonState(JsonObject &root)
|
||||
{
|
||||
//userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json
|
||||
@ -498,6 +749,9 @@ public:
|
||||
top[FPSTR(_DT_pin)] = pinA;
|
||||
top[FPSTR(_CLK_pin)] = pinB;
|
||||
top[FPSTR(_SW_pin)] = pinC;
|
||||
top[FPSTR(_presetLow)] = presetLow;
|
||||
top[FPSTR(_presetHigh)] = presetHigh;
|
||||
top[FPSTR(_applyToAll)] = applyToAll;
|
||||
DEBUG_PRINTLN(F("Rotary Encoder config saved."));
|
||||
}
|
||||
|
||||
@ -514,14 +768,17 @@ public:
|
||||
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
||||
return false;
|
||||
}
|
||||
int8_t newDTpin = pinA;
|
||||
int8_t newCLKpin = pinB;
|
||||
int8_t newSWpin = pinC;
|
||||
int8_t newDTpin = top[FPSTR(_DT_pin)] | pinA;
|
||||
int8_t newCLKpin = top[FPSTR(_CLK_pin)] | pinB;
|
||||
int8_t newSWpin = top[FPSTR(_SW_pin)] | pinC;
|
||||
|
||||
enabled = top[FPSTR(_enabled)] | enabled;
|
||||
newDTpin = top[FPSTR(_DT_pin)] | newDTpin;
|
||||
newCLKpin = top[FPSTR(_CLK_pin)] | newCLKpin;
|
||||
newSWpin = top[FPSTR(_SW_pin)] | newSWpin;
|
||||
presetHigh = top[FPSTR(_presetHigh)] | presetHigh;
|
||||
presetLow = top[FPSTR(_presetLow)] | presetLow;
|
||||
presetHigh = MIN(250,MAX(0,presetHigh));
|
||||
presetLow = MIN(250,MAX(0,presetLow));
|
||||
|
||||
enabled = top[FPSTR(_enabled)] | enabled;
|
||||
applyToAll = top[FPSTR(_applyToAll)] | applyToAll;
|
||||
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
if (!initDone) {
|
||||
@ -548,7 +805,7 @@ public:
|
||||
}
|
||||
}
|
||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
||||
return !top[FPSTR(_enabled)].isNull();
|
||||
return !top[FPSTR(_applyToAll)].isNull();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -562,8 +819,11 @@ public:
|
||||
};
|
||||
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
const char RotaryEncoderUIUsermod::_name[] PROGMEM = "Rotary-Encoder";
|
||||
const char RotaryEncoderUIUsermod::_enabled[] PROGMEM = "enabled";
|
||||
const char RotaryEncoderUIUsermod::_DT_pin[] PROGMEM = "DT-pin";
|
||||
const char RotaryEncoderUIUsermod::_CLK_pin[] PROGMEM = "CLK-pin";
|
||||
const char RotaryEncoderUIUsermod::_SW_pin[] PROGMEM = "SW-pin";
|
||||
const char RotaryEncoderUIUsermod::_name[] PROGMEM = "Rotary-Encoder";
|
||||
const char RotaryEncoderUIUsermod::_enabled[] PROGMEM = "enabled";
|
||||
const char RotaryEncoderUIUsermod::_DT_pin[] PROGMEM = "DT-pin";
|
||||
const char RotaryEncoderUIUsermod::_CLK_pin[] PROGMEM = "CLK-pin";
|
||||
const char RotaryEncoderUIUsermod::_SW_pin[] PROGMEM = "SW-pin";
|
||||
const char RotaryEncoderUIUsermod::_presetHigh[] PROGMEM = "preset-high";
|
||||
const char RotaryEncoderUIUsermod::_presetLow[] PROGMEM = "preset-low";
|
||||
const char RotaryEncoderUIUsermod::_applyToAll[] PROGMEM = "apply-2-all-seg";
|
||||
|
@ -23,6 +23,8 @@ void updateBlynk();
|
||||
|
||||
//button.cpp
|
||||
void shortPressAction(uint8_t b=0);
|
||||
void longPressAction(uint8_t b=0);
|
||||
void doublePressAction(uint8_t b=0);
|
||||
bool isButtonPressed(uint8_t b=0);
|
||||
void handleButton();
|
||||
void handleIO();
|
||||
@ -191,7 +193,9 @@ void handlePlaylist();
|
||||
|
||||
//presets.cpp
|
||||
bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE);
|
||||
inline bool applyTemporaryPreset() {return applyPreset(255);};
|
||||
void savePreset(byte index, bool persist = true, const char* pname = nullptr, JsonObject saveobj = JsonObject());
|
||||
inline void saveTemporaryPreset() {savePreset(255, false);};
|
||||
void deletePreset(byte index);
|
||||
|
||||
//set.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user