Merge branch 'MoonModules:mdev' into downsample4x
This commit is contained in:
@@ -60,9 +60,9 @@ class UsermodBattery : public Usermod
|
||||
bool initializing = true;
|
||||
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
static const char _name[];
|
||||
// static const char _name[];
|
||||
static const char _readInterval[];
|
||||
static const char _enabled[];
|
||||
// static const char _enabled[];
|
||||
static const char _threshold[];
|
||||
static const char _preset[];
|
||||
static const char _duration[];
|
||||
@@ -117,6 +117,7 @@ class UsermodBattery : public Usermod
|
||||
float readVoltage()
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if ((batteryPin <0) || !pinManager.isPinAnalog(batteryPin)) return(-1.0f); // WLEDMM avoid reading from invalid pin
|
||||
// use calibrated millivolts analogread on esp32 (150 mV ~ 2450 mV default attentuation) and divide by 1000 to get from milivolts to volts and multiply by voltage multiplier and apply calibration value
|
||||
return (analogReadMilliVolts(batteryPin) / 1000.0f) * voltageMultiplier + calibration;
|
||||
#else
|
||||
@@ -127,6 +128,7 @@ class UsermodBattery : public Usermod
|
||||
|
||||
public:
|
||||
//Functions called by WLED
|
||||
UsermodBattery(const char *name, bool enabled):Usermod(name, enabled) {} //WLEDMM: this shouldn't be necessary (passthrough of constructor), maybe because Usermod is an abstract class
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
@@ -134,10 +136,11 @@ class UsermodBattery : public Usermod
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
if (!enabled) return; // WLEDMM
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
bool success = false;
|
||||
DEBUG_PRINTLN(F("Allocating battery pin..."));
|
||||
if (batteryPin >= 0 && digitalPinToAnalogChannel(batteryPin) >= 0)
|
||||
if ((batteryPin >= 0) && (digitalPinToAnalogChannel(batteryPin) >= 0))
|
||||
if (pinManager.allocatePin(batteryPin, false, PinOwner::UM_Battery)) {
|
||||
DEBUG_PRINTLN(F("Battery pin allocation succeeded."));
|
||||
success = true;
|
||||
@@ -145,8 +148,9 @@ class UsermodBattery : public Usermod
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
DEBUG_PRINTLN(F("Battery pin allocation failed."));
|
||||
USER_PRINTLN(F("Battery pin allocation failed."));
|
||||
batteryPin = -1; // allocation failed
|
||||
enabled = false;
|
||||
} else {
|
||||
pinMode(batteryPin, INPUT);
|
||||
}
|
||||
@@ -178,7 +182,13 @@ class UsermodBattery : public Usermod
|
||||
*/
|
||||
void loop()
|
||||
{
|
||||
if(strip.isUpdating()) return;
|
||||
// WLEDMM begin
|
||||
if (!enabled) return;
|
||||
if (batteryPin < 0) return;
|
||||
unsigned long currentTime = millis(); // get the current elapsed time
|
||||
if (strip.isUpdating() && (currentTime - lastTime < 30000)) return; // WLEDMM: be nice
|
||||
lastTime = currentTime;
|
||||
// WLEDMM end
|
||||
|
||||
lowPowerIndicator();
|
||||
|
||||
@@ -252,6 +262,7 @@ class UsermodBattery : public Usermod
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
if (!enabled) return; // WLEDMM
|
||||
if (batteryPin < 0) {
|
||||
JsonArray infoVoltage = user.createNestedArray(F("Battery voltage"));
|
||||
infoVoltage.add(F("n/a"));
|
||||
@@ -360,6 +371,8 @@ class UsermodBattery : public Usermod
|
||||
void addToConfig(JsonObject& root)
|
||||
{
|
||||
JsonObject battery = root.createNestedObject(FPSTR(_name)); // usermodname
|
||||
battery[F("enabled")] = enabled; // WLEDMM
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
battery[F("pin")] = batteryPin;
|
||||
#endif
|
||||
@@ -373,11 +386,11 @@ class UsermodBattery : public Usermod
|
||||
battery[FPSTR(_readInterval)] = readingInterval;
|
||||
|
||||
JsonObject ao = battery.createNestedObject(F("auto-off")); // auto off section
|
||||
ao[FPSTR(_enabled)] = autoOffEnabled;
|
||||
ao[F("auto-off-enabled")] = autoOffEnabled;
|
||||
ao[FPSTR(_threshold)] = autoOffThreshold;
|
||||
|
||||
JsonObject lp = battery.createNestedObject(F("indicator")); // low power section
|
||||
lp[FPSTR(_enabled)] = lowPowerIndicatorEnabled;
|
||||
lp[F("indicator-enabled")] = lowPowerIndicatorEnabled;
|
||||
lp[FPSTR(_preset)] = lowPowerIndicatorPreset; // dropdown trickery (String)lowPowerIndicatorPreset;
|
||||
lp[FPSTR(_threshold)] = lowPowerIndicatorThreshold;
|
||||
lp[FPSTR(_duration)] = lowPowerIndicatorDuration;
|
||||
@@ -436,6 +449,10 @@ class UsermodBattery : public Usermod
|
||||
#endif
|
||||
|
||||
JsonObject battery = root[FPSTR(_name)];
|
||||
|
||||
bool configComplete = !battery.isNull(); // WLEDMM
|
||||
configComplete &= getJsonValue(battery[F("enabled")], enabled, true); // WLEDMM
|
||||
|
||||
if (battery.isNull())
|
||||
{
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
@@ -455,11 +472,11 @@ class UsermodBattery : public Usermod
|
||||
setReadingInterval(battery[FPSTR(_readInterval)] | readingInterval);
|
||||
|
||||
JsonObject ao = battery[F("auto-off")];
|
||||
setAutoOffEnabled(ao[FPSTR(_enabled)] | autoOffEnabled);
|
||||
setAutoOffEnabled(ao[F("auto-off-enabled")] | autoOffEnabled); // WLEDMM
|
||||
setAutoOffThreshold(ao[FPSTR(_threshold)] | autoOffThreshold);
|
||||
|
||||
JsonObject lp = battery[F("indicator")];
|
||||
setLowPowerIndicatorEnabled(lp[FPSTR(_enabled)] | lowPowerIndicatorEnabled);
|
||||
setLowPowerIndicatorEnabled(lp[F("indicator-enabled")] | lowPowerIndicatorEnabled); // WLEDMM
|
||||
setLowPowerIndicatorPreset(lp[FPSTR(_preset)] | lowPowerIndicatorPreset); // dropdown trickery (int)lp["preset"]
|
||||
setLowPowerIndicatorThreshold(lp[FPSTR(_threshold)] | lowPowerIndicatorThreshold);
|
||||
lowPowerIndicatorReactivationThreshold = lowPowerIndicatorThreshold+10;
|
||||
@@ -490,7 +507,7 @@ class UsermodBattery : public Usermod
|
||||
}
|
||||
#endif
|
||||
|
||||
return !battery[FPSTR(_readInterval)].isNull();
|
||||
return configComplete && (!battery[FPSTR(_readInterval)].isNull()); // WLEDMM
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -780,9 +797,9 @@ class UsermodBattery : public Usermod
|
||||
};
|
||||
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
const char UsermodBattery::_name[] PROGMEM = "Battery";
|
||||
// const char UsermodBattery::_name[] PROGMEM = "Battery";
|
||||
const char UsermodBattery::_readInterval[] PROGMEM = "interval";
|
||||
const char UsermodBattery::_enabled[] PROGMEM = "enabled";
|
||||
//const char UsermodBattery::_enabled[] PROGMEM = "enabled";
|
||||
const char UsermodBattery::_threshold[] PROGMEM = "threshold";
|
||||
const char UsermodBattery::_preset[] PROGMEM = "preset";
|
||||
const char UsermodBattery::_duration[] PROGMEM = "duration";
|
||||
|
||||
@@ -8,21 +8,25 @@
|
||||
|
||||
#define RTC_DELTA 2 // only modify RTC time if delta exceeds this number of seconds
|
||||
|
||||
//Connect DS1307 to standard I2C pins (ESP32: GPIO 21 (SDA)/GPIO 22 (SCL))
|
||||
//Connect DS1307 or DS3231 to standard I2C pins (ESP32: GPIO 21 (SDA)/GPIO 22 (SCL))
|
||||
|
||||
class RTCUsermod : public Usermod {
|
||||
private:
|
||||
unsigned long lastTime = 0;
|
||||
bool disabled = false;
|
||||
bool RTCfound = false; // WLEDMM to prevent errors after anabling the usermod (Wire.cpp:526] write(): NULL TX buffer pointer)
|
||||
public:
|
||||
|
||||
RTCUsermod(const char *name, bool enabled):Usermod(name, enabled) {} //WLEDMM: this shouldn't be necessary (passthrough of constructor), maybe because Usermod is an abstract class
|
||||
|
||||
void setup() {
|
||||
RTCfound = false; // WLEDMM
|
||||
PinManagerPinType pins[2] = { { i2c_scl, true }, { i2c_sda, true } };
|
||||
if (pins[1].pin < 0 || pins[0].pin < 0) { disabled=true; return; } //WLEDMM bugfix - ensure that "final" GPIO are valid and no "-1" sneaks trough
|
||||
if (pins[1].pin < 0 || pins[0].pin < 0) { enabled=false; return; } //WLEDMM bugfix - ensure that "final" GPIO are valid and no "-1" sneaks trough
|
||||
if (!enabled) { DEBUG_PRINTLN(F("RTC usermod not enabled.")); return; }
|
||||
|
||||
// WLEDMM join hardware I2C
|
||||
if (!pinManager.joinWire()) { // WLEDMM - this allocates global I2C pins, then starts Wire - if not started previously
|
||||
disabled = true;
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -40,20 +44,31 @@ class RTCUsermod : public Usermod {
|
||||
updateLocalTime();
|
||||
USER_PRINTLN(F("Localtime updated from RTC."));
|
||||
} else {
|
||||
if (!RTC.chipPresent()) disabled = true; //don't waste time if H/W error
|
||||
if (!RTC.chipPresent()) {
|
||||
enabled = false; //don't waste time if H/W error
|
||||
USER_PRINTLN(F("RTC board not present."));
|
||||
}
|
||||
}
|
||||
if (enabled) RTCfound = true; // WLEDMM
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (strip.isUpdating()) return;
|
||||
if (!disabled && toki.isTick()) {
|
||||
// WLEDMM begin
|
||||
if (!enabled) return;
|
||||
if (!RTCfound) return; // WLEDMM
|
||||
unsigned long currentTime = millis(); // get the current elapsed time
|
||||
if (strip.isUpdating() && (currentTime - lastTime < 10000)) return; // WLEDMM: be nice
|
||||
// WLEDMM end
|
||||
|
||||
if (enabled && toki.isTick()) { // WLEDMM
|
||||
time_t t = toki.second();
|
||||
lastTime = millis(); // WLEDMM
|
||||
|
||||
if (abs(t - RTC.get())> RTC_DELTA) { // WLEDMM only consider time diffs > 2 seconds
|
||||
if ( (toki.getTimeSource() == TOKI_TS_NTP)
|
||||
||( (toki.getTimeSource() != TOKI_TS_NONE) && (toki.getTimeSource() != TOKI_TS_RTC)
|
||||
&& (toki.getTimeSource() != TOKI_TS_BAD) && (toki.getTimeSource() != TOKI_TS_UDP_SEC) && (toki.getTimeSource() != TOKI_TS_UDP)))
|
||||
{ // WLEMM update RTC if we have a reliable time source
|
||||
{ // WLEDMM update RTC if we have a reliable time source
|
||||
RTC.set(t); //set RTC to NTP/UI-provided value - WLEDMM allow up to 3 sec deviation
|
||||
USER_PRINTLN(F("RTC updated using localtime."));
|
||||
} else {
|
||||
|
||||
@@ -449,9 +449,9 @@ void FFTcode(void * parameter)
|
||||
}
|
||||
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)|| defined(SR_STATS)
|
||||
// timing
|
||||
uint64_t start = esp_timer_get_time();
|
||||
bool haveDoneFFT = false; // indicates if second measurement (FFT time) is valid
|
||||
|
||||
static uint64_t lastCycleStart = 0;
|
||||
static uint64_t lastLastTime = 0;
|
||||
if ((lastCycleStart > 0) && (lastCycleStart < start)) { // filter out overflows
|
||||
@@ -466,6 +466,14 @@ void FFTcode(void * parameter)
|
||||
if (audioSource) audioSource->getSamples(vReal, samplesFFT);
|
||||
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)|| defined(SR_STATS)
|
||||
// debug info in case that stack usage changes
|
||||
static unsigned int minStackFree = UINT32_MAX;
|
||||
unsigned int stackFree = uxTaskGetStackHighWaterMark(NULL);
|
||||
if (minStackFree > stackFree) {
|
||||
minStackFree = stackFree;
|
||||
DEBUGSR_PRINTF("|| %-9s min free stack %d\n", pcTaskGetTaskName(NULL), minStackFree); //WLEDMM
|
||||
}
|
||||
// timing
|
||||
if (start < esp_timer_get_time()) { // filter out overflows
|
||||
uint64_t sampleTimeInMillis = (esp_timer_get_time() - start +5ULL) / 10ULL; // "+5" to ensure proper rounding
|
||||
sampleTime = (sampleTimeInMillis*3 + sampleTime*7)/10.0; // smooth
|
||||
@@ -715,6 +723,7 @@ void FFTcode(void * parameter)
|
||||
postProcessFFTResults((fabsf(volumeSmth)>0.25f)? true : false , NUM_GEQ_CHANNELS); // this function modifies fftCalc, fftAvg and fftResult
|
||||
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)|| defined(SR_STATS)
|
||||
// timing
|
||||
static uint64_t lastLastFFT = 0;
|
||||
if (haveDoneFFT && (start < esp_timer_get_time())) { // filter out overflows
|
||||
uint64_t fftTimeInMillis = ((esp_timer_get_time() - start) +5ULL) / 10ULL; // "+5" to ensure proper rounding
|
||||
@@ -1678,7 +1687,13 @@ class AudioReactive : public Usermod {
|
||||
//useInputFilter = 0; // in case you need to disable low-cut software filtering
|
||||
audioSource = new ES7243(SAMPLE_RATE, BLOCK_SIZE);
|
||||
delay(100);
|
||||
if (audioSource) audioSource->initialize(sdaPin, sclPin, i2swsPin, i2ssdPin, i2sckPin, mclkPin);
|
||||
// WLEDMM align global pins
|
||||
if ((sdaPin >= 0) && (i2c_sda < 0)) i2c_sda = sdaPin; // copy usermod prefs into globals (if globals not defined)
|
||||
if ((sclPin >= 0) && (i2c_scl < 0)) i2c_scl = sclPin;
|
||||
if (i2c_sda >= 0) sdaPin = -1; // -1 = use global
|
||||
if (i2c_scl >= 0) sclPin = -1;
|
||||
|
||||
if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
|
||||
break;
|
||||
case 3:
|
||||
DEBUGSR_PRINT(F("AR: SPH0645 Microphone - ")); DEBUGSR_PRINTLN(F(I2S_MIC_CHANNEL_TEXT));
|
||||
@@ -1710,11 +1725,21 @@ class AudioReactive : public Usermod {
|
||||
break;
|
||||
#endif
|
||||
case 6:
|
||||
DEBUGSR_PRINTLN(F("AR: ES8388 Source"));
|
||||
#ifdef use_es8388_mic
|
||||
DEBUGSR_PRINTLN(F("AR: ES8388 Source (Mic)"));
|
||||
#else
|
||||
DEBUGSR_PRINTLN(F("AR: ES8388 Source (Line-In)"));
|
||||
#endif
|
||||
audioSource = new ES8388Source(SAMPLE_RATE, BLOCK_SIZE, 1.0f);
|
||||
//useInputFilter = 0; // to disable low-cut software filtering and restore previous behaviour
|
||||
delay(100);
|
||||
if (audioSource) audioSource->initialize(sdaPin, sclPin, i2swsPin, i2ssdPin, i2sckPin, mclkPin);
|
||||
// WLEDMM align global pins
|
||||
if ((sdaPin >= 0) && (i2c_sda < 0)) i2c_sda = sdaPin; // copy usermod prefs into globals (if globals not defined)
|
||||
if ((sclPin >= 0) && (i2c_scl < 0)) i2c_scl = sclPin;
|
||||
if (i2c_sda >= 0) sdaPin = -1; // -1 = use global
|
||||
if (i2c_scl >= 0) sclPin = -1;
|
||||
|
||||
if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
|
||||
break;
|
||||
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -1758,6 +1783,10 @@ class AudioReactive : public Usermod {
|
||||
DEBUGSR_PRINT(F("AR: init done, enabled = "));
|
||||
DEBUGSR_PRINTLN(enabled ? F("true.") : F("false."));
|
||||
USER_FLUSH();
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(SR_DEBUG)
|
||||
DEBUGSR_PRINTF("|| %-9s min free stack %d\n", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); //WLEDMM
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1788,6 +1817,10 @@ class AudioReactive : public Usermod {
|
||||
DEBUGSR_PRINTLN(udpSyncConnected ? F("AR connected(): UDP: connected to WIFI.") : F("AR connected(): UDP is disconnected (Wifi)."));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(SR_DEBUG)
|
||||
DEBUGSR_PRINTF("|| %-9s min free stack %d\n", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); //WLEDMM
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1844,6 +1877,15 @@ class AudioReactive : public Usermod {
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if (!audioSource->isInitialized()) disableSoundProcessing = true; // no audio source
|
||||
|
||||
#ifdef SR_DEBUG
|
||||
// debug info in case that task stack usage changes
|
||||
static unsigned int minLoopStackFree = UINT32_MAX;
|
||||
unsigned int stackFree = uxTaskGetStackHighWaterMark(NULL);
|
||||
if (minLoopStackFree > stackFree) {
|
||||
minLoopStackFree = stackFree;
|
||||
DEBUGSR_PRINTF("|| %-9s min free stack %d\n", pcTaskGetTaskName(NULL), minLoopStackFree); //WLEDMM
|
||||
}
|
||||
#endif
|
||||
|
||||
// Only run the sampling code IF we're not in Receive mode or realtime mode
|
||||
if (!(audioSyncEnabled & 0x02) && !disableSoundProcessing) {
|
||||
@@ -2040,6 +2082,10 @@ class AudioReactive : public Usermod {
|
||||
micDataReal = 0.0f; // just to be sure
|
||||
if (enabled) disableSoundProcessing = false;
|
||||
updateIsRunning = init;
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(SR_DEBUG)
|
||||
DEBUGSR_PRINTF("|| %-9s min free stack %d\n", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); //WLEDMM
|
||||
#endif
|
||||
}
|
||||
|
||||
#else // reduced function for 8266
|
||||
@@ -2336,6 +2382,11 @@ class AudioReactive : public Usermod {
|
||||
|
||||
JsonObject dmic = top.createNestedObject(FPSTR(_digitalmic));
|
||||
dmic[F("type")] = dmType;
|
||||
// WLEDMM: align with globals I2C pins
|
||||
if ((dmType == 2) || (dmType == 6)) { // only for ES7243 and ES8388
|
||||
if (i2c_sda >= 0) sdaPin = -1; // -1 = use global
|
||||
if (i2c_scl >= 0) sclPin = -1; // -1 = use global
|
||||
}
|
||||
JsonArray pinArray = dmic.createNestedArray("pin");
|
||||
pinArray.add(i2ssdPin);
|
||||
pinArray.add(i2swsPin);
|
||||
|
||||
@@ -126,7 +126,7 @@ class AudioSource {
|
||||
This function needs to take care of anything that needs to be done
|
||||
before samples can be obtained from the microphone.
|
||||
*/
|
||||
virtual void initialize(int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) = 0;
|
||||
virtual void initialize(int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) = 0;
|
||||
|
||||
/* Deinitialize
|
||||
Release all resources and deactivate any functionality that is used
|
||||
@@ -206,7 +206,8 @@ class I2SSource : public AudioSource {
|
||||
};
|
||||
}
|
||||
|
||||
virtual void initialize(int8_t i2swsPin = I2S_PIN_NO_CHANGE, int8_t i2ssdPin = I2S_PIN_NO_CHANGE, int8_t i2sckPin = I2S_PIN_NO_CHANGE, int8_t mclkPin = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
virtual void initialize(int8_t i2swsPin = I2S_PIN_NO_CHANGE, int8_t i2ssdPin = I2S_PIN_NO_CHANGE, int8_t i2sckPin = I2S_PIN_NO_CHANGE, int8_t mclkPin = I2S_PIN_NO_CHANGE) {
|
||||
DEBUGSR_PRINTLN("I2SSource:: initialize().");
|
||||
if (i2swsPin != I2S_PIN_NO_CHANGE && i2ssdPin != I2S_PIN_NO_CHANGE) {
|
||||
if (!pinManager.allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) ||
|
||||
!pinManager.allocatePin(i2ssdPin, false, PinOwner::UM_Audioreactive)) { // #206
|
||||
@@ -444,19 +445,14 @@ class ES7243 : public I2SSource {
|
||||
private:
|
||||
// I2C initialization functions for ES7243
|
||||
void _es7243I2cBegin() {
|
||||
bool i2c_initialized = Wire.begin(pin_ES7243_SDA, pin_ES7243_SCL, 100000U);
|
||||
if (i2c_initialized == false) {
|
||||
ERRORSR_PRINTLN(F("AR: ES7243 failed to initialize I2C bus driver."));
|
||||
}
|
||||
Wire.setClock(100000);
|
||||
}
|
||||
|
||||
void _es7243I2cWrite(uint8_t reg, uint8_t val) {
|
||||
#ifndef ES7243_ADDR
|
||||
Wire.beginTransmission(0x13);
|
||||
#define ES7243_ADDR 0x13 // default address
|
||||
#else
|
||||
#ifndef ES7243_ADDR
|
||||
#define ES7243_ADDR 0x13 // default address
|
||||
#endif
|
||||
Wire.beginTransmission(ES7243_ADDR);
|
||||
#endif
|
||||
Wire.write((uint8_t)reg);
|
||||
Wire.write((uint8_t)val);
|
||||
uint8_t i2cErr = Wire.endTransmission(); // i2cErr == 0 means OK
|
||||
@@ -481,53 +477,30 @@ public:
|
||||
_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT;
|
||||
};
|
||||
|
||||
void initialize(int8_t sdaPin, int8_t sclPin, int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
|
||||
// check that pins are valid
|
||||
if ((sdaPin < 0) || (sclPin < 0)) {
|
||||
ERRORSR_PRINTF("\nAR: invalid ES7243 I2C pins: SDA=%d, SCL=%d\n", sdaPin, sclPin);
|
||||
return;
|
||||
}
|
||||
void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
|
||||
DEBUGSR_PRINTLN("ES7243:: initialize();");
|
||||
|
||||
if ((i2c_sda < 0) || (i2c_scl < 0)) { // check that global I2C pins are not "undefined"
|
||||
// if ((i2sckPin < 0) || (mclkPin < 0)) { // WLEDMM not sure if this check is needed here, too
|
||||
// ERRORSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
|
||||
// return;
|
||||
// }
|
||||
if ((i2c_sda < 0) || (i2c_scl < 0)) { // check that global I2C pins are not "undefined"
|
||||
ERRORSR_PRINTF("\nAR: invalid ES7243 global I2C pins: SDA=%d, SCL=%d\n", i2c_sda, i2c_scl);
|
||||
return;
|
||||
}
|
||||
if (!pinManager.joinWire()) { // WLEDMM specific: start I2C with globally defined pins
|
||||
if (!pinManager.joinWire(i2c_sda, i2c_scl)) { // WLEDMM specific: start I2C with globally defined pins
|
||||
ERRORSR_PRINTF("\nAR: failed to join I2C bus with SDA=%d, SCL=%d\n", i2c_sda, i2c_scl);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((i2sckPin < 0) || (mclkPin < 0)) {
|
||||
ERRORSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reserve SDA and SCL pins of the I2C interface
|
||||
PinManagerPinType es7243Pins[2] = { { sdaPin, true }, { sclPin, true } };
|
||||
if (!pinManager.allocateMultiplePins(es7243Pins, 2, PinOwner::HW_I2C)) {
|
||||
pinManager.deallocateMultiplePins(es7243Pins, 2, PinOwner::HW_I2C);
|
||||
ERRORSR_PRINTF("\nAR: Failed to allocate ES7243 I2C pins: SDA=%d, SCL=%d\n", sdaPin, sclPin);
|
||||
return;
|
||||
}
|
||||
|
||||
pin_ES7243_SDA = sdaPin;
|
||||
pin_ES7243_SCL = sclPin;
|
||||
|
||||
// First route mclk, then configure ADC over I2C, then configure I2S
|
||||
_es7243InitAdc();
|
||||
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
|
||||
}
|
||||
|
||||
void deinitialize() {
|
||||
// Release SDA and SCL pins of the I2C interface
|
||||
PinManagerPinType es7243Pins[2] = { { pin_ES7243_SDA, true }, { pin_ES7243_SCL, true } };
|
||||
pinManager.deallocateMultiplePins(es7243Pins, 2, PinOwner::HW_I2C);
|
||||
I2SSource::deinitialize();
|
||||
}
|
||||
|
||||
private:
|
||||
int8_t pin_ES7243_SDA;
|
||||
int8_t pin_ES7243_SCL;
|
||||
};
|
||||
|
||||
/* ES8388 Sound Modude
|
||||
@@ -538,19 +511,14 @@ class ES8388Source : public I2SSource {
|
||||
private:
|
||||
// I2C initialization functions for ES8388
|
||||
void _es8388I2cBegin() {
|
||||
bool i2c_initialized = Wire.begin(pin_ES8388_SDA, pin_ES8388_SCL, 100000U);
|
||||
if (i2c_initialized == false) {
|
||||
ERRORSR_PRINTLN(F("AR: ES8388 failed to initialize I2C bus driver."));
|
||||
}
|
||||
Wire.setClock(100000);
|
||||
}
|
||||
|
||||
void _es8388I2cWrite(uint8_t reg, uint8_t val) {
|
||||
#ifndef ES8388_ADDR
|
||||
Wire.beginTransmission(0x10);
|
||||
#define ES8388_ADDR 0x10 // default address
|
||||
#else
|
||||
#ifndef ES8388_ADDR
|
||||
#define ES8388_ADDR 0x10 // default address
|
||||
#endif
|
||||
Wire.beginTransmission(ES8388_ADDR);
|
||||
#endif
|
||||
Wire.write((uint8_t)reg);
|
||||
Wire.write((uint8_t)val);
|
||||
uint8_t i2cErr = Wire.endTransmission(); // i2cErr == 0 means OK
|
||||
@@ -637,58 +605,34 @@ class ES8388Source : public I2SSource {
|
||||
_config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
|
||||
};
|
||||
|
||||
void initialize(int8_t sdaPin, int8_t sclPin, int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
|
||||
void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
|
||||
DEBUGSR_PRINTLN("ES8388Source:: initialize();");
|
||||
|
||||
// if ((i2sckPin < 0) || (mclkPin < 0)) { // WLEDMM not sure if this check is needed here, too
|
||||
// ERRORSR_PRINTF("\nAR: invalid I2S ES8388 pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
|
||||
// return;
|
||||
// }
|
||||
// BUG: "use global I2C pins" are valid as -1, and -1 is seen as invalid here.
|
||||
// Workaround: Set I2C pins here, which will also set them globally.
|
||||
// Bug also exists in ES7243.
|
||||
|
||||
// check that pins are valid
|
||||
if ((sdaPin < 0) || (sclPin < 0)) {
|
||||
ERRORSR_PRINTF("\nAR: invalid ES8388 I2C pins: SDA=%d, SCL=%d\n", sdaPin, sclPin);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((i2c_sda < 0) || (i2c_scl < 0)) { // check that global I2C pins are not "undefined"
|
||||
ERRORSR_PRINTF("\nAR: invalid ES8388 global I2C pins: SDA=%d, SCL=%d\n", i2c_sda, i2c_scl);
|
||||
return;
|
||||
}
|
||||
if (!pinManager.joinWire()) { // WLEDMM specific: start I2C with globally defined pins
|
||||
if (!pinManager.joinWire(i2c_sda, i2c_scl)) { // WLEDMM specific: start I2C with globally defined pins
|
||||
ERRORSR_PRINTF("\nAR: failed to join I2C bus with SDA=%d, SCL=%d\n", i2c_sda, i2c_scl);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((i2sckPin < 0) || (mclkPin < 0)) {
|
||||
ERRORSR_PRINTF("\nAR: invalid I2S pin: SCK=%d, MCLK=%d\n", i2sckPin, mclkPin);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reserve SDA and SCL pins of the I2C interface
|
||||
PinManagerPinType es8388Pins[2] = { { sdaPin, true }, { sclPin, true } };
|
||||
if (!pinManager.allocateMultiplePins(es8388Pins, 2, PinOwner::HW_I2C)) {
|
||||
pinManager.deallocateMultiplePins(es8388Pins, 2, PinOwner::HW_I2C);
|
||||
ERRORSR_PRINTF("\nAR: Failed to allocate ES8388 I2C pins: SDA=%d, SCL=%d\n", sdaPin, sclPin);
|
||||
return;
|
||||
}
|
||||
|
||||
pin_ES8388_SDA = sdaPin;
|
||||
pin_ES8388_SCL = sclPin;
|
||||
|
||||
// First route mclk, then configure ADC over I2C, then configure I2S
|
||||
_es8388InitAdc();
|
||||
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
|
||||
}
|
||||
|
||||
void deinitialize() {
|
||||
// Release SDA and SCL pins of the I2C interface
|
||||
PinManagerPinType es8388Pins[2] = { { pin_ES8388_SDA, true }, { pin_ES8388_SCL, true } };
|
||||
pinManager.deallocateMultiplePins(es8388Pins, 2, PinOwner::HW_I2C);
|
||||
I2SSource::deinitialize();
|
||||
}
|
||||
|
||||
private:
|
||||
int8_t pin_ES8388_SDA;
|
||||
int8_t pin_ES8388_SCL;
|
||||
};
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
|
||||
@@ -731,7 +675,8 @@ class I2SAdcSource : public I2SSource {
|
||||
/* identify Audiosource type - I2S-ADC*/
|
||||
AudioSourceType getType(void) {return(Type_I2SAdc);}
|
||||
|
||||
void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
DEBUGSR_PRINTLN("I2SAdcSource:: initialize().");
|
||||
_myADCchannel = 0x0F;
|
||||
if(!pinManager.allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) {
|
||||
ERRORSR_PRINTF("failed to allocate GPIO for audio analog input: %d\n", audioPin);
|
||||
@@ -902,7 +847,8 @@ class SPH0654 : public I2SSource {
|
||||
I2SSource(sampleRate, blockSize, sampleScale, i2sMaster)
|
||||
{}
|
||||
|
||||
void initialize(uint8_t i2swsPin, uint8_t i2ssdPin, uint8_t i2sckPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
void initialize(int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
DEBUGSR_PRINTLN("SPH0654:: initialize();");
|
||||
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin);
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// these registers are only existing in "classic" ESP32
|
||||
|
||||
@@ -5303,6 +5303,7 @@ uint16_t mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams.
|
||||
oldSpawnColor = SEGMENT.getPixelColorXY(SEGENV.aux0, SEGENV.aux1); // find color of previous spawns
|
||||
SEGENV.aux1 ++; // our sample pixel will be one row down the next time
|
||||
}
|
||||
if ((oldSpawnColor == CRGB::Black) || (oldSpawnColor == trailColor)) oldSpawnColor = spawnColor; // reject "black", as it would mean that ALL pixels create trails
|
||||
|
||||
// move pixels one row down. Falling codes keep color and add trail pixels; all others pixels are faded
|
||||
for (int row=rows-1; row>=0; row--) {
|
||||
@@ -5313,7 +5314,7 @@ uint16_t mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams.
|
||||
if (row < rows-1) SEGMENT.setPixelColorXY(col, row+1, spawnColor);
|
||||
} else {
|
||||
// fade other pixels
|
||||
SEGMENT.setPixelColorXY(col, row, pix.nscale8(fade));
|
||||
if (pix != CRGB::Black) SEGMENT.setPixelColorXY(col, row, pix.nscale8(fade)); // optimization: don't fade black pixels
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ void registerUsermods()
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
#ifdef USERMOD_BATTERY
|
||||
usermods.add(new UsermodBattery());
|
||||
usermods.add(new UsermodBattery("Battery", true));
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
@@ -290,7 +290,7 @@ void registerUsermods()
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_RTC
|
||||
usermods.add(new RTCUsermod());
|
||||
usermods.add(new RTCUsermod("RTC", true));
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ELEKSTUBE_IPS
|
||||
|
||||
Reference in New Issue
Block a user