Merge branch 'esp32-s2' into dev
This commit is contained in:
commit
fc0dc4472b
@ -8,7 +8,7 @@
|
||||
#error This audio reactive usermod does not support the ESP8266.
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||
#include <esp_timer.h>
|
||||
#endif
|
||||
|
||||
@ -41,13 +41,15 @@
|
||||
|
||||
constexpr i2s_port_t I2S_PORT = I2S_NUM_0;
|
||||
constexpr int BLOCK_SIZE = 128;
|
||||
constexpr int SAMPLE_RATE = 22050; // Base sample rate in Hz - 22Khz is a standard rate. Physical sample time -> 23ms
|
||||
//constexpr int SAMPLE_RATE = 20480; // Base sample rate in Hz - 20Khz is experimental. Physical sample time -> 25ms
|
||||
//constexpr int SAMPLE_RATE = 10240; // Base sample rate in Hz - previous default. Physical sample time -> 50ms
|
||||
constexpr SRate_t SAMPLE_RATE = 22050; // Base sample rate in Hz - 22Khz is a standard rate. Physical sample time -> 23ms
|
||||
//constexpr SRate_t SAMPLE_RATE = 16000; // 16kHz - use if FFTtask takes more than 20ms. Physical sample time -> 32ms
|
||||
//constexpr SRate_t SAMPLE_RATE = 20480; // Base sample rate in Hz - 20Khz is experimental. Physical sample time -> 25ms
|
||||
//constexpr SRate_t SAMPLE_RATE = 10240; // Base sample rate in Hz - previous default. Physical sample time -> 50ms
|
||||
|
||||
#define FFT_MIN_CYCLE 18 // minimum time before FFT task is repeated. Use with 22Khz sampling
|
||||
//#define FFT_MIN_CYCLE 22 // minimum time before FFT task is repeated. Use with 20Khz sampling
|
||||
//#define FFT_MIN_CYCLE 44 // minimum time before FFT task is repeated. Use with 10Khz sampling
|
||||
#define FFT_MIN_CYCLE 21 // minimum time before FFT task is repeated. Use with 22Khz sampling
|
||||
//#define FFT_MIN_CYCLE 30 // Use with 16Khz sampling
|
||||
//#define FFT_MIN_CYCLE 23 // minimum time before FFT task is repeated. Use with 20Khz sampling
|
||||
//#define FFT_MIN_CYCLE 46 // minimum time before FFT task is repeated. Use with 10Khz sampling
|
||||
|
||||
// globals
|
||||
static uint8_t inputLevel = 128; // UI slider value
|
||||
@ -112,7 +114,7 @@ static void autoResetPeak(void); // peak auto-reset function
|
||||
#else
|
||||
// lib_deps += https://github.com/blazoncek/arduinoFFT.git
|
||||
#endif
|
||||
#include "arduinoFFT.h"
|
||||
#include <arduinoFFT.h>
|
||||
|
||||
// FFT Output variables shared with animations
|
||||
#define NUM_GEQ_CHANNELS 16 // number of frequency channels. Don't change !!
|
||||
@ -144,9 +146,9 @@ static float fftAvg[NUM_GEQ_CHANNELS] = {0.0f}; // Calcula
|
||||
static float fftResultMax[NUM_GEQ_CHANNELS] = {0.0f}; // A table used for testing to determine how our post-processing is working.
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
static unsigned long fftTime = 0;
|
||||
static unsigned long sampleTime = 0;
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||
static uint64_t fftTime = 0;
|
||||
static uint64_t sampleTime = 0;
|
||||
#endif
|
||||
|
||||
// Table of multiplication factors so that we can even out the frequency response.
|
||||
@ -182,31 +184,33 @@ void FFTcode(void * parameter)
|
||||
// see https://www.freertos.org/vtaskdelayuntil.html
|
||||
const TickType_t xFrequency = FFT_MIN_CYCLE * portTICK_PERIOD_MS;
|
||||
|
||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||
for(;;) {
|
||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||
delay(1); // DO NOT DELETE THIS LINE! It is needed to give the IDLE(0) task enough time and to keep the watchdog happy.
|
||||
// taskYIELD(), yield(), vTaskDelay() and esp_task_wdt_feed() didn't seem to work.
|
||||
|
||||
vTaskDelayUntil( &xLastWakeTime, xFrequency); // release CPU, and let I2S fill its buffers
|
||||
// Only run the FFT computing code if we're not in Receive mode and not in realtime mode
|
||||
// Don't run FFT computing code if we're in Receive mode or in realtime mode
|
||||
if (disableSoundProcessing || (audioSyncEnabled & 0x02)) {
|
||||
vTaskDelayUntil( &xLastWakeTime, xFrequency); // release CPU, and let I2S fill its buffers
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||
uint64_t start = esp_timer_get_time();
|
||||
#endif
|
||||
|
||||
// get a fresh batch of samples from I2S
|
||||
if (audioSource) audioSource->getSamples(vReal, samplesFFT);
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||
if (start < esp_timer_get_time()) { // filter out overflows
|
||||
unsigned long sampleTimeInMillis = (esp_timer_get_time() - start +500ULL) / 1000ULL; // "+500" to ensure proper rounding
|
||||
unsigned long sampleTimeInMillis = (esp_timer_get_time() - start +5ULL) / 10ULL; // "+5" to ensure proper rounding
|
||||
sampleTime = (sampleTimeInMillis*3 + sampleTime*7)/10; // smooth
|
||||
}
|
||||
#endif
|
||||
|
||||
xLastWakeTime = xTaskGetTickCount(); // update "last unblocked time" for vTaskDelay
|
||||
|
||||
// find highest sample in the batch
|
||||
float maxSample = 0.0f; // max sample from FFT batch
|
||||
for (int i=0; i < samplesFFT; i++) {
|
||||
@ -220,30 +224,42 @@ void FFTcode(void * parameter)
|
||||
// early release allows the filters (getSample() and agcAvg()) to work with fresh values - we will have matching gain and noise gate values when we want to process the FFT results. micDataReal = maxSample;
|
||||
micDataReal = maxSample;
|
||||
|
||||
// run FFT (takes 3-5ms on ESP32)
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
FFT.dcRemoval(); // remove DC offset
|
||||
FFT.windowing( FFTWindow::Flat_top, FFTDirection::Forward); // Weigh data using "Flat Top" function - better amplitude accuracy
|
||||
//FFT.windowing(FFTWindow::Blackman_Harris, FFTDirection::Forward); // Weigh data using "Blackman- Harris" window - sharp peaks due to excellent sideband rejection
|
||||
FFT.compute( FFTDirection::Forward ); // Compute FFT
|
||||
FFT.complexToMagnitude(); // Compute magnitudes
|
||||
#ifdef SR_DEBUG
|
||||
if (true) { // this allows measure FFT runtimes, as it disables the "only when needed" optimization
|
||||
#else
|
||||
FFT.DCRemoval(); // let FFT lib remove DC component, so we don't need to care about this in getSamples()
|
||||
if (sampleAvg > 1) { // noise gate open means that FFT results will be used. Don't run FFT if results are not needed.
|
||||
#endif
|
||||
|
||||
//FFT.Windowing( FFT_WIN_TYP_HAMMING, FFT_FORWARD ); // Weigh data - standard Hamming window
|
||||
//FFT.Windowing( FFT_WIN_TYP_BLACKMAN, FFT_FORWARD ); // Blackman window - better side freq rejection
|
||||
//FFT.Windowing( FFT_WIN_TYP_BLACKMAN_HARRIS, FFT_FORWARD );// Blackman-Harris - excellent sideband rejection
|
||||
FFT.Windowing( FFT_WIN_TYP_FLT_TOP, FFT_FORWARD ); // Flat Top Window - better amplitude accuracy
|
||||
FFT.Compute( FFT_FORWARD ); // Compute FFT
|
||||
FFT.ComplexToMagnitude(); // Compute magnitudes
|
||||
// run FFT (takes 3-5ms on ESP32, ~12ms on ESP32-S2)
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
FFT.dcRemoval(); // remove DC offset
|
||||
FFT.windowing( FFTWindow::Flat_top, FFTDirection::Forward); // Weigh data using "Flat Top" function - better amplitude accuracy
|
||||
//FFT.windowing(FFTWindow::Blackman_Harris, FFTDirection::Forward); // Weigh data using "Blackman- Harris" window - sharp peaks due to excellent sideband rejection
|
||||
FFT.compute( FFTDirection::Forward ); // Compute FFT
|
||||
FFT.complexToMagnitude(); // Compute magnitudes
|
||||
#else
|
||||
FFT.DCRemoval(); // let FFT lib remove DC component, so we don't need to care about this in getSamples()
|
||||
|
||||
//FFT.Windowing( FFT_WIN_TYP_HAMMING, FFT_FORWARD ); // Weigh data - standard Hamming window
|
||||
//FFT.Windowing( FFT_WIN_TYP_BLACKMAN, FFT_FORWARD ); // Blackman window - better side freq rejection
|
||||
//FFT.Windowing( FFT_WIN_TYP_BLACKMAN_HARRIS, FFT_FORWARD );// Blackman-Harris - excellent sideband rejection
|
||||
FFT.Windowing( FFT_WIN_TYP_FLT_TOP, FFT_FORWARD ); // Flat Top Window - better amplitude accuracy
|
||||
FFT.Compute( FFT_FORWARD ); // Compute FFT
|
||||
FFT.ComplexToMagnitude(); // Compute magnitudes
|
||||
#endif
|
||||
|
||||
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||
FFT.majorPeak(FFT_MajorPeak, FFT_Magnitude); // let the effects know which freq was most dominant
|
||||
FFT.majorPeak(FFT_MajorPeak, FFT_Magnitude); // let the effects know which freq was most dominant
|
||||
#else
|
||||
FFT.MajorPeak(&FFT_MajorPeak, &FFT_Magnitude); // let the effects know which freq was most dominant
|
||||
FFT.MajorPeak(&FFT_MajorPeak, &FFT_Magnitude); // let the effects know which freq was most dominant
|
||||
#endif
|
||||
FFT_MajorPeak = constrain(FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
||||
FFT_MajorPeak = constrain(FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
||||
|
||||
} else { // noise gate closed - only clear results as FFT was skipped. MIC samples are still valid when we do this.
|
||||
memset(vReal, 0, sizeof(vReal));
|
||||
FFT_MajorPeak = 1;
|
||||
FFT_Magnitude = 0.001;
|
||||
}
|
||||
|
||||
for (int i = 0; i < samplesFFT; i++) {
|
||||
float t = fabsf(vReal[i]); // just to be sure - values in fft bins should be positive any way
|
||||
@ -380,9 +396,9 @@ void FFTcode(void * parameter)
|
||||
fftResult[i] = constrain((int)currentResult, 0, 255);
|
||||
}
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||
if (start < esp_timer_get_time()) { // filter out overflows
|
||||
unsigned long fftTimeInMillis = ((esp_timer_get_time() - start) +500ULL) / 1000ULL; // "+500" to ensure proper rounding
|
||||
unsigned long fftTimeInMillis = ((esp_timer_get_time() - start) +5ULL) / 10ULL; // "+5" to ensure proper rounding
|
||||
fftTime = (fftTimeInMillis*3 + fftTime*7)/10; // smooth
|
||||
}
|
||||
#endif
|
||||
@ -390,6 +406,8 @@ void FFTcode(void * parameter)
|
||||
autoResetPeak();
|
||||
detectSamplePeak();
|
||||
|
||||
vTaskDelayUntil( &xLastWakeTime, xFrequency); // release CPU, and let I2S fill its buffers
|
||||
|
||||
} // for(;;)ever
|
||||
} // FFTcode() task end
|
||||
|
||||
@ -448,7 +466,7 @@ class AudioReactive : public Usermod {
|
||||
int8_t i2swsPin = I2S_WSPIN;
|
||||
#endif
|
||||
#ifndef I2S_CKPIN // aka BCLK
|
||||
int8_t i2sckPin = 14;
|
||||
int8_t i2sckPin = 14; /*PDM: set to I2S_PIN_NO_CHANGE*/
|
||||
#else
|
||||
int8_t i2sckPin = I2S_CKPIN;
|
||||
#endif
|
||||
@ -463,9 +481,9 @@ class AudioReactive : public Usermod {
|
||||
int8_t sclPin = ES7243_SCLPIN;
|
||||
#endif
|
||||
#ifndef MCLK_PIN
|
||||
int8_t mclkPin = -1;
|
||||
int8_t mclkPin = I2S_PIN_NO_CHANGE; /* ESP32: only -1, 0, 1, 3 allowed*/
|
||||
#else
|
||||
int8_t mclkPin = MLCK_PIN;
|
||||
int8_t mclkPin = MCLK_PIN;
|
||||
#endif
|
||||
|
||||
// new "V2" audiosync struct - 40 Bytes
|
||||
@ -949,10 +967,18 @@ class AudioReactive : public Usermod {
|
||||
|
||||
// Reset I2S peripheral for good measure
|
||||
i2s_driver_uninstall(I2S_NUM_0);
|
||||
periph_module_reset(PERIPH_I2S0_MODULE);
|
||||
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
periph_module_reset(PERIPH_I2S0_MODULE); // not possible on -C3
|
||||
#endif
|
||||
delay(100); // Give that poor microphone some time to setup.
|
||||
switch (dmType) {
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// stub cases for not-yet-supported I2S modes on other ESP32 chips
|
||||
case 0: //ADC analog
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case 5: //PDM Microphone
|
||||
#endif
|
||||
#endif
|
||||
case 1:
|
||||
DEBUGSR_PRINT(F("AR: Generic I2S Microphone - ")); DEBUGSR_PRINTLN(F(I2S_MIC_CHANNEL_TEXT));
|
||||
audioSource = new I2SSource(SAMPLE_RATE, BLOCK_SIZE);
|
||||
@ -977,12 +1003,16 @@ class AudioReactive : public Usermod {
|
||||
delay(100);
|
||||
if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
|
||||
break;
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case 5:
|
||||
DEBUGSR_PRINT(F("AR: I2S PDM Microphone - ")); DEBUGSR_PRINTLN(F(I2S_MIC_CHANNEL_TEXT));
|
||||
audioSource = new I2SSource(SAMPLE_RATE, BLOCK_SIZE);
|
||||
delay(100);
|
||||
if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin);
|
||||
break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// ADC over I2S is only possible on "classic" ESP32
|
||||
case 0:
|
||||
default:
|
||||
DEBUGSR_PRINTLN(F("AR: Analog Microphone (left channel only)."));
|
||||
@ -990,6 +1020,7 @@ class AudioReactive : public Usermod {
|
||||
delay(100);
|
||||
if (audioSource) audioSource->initialize(audioPin);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
delay(250); // give microphone enough time to initialise
|
||||
|
||||
@ -1357,13 +1388,15 @@ class AudioReactive : public Usermod {
|
||||
infoArr.add("off");
|
||||
if (audioSyncEnabled && !udpSyncConnected) infoArr.add(" <i>(unconnected)</i>");
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
#if defined(WLED_DEBUG) || defined(SR_DEBUG)
|
||||
infoArr = user.createNestedArray(F("Sampling time"));
|
||||
infoArr.add(sampleTime);
|
||||
infoArr.add("ms");
|
||||
infoArr.add(float(sampleTime)/100.0f);
|
||||
infoArr.add(" ms");
|
||||
infoArr = user.createNestedArray(F("FFT time"));
|
||||
infoArr.add(fftTime-sampleTime);
|
||||
infoArr.add("ms");
|
||||
infoArr.add(float(fftTime-sampleTime)/100.0f);
|
||||
infoArr.add(" ms");
|
||||
DEBUGSR_PRINTF("AR Sampling time: %5.2f ms\n", float(sampleTime)/100.0f);
|
||||
DEBUGSR_PRINTF("AR FFT time : %5.2f ms\n", float(fftTime-sampleTime)/100.0f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1529,12 +1562,16 @@ class AudioReactive : public Usermod {
|
||||
void appendConfigData()
|
||||
{
|
||||
oappend(SET_F("dd=addDropdown('AudioReactive','digitalmic:type');"));
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
oappend(SET_F("addOption(dd,'Generic Analog',0);"));
|
||||
#endif
|
||||
oappend(SET_F("addOption(dd,'Generic I2S',1);"));
|
||||
oappend(SET_F("addOption(dd,'ES7243',2);"));
|
||||
oappend(SET_F("addOption(dd,'SPH0654',3);"));
|
||||
oappend(SET_F("addOption(dd,'Generic I2S with Mclk',4);"));
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
oappend(SET_F("addOption(dd,'Generic I2S PDM',5);"));
|
||||
#endif
|
||||
oappend(SET_F("dd=addDropdown('AudioReactive','cfg:AGC');"));
|
||||
oappend(SET_F("addOption(dd,'Off',0);"));
|
||||
oappend(SET_F("addOption(dd,'Normal',1);"));
|
||||
@ -1562,7 +1599,11 @@ class AudioReactive : public Usermod {
|
||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',0,'I2S SD');"));
|
||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',1,'I2S WS');"));
|
||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',2,'I2S SCK');"));
|
||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'I2S Master CLK');"));
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'I2S Master CLK <i>only use -1, 0, 1 or 3 for MCLK</i>');"));
|
||||
#else
|
||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'I2S Master CLK');"));
|
||||
#endif
|
||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',4,'I2C SDA');"));
|
||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',5,'I2C SCL');"));
|
||||
}
|
||||
|
@ -4,15 +4,31 @@
|
||||
#include "wled.h"
|
||||
#include <driver/i2s.h>
|
||||
#include <driver/adc.h>
|
||||
#include <soc/i2s_reg.h> // needed for SPH0465 timing workaround (classic ESP32)
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#include <driver/adc_deprecated.h>
|
||||
#include <driver/adc_types_deprecated.h>
|
||||
#endif
|
||||
// type of i2s_config_t.SampleRate was changed from "int" to "unsigned" in IDF 4.4.x
|
||||
#define SRate_t uint32_t
|
||||
#else
|
||||
#define SRate_t int
|
||||
#endif
|
||||
|
||||
//#include <driver/i2s_std.h>
|
||||
//#include <driver/i2s_pdm.h>
|
||||
//#include <driver/i2s_tdm.h>
|
||||
//#include <driver/gpio.h>
|
||||
|
||||
// see https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/chip-series-comparison.html#related-documents
|
||||
// and https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/i2s.html#overview-of-all-modes
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||
// there are two things in these MCUs that could lead to problems with audio processing:
|
||||
// * no floating point hardware (FPU) support - FFT uses float calculations. If done in software, a strong slow-down can be expected (between 8x and 20x)
|
||||
// * single core, so FFT task might slow down other things like LED updates
|
||||
#warning This audio reactive usermod does not support ESP32-C2, ESP32-C3 or ESP32-S2.
|
||||
#endif
|
||||
|
||||
/* ToDo: remove. ES7243 is controlled via compiler defines
|
||||
Until this configuration is moved to the webinterface
|
||||
@ -20,13 +36,6 @@
|
||||
|
||||
// if you have problems to get your microphone work on the left channel, uncomment the following line
|
||||
//#define I2S_USE_RIGHT_CHANNEL // (experimental) define this to use right channel (digital mics only)
|
||||
#ifdef I2S_USE_RIGHT_CHANNEL
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_RIGHT
|
||||
#define I2S_MIC_CHANNEL_TEXT "right channel only."
|
||||
#else
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_LEFT
|
||||
#define I2S_MIC_CHANNEL_TEXT "left channel only."
|
||||
#endif
|
||||
|
||||
// Uncomment the line below to utilize ADC1 _exclusively_ for I2S sound input.
|
||||
// benefit: analog mic inputs will be sampled contiously -> better response times and less "glitches"
|
||||
@ -36,18 +45,56 @@
|
||||
|
||||
// data type requested from the I2S driver - currently we always use 32bit
|
||||
//#define I2S_USE_16BIT_SAMPLES // (experimental) define this to request 16bit - more efficient but possibly less compatible
|
||||
|
||||
#ifdef I2S_USE_16BIT_SAMPLES
|
||||
#define I2S_SAMPLE_RESOLUTION I2S_BITS_PER_SAMPLE_16BIT
|
||||
#define I2S_datatype int16_t
|
||||
#define I2S_unsigned_datatype uint16_t
|
||||
#define I2S_data_size I2S_BITS_PER_CHAN_16BIT
|
||||
#undef I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||
#else
|
||||
#define I2S_SAMPLE_RESOLUTION I2S_BITS_PER_SAMPLE_32BIT
|
||||
//#define I2S_SAMPLE_RESOLUTION I2S_BITS_PER_SAMPLE_24BIT
|
||||
#define I2S_datatype int32_t
|
||||
#define I2S_unsigned_datatype uint32_t
|
||||
#define I2S_data_size I2S_BITS_PER_CHAN_32BIT
|
||||
#define I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||
#endif
|
||||
|
||||
/* There are several (confusing) options in IDF 4.4.x:
|
||||
* I2S_CHANNEL_FMT_RIGHT_LEFT, I2S_CHANNEL_FMT_ALL_RIGHT and I2S_CHANNEL_FMT_ALL_LEFT stands for stereo mode, which means two channels will transport different data.
|
||||
* I2S_CHANNEL_FMT_ONLY_RIGHT and I2S_CHANNEL_FMT_ONLY_LEFT they are mono mode, both channels will only transport same data.
|
||||
* I2S_CHANNEL_FMT_MULTIPLE means TDM channels, up to 16 channel will available, and they are stereo as default.
|
||||
* if you want to receive two channels, one is the actual data from microphone and another channel is suppose to receive 0, it's different data in two channels, you need to choose I2S_CHANNEL_FMT_RIGHT_LEFT in this case.
|
||||
*/
|
||||
|
||||
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)) && (ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(4, 4, 3))
|
||||
// espressif bug: only_left has no sound, left and right are swapped
|
||||
// https://github.com/espressif/esp-idf/issues/9635 I2S mic not working since 4.4 (IDFGH-8138)
|
||||
// https://github.com/espressif/esp-idf/issues/8538 I2S channel selection issue? (IDFGH-6918)
|
||||
// https://github.com/espressif/esp-idf/issues/6625 I2S: left/right channels are swapped for read (IDFGH-4826)
|
||||
#ifdef I2S_USE_RIGHT_CHANNEL
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_LEFT
|
||||
#define I2S_MIC_CHANNEL_TEXT "right channel only (work-around swapped channel bug in IDF 4.4)."
|
||||
#else
|
||||
//#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ALL_LEFT
|
||||
//#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_RIGHT_LEFT
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_RIGHT
|
||||
#define I2S_MIC_CHANNEL_TEXT "left channel only (work-around swapped channel bug in IDF 4.4)."
|
||||
#endif
|
||||
|
||||
#else
|
||||
// not swapped
|
||||
#ifdef I2S_USE_RIGHT_CHANNEL
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_RIGHT
|
||||
#define I2S_MIC_CHANNEL_TEXT "right channel only."
|
||||
#else
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_LEFT
|
||||
#define I2S_MIC_CHANNEL_TEXT "left channel only."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Interface class
|
||||
AudioSource serves as base class for all microphone types
|
||||
This enables accessing all microphones with one single interface
|
||||
@ -91,13 +138,13 @@ class AudioSource {
|
||||
virtual I2S_datatype postProcessSample(I2S_datatype sample_in) {return(sample_in);} // default method can be overriden by instances (ADC) that need sample postprocessing
|
||||
|
||||
// Private constructor, to make sure it is not callable except from derived classes
|
||||
AudioSource(int sampleRate, int blockSize) :
|
||||
AudioSource(SRate_t sampleRate, int blockSize) :
|
||||
_sampleRate(sampleRate),
|
||||
_blockSize(blockSize),
|
||||
_initialized(false)
|
||||
{};
|
||||
|
||||
int _sampleRate; // Microphone sampling rate
|
||||
SRate_t _sampleRate; // Microphone sampling rate
|
||||
int _blockSize; // I2S block size
|
||||
bool _initialized; // Gets set to true if initialization is successful
|
||||
};
|
||||
@ -107,7 +154,7 @@ class AudioSource {
|
||||
*/
|
||||
class I2SSource : public AudioSource {
|
||||
public:
|
||||
I2SSource(int sampleRate, int blockSize) :
|
||||
I2SSource(SRate_t sampleRate, int blockSize) :
|
||||
AudioSource(sampleRate, blockSize) {
|
||||
_config = {
|
||||
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
|
||||
@ -116,12 +163,19 @@ class I2SSource : public AudioSource {
|
||||
.channel_format = I2S_MIC_CHANNEL,
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
|
||||
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
|
||||
//.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = _blockSize,
|
||||
.use_apll = 0,
|
||||
.bits_per_chan = I2S_data_size,
|
||||
#else
|
||||
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
|
||||
#endif
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = _blockSize
|
||||
.dma_buf_len = _blockSize,
|
||||
.use_apll = false
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
@ -129,18 +183,24 @@ class I2SSource : public AudioSource {
|
||||
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
|
||||
DEBUGSR_PRINTF("\nAR: Failed to allocate I2S pins: ws=%d, sd=%d\n", i2swsPin, i2ssdPin);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// i2ssckPin needs special treatment, since it might be unused on PDM mics
|
||||
if (i2sckPin != I2S_PIN_NO_CHANGE) {
|
||||
if (!pinManager.allocatePin(i2sckPin, true, PinOwner::UM_Audioreactive)) return;
|
||||
if (!pinManager.allocatePin(i2sckPin, true, PinOwner::UM_Audioreactive)) {
|
||||
DEBUGSR_PRINTF("\nAR: Failed to allocate I2S pins: sck=%d\n", i2sckPin);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
// This is an I2S PDM microphone, these microphones only use a clock and
|
||||
// data line, to make it simpler to debug, use the WS pin as CLK and SD
|
||||
// pin as DATA
|
||||
_config.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM); // Change mode to pdm if clock pin not provided
|
||||
_config.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM); // Change mode to pdm if clock pin not provided. PDM is not supported on ESP32-S2. PDM RX not supported on ESP32-C3
|
||||
#endif
|
||||
}
|
||||
|
||||
// Reserve the master clock pin if provided
|
||||
@ -151,6 +211,9 @@ class I2SSource : public AudioSource {
|
||||
}
|
||||
|
||||
_pinConfig = {
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
.mck_io_num = mclkPin, // "classic" ESP32 supports setting MCK on GPIO0/GPIO1/GPIO3 only. i2s_set_pin() will fail if wrong mck_io_num is provided.
|
||||
#endif
|
||||
.bck_io_num = i2sckPin,
|
||||
.ws_io_num = i2swsPin,
|
||||
.data_out_num = I2S_PIN_NO_CHANGE,
|
||||
@ -166,9 +229,18 @@ class I2SSource : public AudioSource {
|
||||
err = i2s_set_pin(I2S_NUM_0, &_pinConfig);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to set i2s pin config: %d\n", err);
|
||||
i2s_driver_uninstall(I2S_NUM_0); // uninstall already-installed driver
|
||||
return;
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
|
||||
err = i2s_set_clk(I2S_NUM_0, _sampleRate, I2S_SAMPLE_RESOLUTION, I2S_CHANNEL_MONO); // set bit clocks. Also takes care of MCLK routing if needed.
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to configure i2s clocks: %d\n", err);
|
||||
i2s_driver_uninstall(I2S_NUM_0); // uninstall already-installed driver
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
@ -222,7 +294,11 @@ class I2SSource : public AudioSource {
|
||||
|
||||
protected:
|
||||
void _routeMclk(int8_t mclkPin) {
|
||||
/* Enable the mclk routing depending on the selected mclk pin
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// MCLK routing by writing registers is not needed any more with IDF > 4.4.0
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
// this way of MCLK routing only works on "classic" ESP32
|
||||
/* Enable the mclk routing depending on the selected mclk pin (ESP32: only 0,1,3)
|
||||
Only I2S_NUM_0 is supported
|
||||
*/
|
||||
if (mclkPin == GPIO_NUM_0) {
|
||||
@ -235,6 +311,8 @@ class I2SSource : public AudioSource {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_CLK_OUT2);
|
||||
WRITE_PERI_REG(PIN_CTRL, 0xFF00);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
i2s_config_t _config;
|
||||
@ -275,7 +353,7 @@ class ES7243 : public I2SSource {
|
||||
}
|
||||
|
||||
public:
|
||||
ES7243(int sampleRate, int blockSize) :
|
||||
ES7243(SRate_t sampleRate, int blockSize) :
|
||||
I2SSource(sampleRate, blockSize) {
|
||||
_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT;
|
||||
};
|
||||
@ -307,6 +385,9 @@ public:
|
||||
int8_t pin_ES7243_SCL;
|
||||
};
|
||||
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// ADC over I2S is only availeable in "classic" ESP32
|
||||
|
||||
/* ADC over I2S Microphone
|
||||
This microphone is an ADC pin sampled via the I2S interval
|
||||
This allows to use the I2S API to obtain ADC samples with high sample rates
|
||||
@ -314,7 +395,7 @@ public:
|
||||
*/
|
||||
class I2SAdcSource : public I2SSource {
|
||||
public:
|
||||
I2SAdcSource(int sampleRate, int blockSize) :
|
||||
I2SAdcSource(SRate_t sampleRate, int blockSize) :
|
||||
I2SSource(sampleRate, blockSize) {
|
||||
_config = {
|
||||
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
|
||||
@ -363,13 +444,17 @@ class I2SAdcSource : public I2SSource {
|
||||
return;
|
||||
}
|
||||
|
||||
adc1_config_width(ADC_WIDTH_BIT_12); // ensure that ADC runs with 12bit resolution
|
||||
|
||||
// Enable I2S mode of ADC
|
||||
err = i2s_set_adc_mode(ADC_UNIT_1, adc1_channel_t(channel));
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to set i2s adc mode: %d\n", err);
|
||||
return;
|
||||
}
|
||||
// adc1_config_channel_atten(adc1_channel_t(channel), ADC_ATTEN_DB_11)); //see https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/I2S/HiFreq_ADC/HiFreq_ADC.ino
|
||||
|
||||
// see example in https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/I2S/HiFreq_ADC/HiFreq_ADC.ino
|
||||
adc1_config_channel_atten(adc1_channel_t(channel), ADC_ATTEN_DB_11); // configure ADC input amplification
|
||||
|
||||
#if defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||
// according to docs from espressif, the ADC needs to be started explicitly
|
||||
@ -489,20 +574,29 @@ class I2SAdcSource : public I2SSource {
|
||||
int8_t _audioPin;
|
||||
int8_t _myADCchannel = 0x0F; // current ADC channel for analog input. 0x0F means "undefined"
|
||||
};
|
||||
#endif
|
||||
|
||||
/* SPH0645 Microphone
|
||||
This is an I2S microphone with some timing quirks that need
|
||||
special consideration.
|
||||
*/
|
||||
|
||||
// https://github.com/espressif/esp-idf/issues/7192 SPH0645 i2s microphone issue when migrate from legacy esp-idf version (IDFGH-5453)
|
||||
// a user recommended this: Try to set .communication_format to I2S_COMM_FORMAT_STAND_I2S and call i2s_set_clk() after i2s_set_pin().
|
||||
class SPH0654 : public I2SSource {
|
||||
public:
|
||||
SPH0654(int sampleRate, int blockSize) :
|
||||
SPH0654(SRate_t sampleRate, int blockSize) :
|
||||
I2SSource(sampleRate, blockSize)
|
||||
{}
|
||||
|
||||
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) {
|
||||
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
|
||||
REG_SET_BIT(I2S_TIMING_REG(I2S_NUM_0), BIT(9));
|
||||
REG_SET_BIT(I2S_CONF_REG(I2S_NUM_0), I2S_RX_MSB_SHIFT);
|
||||
#else
|
||||
#warning FIX ME! Please.
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
@ -7099,7 +7099,7 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
|
||||
if (SEGENV.call == 0) for (int i=0; i<cols; i++) previousBarHeight[i] = 0;
|
||||
|
||||
bool rippleTime = false;
|
||||
if (millis() - SEGENV.step >= (256 - SEGMENT.intensity)) {
|
||||
if (millis() - SEGENV.step >= (256U - SEGMENT.intensity)) {
|
||||
SEGENV.step = millis();
|
||||
rippleTime = true;
|
||||
}
|
||||
|
@ -504,7 +504,7 @@ class BusOnOff : public Bus {
|
||||
|
||||
uint8_t currentPin = bc.pins[0];
|
||||
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) {
|
||||
deallocatePins(); return;
|
||||
return;
|
||||
}
|
||||
_pin = currentPin; //store only after allocatePin() succeeds
|
||||
pinMode(_pin, OUTPUT);
|
||||
@ -540,7 +540,7 @@ class BusOnOff : public Bus {
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
deallocatePins();
|
||||
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
||||
}
|
||||
|
||||
~BusOnOff() {
|
||||
@ -550,10 +550,6 @@ class BusOnOff : public Bus {
|
||||
private:
|
||||
uint8_t _pin = 255;
|
||||
uint8_t _data = 0;
|
||||
|
||||
void deallocatePins() {
|
||||
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -689,6 +685,8 @@ class BusManager {
|
||||
busses[numBusses] = new BusNetwork(bc);
|
||||
} else if (IS_DIGITAL(bc.type)) {
|
||||
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
|
||||
} else if (bc.type == TYPE_ONOFF) {
|
||||
busses[numBusses] = new BusOnOff(bc);
|
||||
} else {
|
||||
busses[numBusses] = new BusPwm(bc);
|
||||
}
|
||||
|
@ -3,6 +3,18 @@
|
||||
|
||||
#include "NeoPixelBrightnessBus.h"
|
||||
|
||||
// temporary - these defines should actually be set in platformio.ini
|
||||
// C3: I2S0 and I2S1 methods not supported
|
||||
// S2: I2S1 methods not supported
|
||||
// S3: I2S0 and I2S1 methods not supported yet
|
||||
#if !defined(WLED_NO_I2S0_PIXELBUS) && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3))
|
||||
#define WLED_NO_I2S0_PIXELBUS
|
||||
#endif
|
||||
#if !defined(WLED_NO_I2S1_PIXELBUS) && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2))
|
||||
#define WLED_NO_I2S1_PIXELBUS
|
||||
#endif
|
||||
// temporary end
|
||||
|
||||
//Hardware SPI Pins
|
||||
#define P_8266_HS_MOSI 13
|
||||
#define P_8266_HS_CLK 14
|
||||
@ -117,43 +129,43 @@
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
//RGB
|
||||
#define B_32_RN_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32RmtNWs2812xMethod>
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
#define B_32_I0_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s0800KbpsMethod>
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#define B_32_I1_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1800KbpsMethod>
|
||||
#endif
|
||||
//RGBW
|
||||
#define B_32_RN_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32RmtNWs2812xMethod>
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
#define B_32_I0_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32I2s0800KbpsMethod>
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#define B_32_I1_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32I2s1800KbpsMethod>
|
||||
#endif
|
||||
//400Kbps
|
||||
#define B_32_RN_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32RmtN400KbpsMethod>
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
#define B_32_I0_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s0400KbpsMethod>
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#define B_32_I1_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1400KbpsMethod>
|
||||
#endif
|
||||
//TM1814 (RGBW)
|
||||
#define B_32_RN_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32RmtNTm1814Method>
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
#define B_32_I0_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32I2s0Tm1814Method>
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#define B_32_I1_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32I2s1Tm1814Method>
|
||||
#endif
|
||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
||||
//TM1829 (RGB)
|
||||
#define B_32_RN_TM2_3 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp32RmtNTm1829Method>
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
#define B_32_I0_TM2_3 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp32I2s0Tm1829Method>
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#define B_32_I1_TM2_3 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp32I2s1Tm1829Method>
|
||||
#endif
|
||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
||||
@ -237,33 +249,33 @@ class PolyBus {
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Begin(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Begin(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Begin(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: beginTM1814<B_32_RN_TM1_4*>(busPtr); break;
|
||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Begin(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_TM1_4: beginTM1814<B_32_I0_TM1_4*>(busPtr); break;
|
||||
case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_TM1_4: beginTM1814<B_32_I1_TM1_4*>(busPtr); break;
|
||||
case I_32_I1_TM2_3: (static_cast<B_32_I1_TM2_3*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
@ -309,33 +321,33 @@ class PolyBus {
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_3: busPtr = new B_32_I0_NEO_3(len, pins[0]); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_3: busPtr = new B_32_I1_NEO_3(len, pins[0]); break;
|
||||
#endif
|
||||
case I_32_RN_NEO_4: busPtr = new B_32_RN_NEO_4(len, pins[0], (NeoBusChannel)channel); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_4: busPtr = new B_32_I0_NEO_4(len, pins[0]); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_4: busPtr = new B_32_I1_NEO_4(len, pins[0]); break;
|
||||
#endif
|
||||
case I_32_RN_400_3: busPtr = new B_32_RN_400_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_400_3: busPtr = new B_32_I0_400_3(len, pins[0]); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_400_3: busPtr = new B_32_I1_400_3(len, pins[0]); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: busPtr = new B_32_RN_TM1_4(len, pins[0], (NeoBusChannel)channel); break;
|
||||
case I_32_RN_TM2_3: busPtr = new B_32_RN_TM2_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_TM1_4: busPtr = new B_32_I0_TM1_4(len, pins[0]); break;
|
||||
case I_32_I0_TM2_3: busPtr = new B_32_I0_TM2_3(len, pins[0]); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_TM1_4: busPtr = new B_32_I1_TM1_4(len, pins[0]); break;
|
||||
case I_32_I1_TM2_3: busPtr = new B_32_I1_TM2_3(len, pins[0]); break;
|
||||
#endif
|
||||
@ -382,33 +394,33 @@ class PolyBus {
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Show(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->Show(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->Show(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->Show(); break;
|
||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Show(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->Show(); break;
|
||||
case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->Show(); break;
|
||||
case I_32_I1_TM2_3: (static_cast<B_32_I1_TM2_3*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
@ -452,33 +464,33 @@ class PolyBus {
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: return (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_3: return (static_cast<B_32_I0_NEO_3*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_3: return (static_cast<B_32_I1_NEO_3*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
case I_32_RN_NEO_4: return (static_cast<B_32_RN_NEO_4*>(busPtr))->CanShow(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_4: return (static_cast<B_32_I0_NEO_4*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_4: return (static_cast<B_32_I1_NEO_4*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
case I_32_RN_400_3: return (static_cast<B_32_RN_400_3*>(busPtr))->CanShow(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_400_3: return (static_cast<B_32_I0_400_3*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_400_3: return (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: return (static_cast<B_32_RN_TM1_4*>(busPtr))->CanShow(); break;
|
||||
case I_32_RN_TM2_3: return (static_cast<B_32_RN_TM2_3*>(busPtr))->CanShow(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_TM1_4: return (static_cast<B_32_I0_TM1_4*>(busPtr))->CanShow(); break;
|
||||
case I_32_I0_TM2_3: return (static_cast<B_32_I0_TM2_3*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_TM1_4: return (static_cast<B_32_I1_TM1_4*>(busPtr))->CanShow(); break;
|
||||
case I_32_I1_TM2_3: return (static_cast<B_32_I1_TM2_3*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
@ -546,33 +558,33 @@ class PolyBus {
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
#endif
|
||||
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
case I_32_I1_TM2_3: (static_cast<B_32_I1_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
@ -616,33 +628,33 @@ class PolyBus {
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetBrightness(b); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->SetBrightness(b); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->SetBrightness(b); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetBrightness(b); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_32_I1_TM2_3: (static_cast<B_32_I1_TM2_3*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
@ -687,33 +699,33 @@ class PolyBus {
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: col = (static_cast<B_32_RN_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_3: col = (static_cast<B_32_I0_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_3: col = (static_cast<B_32_I1_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
case I_32_RN_NEO_4: col = (static_cast<B_32_RN_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_4: col = (static_cast<B_32_I0_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_4: col = (static_cast<B_32_I1_NEO_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
case I_32_RN_400_3: col = (static_cast<B_32_RN_400_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_400_3: col = (static_cast<B_32_I0_400_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_400_3: col = (static_cast<B_32_I1_400_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: col = (static_cast<B_32_RN_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_32_RN_TM2_3: col = (static_cast<B_32_RN_TM2_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_TM1_4: col = (static_cast<B_32_I0_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_32_I0_TM2_3: col = (static_cast<B_32_I0_TM2_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_TM1_4: col = (static_cast<B_32_I1_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_32_I1_TM2_3: col = (static_cast<B_32_I1_TM2_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
@ -777,33 +789,33 @@ class PolyBus {
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: delete (static_cast<B_32_RN_NEO_3*>(busPtr)); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_3: delete (static_cast<B_32_I0_NEO_3*>(busPtr)); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_3: delete (static_cast<B_32_I1_NEO_3*>(busPtr)); break;
|
||||
#endif
|
||||
case I_32_RN_NEO_4: delete (static_cast<B_32_RN_NEO_4*>(busPtr)); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_4: delete (static_cast<B_32_I0_NEO_4*>(busPtr)); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_4: delete (static_cast<B_32_I1_NEO_4*>(busPtr)); break;
|
||||
#endif
|
||||
case I_32_RN_400_3: delete (static_cast<B_32_RN_400_3*>(busPtr)); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_400_3: delete (static_cast<B_32_I0_400_3*>(busPtr)); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_400_3: delete (static_cast<B_32_I1_400_3*>(busPtr)); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: delete (static_cast<B_32_RN_TM1_4*>(busPtr)); break;
|
||||
case I_32_RN_TM2_3: delete (static_cast<B_32_RN_TM2_3*>(busPtr)); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_TM1_4: delete (static_cast<B_32_I0_TM1_4*>(busPtr)); break;
|
||||
case I_32_I0_TM2_3: delete (static_cast<B_32_I0_TM2_3*>(busPtr)); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_TM1_4: delete (static_cast<B_32_I1_TM1_4*>(busPtr)); break;
|
||||
case I_32_I1_TM2_3: delete (static_cast<B_32_I1_TM2_3*>(busPtr)); break;
|
||||
#endif
|
||||
|
@ -540,8 +540,8 @@ void deserializeConfigFromFS() {
|
||||
if (!success) { //if file does not exist, try reading from EEPROM
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
deEEPSettings();
|
||||
#endif
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!requestJSONBufferLock(1)) return;
|
||||
@ -946,6 +946,8 @@ void serializeConfig() {
|
||||
if (f) serializeJson(doc, f);
|
||||
f.close();
|
||||
releaseJSONBufferLock();
|
||||
|
||||
doSerializeConfig = false;
|
||||
}
|
||||
|
||||
//settings in /wsec.json, not accessible via webserver, for passwords and tokens
|
||||
|
@ -25,10 +25,14 @@
|
||||
#ifdef ESP8266
|
||||
#define WLED_MAX_BUSSES 3
|
||||
#else
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define WLED_MAX_BUSSES 5
|
||||
#else
|
||||
#define WLED_MAX_BUSSES 10
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
#define WLED_MAX_BUSSES 8
|
||||
#else
|
||||
#define WLED_MAX_BUSSES 10
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@ -279,11 +283,15 @@
|
||||
#endif
|
||||
|
||||
#ifndef MAX_LED_MEMORY
|
||||
#ifdef ESP8266
|
||||
#define MAX_LED_MEMORY 4000
|
||||
#else
|
||||
#define MAX_LED_MEMORY 64000
|
||||
#endif
|
||||
#ifdef ESP8266
|
||||
#define MAX_LED_MEMORY 4000
|
||||
#else
|
||||
#ifdef ARDUINO_ARCH_ESP32S2
|
||||
#define MAX_LED_MEMORY 32000
|
||||
#else
|
||||
#define MAX_LED_MEMORY 64000
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MAX_LEDS_PER_BUS
|
||||
@ -333,7 +341,8 @@
|
||||
#define JSON_BUFFER_SIZE 24576
|
||||
#endif
|
||||
|
||||
#define MIN_HEAP_SIZE (MAX_LED_MEMORY+2048)
|
||||
//#define MIN_HEAP_SIZE (MAX_LED_MEMORY+2048)
|
||||
#define MIN_HEAP_SIZE (8192)
|
||||
|
||||
// Maximum size of node map (list of other WLED instances)
|
||||
#ifdef ESP8266
|
||||
|
@ -1194,7 +1194,7 @@ TD .checkmark, TD .radiomark {
|
||||
/*filter: brightness(1);*/
|
||||
font-size: 19px;
|
||||
border-radius: 21px;
|
||||
min-width: 280px;
|
||||
/*min-width: 264px;*/
|
||||
}
|
||||
|
||||
.seg {
|
||||
|
@ -399,7 +399,7 @@ function presetError(empty)
|
||||
if (bckstr.length > 10) hasBackup = true;
|
||||
} catch (e) {}
|
||||
|
||||
var cn = `<div class="pres c" ${empty?'style="padding:8px 0;margin-top: 15px;"':'onclick="loadPresets()" style="cursor:pointer;padding:8px 0;"'}>`;
|
||||
var cn = `<div class="pres c" ${empty?'style="padding:8px;margin-top: 16px;"':'onclick="loadPresets()" style="cursor:pointer;padding:8px;margin-top: 16px;"'}>`;
|
||||
if (empty)
|
||||
cn += `You have no presets yet!`;
|
||||
else
|
||||
|
@ -23,7 +23,12 @@
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
d.um_p = [];
|
||||
d.rsvd = [];
|
||||
d.ro_pins = [];
|
||||
d.max_gpio = 39;
|
||||
GetV();checkSi();setABL();
|
||||
if (d.um_p[0]==-1) d.um_p.shift();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
@ -57,9 +62,11 @@
|
||||
//check for pin conflicts
|
||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
||||
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
||||
if (d.um_p && d.um_p.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(d.um_p)} can't be used.`);LCs[i].value="";LCs[i].focus();return false;}
|
||||
else if (LCs[i].value > 5 && LCs[i].value < 12) {alert("Sorry, pins 6-11 can not be used.");LCs[i].value="";LCs[i].focus();return false;}
|
||||
else if (!(nm == "IR" || nm=="BT") && LCs[i].value > 33) {alert("Sorry, pins >33 are input only.");LCs[i].value="";LCs[i].focus();return false;}
|
||||
var p = []; // used pin array
|
||||
for (k=0;k<d.rsvd.length;k++) p.push(d.rsvd[k]); // fill with reservations
|
||||
for (k=0;k<d.um_p.length;k++) p.push(d.um_p[k]); // fill with usermod pins
|
||||
if (p.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(p)} can't be used.`);LCs[i].value="";LCs[i].focus();return false;}
|
||||
else if (!(nm == "IR" || nm=="BT") && d.ro_pins.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(d.ro_gpio)} are input only.`);LCs[i].value="";LCs[i].focus();return false;}
|
||||
for (j=i+1; j<LCs.length; j++)
|
||||
{
|
||||
var n2 = LCs[j].name.substring(0,2);
|
||||
@ -230,7 +237,7 @@
|
||||
LCs[i].style.color="#fff";
|
||||
continue; // do not check conflicts
|
||||
} else {
|
||||
LCs[i].max = 33;
|
||||
LCs[i].max = d.max_gpio;
|
||||
LCs[i].min = -1;
|
||||
}
|
||||
}
|
||||
@ -238,7 +245,8 @@
|
||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
||||
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
||||
var p = []; // used pin array
|
||||
if (d.um_p && Array.isArray(d.um_p)) for (k=0;k<d.um_p.length;k++) p.push(d.um_p[k]); // fill with reservations
|
||||
for (k=0;k<d.rsvd.length;k++) p.push(d.rsvd[k]); // fill with reservations
|
||||
for (k=0;k<d.um_p.length;k++) p.push(d.um_p[k]); // fill with usermod pins
|
||||
for (j=0; j<LCs.length; j++) {
|
||||
if (i==j) continue;
|
||||
var n2 = LCs[j].name.substring(0,2);
|
||||
@ -252,8 +260,13 @@
|
||||
}
|
||||
}
|
||||
// now check for conflicts
|
||||
if (p.some((e)=>e==parseInt(LCs[i].value,10))) LCs[i].style.color="red"; else LCs[i].style.color=parseInt(LCs[i].value,10)>33?"orange":"#fff";
|
||||
if (p.some((e)=>e==parseInt(LCs[i].value,10))) LCs[i].style.color="red"; else LCs[i].style.color=d.ro_gpio.some((e)=>e==parseInt(LCs[i].value,10))?"orange":"#fff";
|
||||
}
|
||||
// check buttons, IR & relay
|
||||
if (nm=="IR" || nm=="BT" || nm=="RL") {
|
||||
LCs[i].max = d.max_gpio;
|
||||
LCs[i].min = -1;
|
||||
}
|
||||
}
|
||||
// update total led count
|
||||
gId("lc").textContent = sLC;
|
||||
@ -268,25 +281,25 @@
|
||||
gId('wreason').innerHTML = (bquot > 80) ? "80% of max. LED memory" +(bquot>100 ? ` (<b>ERROR: Using over ${maxM}B!</b>)` : "") : "800 LEDs per output";
|
||||
// calculate power
|
||||
var val = Math.ceil((100 + sPC * laprev)/500)/2;
|
||||
val = (val > 5) ? Math.ceil(val) : val;
|
||||
var s = "";
|
||||
val = (val > 5) ? Math.ceil(val) : val;
|
||||
var s = "";
|
||||
var is12V = (d.Sf.LAsel.value == 30);
|
||||
var isWS2815 = (d.Sf.LAsel.value == 255);
|
||||
if (val < 1.02 && !is12V && !isWS2815)
|
||||
{
|
||||
s = "ESP 5V pin with 1A USB supply";
|
||||
} else
|
||||
{
|
||||
s += is12V ? "12V ": isWS2815 ? "WS2815 12V " : "5V ";
|
||||
s += val;
|
||||
s += "A supply connected to LEDs";
|
||||
}
|
||||
if (val < 1.02 && !is12V && !isWS2815)
|
||||
{
|
||||
s = "ESP 5V pin with 1A USB supply";
|
||||
} else
|
||||
{
|
||||
s += is12V ? "12V ": isWS2815 ? "WS2815 12V " : "5V ";
|
||||
s += val;
|
||||
s += "A supply connected to LEDs";
|
||||
}
|
||||
var val2 = Math.ceil((100 + sPC * laprev)/1500)/2;
|
||||
val2 = (val2 > 5) ? Math.ceil(val2) : val2;
|
||||
var s2 = "(for most effects, ~";
|
||||
s2 += val2;
|
||||
s2 += "A is enough)<br>";
|
||||
gId('psu').innerHTML = s;
|
||||
gId('psu').innerHTML = s;
|
||||
gId('psu2').innerHTML = isWS2815 ? "" : s2;
|
||||
gId("json").style.display = d.Sf.IT.value==8 ? "" : "none";
|
||||
}
|
||||
@ -348,11 +361,11 @@ ${i+1}:
|
||||
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" class="l starts" min="0" max="8191" value="${lastEnd(i)}" oninput="startsDirty[${i}]=true;UI();" required />
|
||||
<div id="dig${i}c" style="display:inline">Length: <input type="number" name="LC${i}" class="l" min="1" max="${maxPB}" value="1" required oninput="UI()" /></div><br>
|
||||
</div>
|
||||
<span id="p0d${i}">GPIO:</span> <input type="number" name="L0${i}" min="0" max="33" required class="s" onchange="UI()"/>
|
||||
<span id="p1d${i}"></span><input type="number" name="L1${i}" min="0" max="33" class="s" onchange="UI()"/>
|
||||
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="33" class="s" onchange="UI()"/>
|
||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="33" class="s" onchange="UI()"/>
|
||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="33" class="s" onchange="UI()"/>
|
||||
<span id="p0d${i}">GPIO:</span> <input type="number" name="L0${i}" min="0" max="48" required class="s" onchange="UI()"/>
|
||||
<span id="p1d${i}"></span><input type="number" name="L1${i}" min="0" max="48" class="s" onchange="UI()"/>
|
||||
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="48" class="s" onchange="UI()"/>
|
||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="48" class="s" onchange="UI()"/>
|
||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="48" class="s" onchange="UI()"/>
|
||||
<div id="dig${i}r" style="display:inline"><br><span id="rev${i}">Reversed</span>: <input type="checkbox" name="CV${i}"></div>
|
||||
<div id="dig${i}s" style="display:inline"><br>Skip first LEDs: <input type="number" name="SL${i}" min="0" max="255" value="0" oninput="UI()"></div>
|
||||
<div id="dig${i}f" style="display:inline"><br>Off Refresh: <input id="rf${i}" type="checkbox" name="RF${i}"></div>
|
||||
@ -422,7 +435,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
||||
var c = gId("btns").innerHTML;
|
||||
var bt = "BT" + String.fromCharCode((i<10?48:55)+i);
|
||||
var be = "BE" + String.fromCharCode((i<10?48:55)+i);
|
||||
c += `Button ${i} GPIO: <input type="number" min="-1" max="40" name="${bt}" onchange="UI()" class="xs" value="${p}">`;
|
||||
c += `Button ${i} GPIO: <input type="number" min="-1" max="48" name="${bt}" onchange="UI()" class="xs" value="${p}">`;
|
||||
c += ` <select name="${be}">`
|
||||
c += `<option value="0" ${t==0?"selected":""}>Disabled</option>`;
|
||||
c += `<option value="2" ${t==2?"selected":""}>Pushbutton</option>`;
|
||||
@ -605,7 +618,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
||||
<hr style="width:260px">
|
||||
<div id="btns"></div>
|
||||
Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" required><br>
|
||||
IR GPIO: <input type="number" min="-1" max="40" name="IR" onchange="UI()" class="xs"><select name="IT" onchange="UI()">
|
||||
IR GPIO: <input type="number" min="-1" max="48" name="IR" onchange="UI()" class="xs"><select name="IT" onchange="UI()">
|
||||
<option value=0>Remote disabled</option>
|
||||
<option value=1>24-key RGB</option>
|
||||
<option value=2>24-key with CT</option>
|
||||
@ -619,7 +632,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
||||
Apply IR change to main segment only: <input type="checkbox" name="MSO"><br>
|
||||
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile('/ir.json')">Upload</button><br></div>
|
||||
<a href="https://kno.wled.ge/interfaces/infrared/" target="_blank">IR info</a><br>
|
||||
Relay GPIO: <input type="number" min="-1" max="33" name="RL" onchange="UI()" class="xs"> Invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')"> ✕</span><br>
|
||||
Relay GPIO: <input type="number" min="-1" max="48" name="RL" onchange="UI()" class="xs"> Invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')"> ✕</span><br>
|
||||
<hr style="width:260px">
|
||||
<h3>Defaults</h3>
|
||||
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
||||
|
@ -1,22 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=500">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<title>Usermod Settings</title>
|
||||
<script>
|
||||
var d = document;
|
||||
var umCfg = {};
|
||||
var pins = [6,7,8,9,10,11];
|
||||
var pinO = ["rsvd","rsvd","rsvd","rsvd","rsvd","rsvd"], owner;
|
||||
var loc = false, locip;
|
||||
var urows;
|
||||
var numM = 0;
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function isO(i) { return (i && typeof i === 'object' && !Array.isArray(i)); }
|
||||
function H() { window.open("https://github.com/Aircoookie/WLED/wiki/Settings#usermod-settings"); }
|
||||
function B() { window.open("/settings","_self"); }
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=500">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<title>Usermod Settings</title>
|
||||
<script>
|
||||
var d = document;
|
||||
var umCfg = {};
|
||||
var pins = [], pinO = [], owner;
|
||||
var loc = false, locip;
|
||||
var urows;
|
||||
var numM = 0;
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function isO(i) { return (i && typeof i === 'object' && !Array.isArray(i)); }
|
||||
function H() { window.open("https://github.com/Aircoookie/WLED/wiki/Settings#usermod-settings"); }
|
||||
function B() { window.open("/settings","_self"); }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
@ -27,7 +26,18 @@
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
d.um_p = [];
|
||||
d.rsvd = [];
|
||||
d.ro_pins = [];
|
||||
d.max_gpio = 39;
|
||||
GetV();
|
||||
for (let k=0; k<d.rsvd.length; k++) { pins.push(d.rsvd[k]); pinO.push("rsvd"); }
|
||||
if (d.um_p[0]==-1) d.um_p.shift();
|
||||
d.Sf.SDA.max = d.max_gpio;
|
||||
d.Sf.SCL.max = d.max_gpio;
|
||||
d.Sf.MOSI.max = d.max_gpio;
|
||||
d.Sf.SCLK.max = d.max_gpio;
|
||||
d.Sf.MISO.max = d.max_gpio;
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
@ -35,182 +45,182 @@
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
ldS();
|
||||
if (!numM) gId("um").innerHTML = "No Usermods installed.";
|
||||
}
|
||||
// https://stackoverflow.com/questions/3885817/how-do-i-check-that-a-number-is-float-or-integer
|
||||
function isF(n) { return n === +n && n !== (n|0); }
|
||||
function isI(n) { return n === +n && n === (n|0); }
|
||||
function check(o,k) { // input object, pin owner key
|
||||
var n = o.name.replace("[]","").substr(-3);
|
||||
if (o.type=="number" && n.substr(0,3)=="pin") {
|
||||
for (var i=0; i<pins.length; i++) {
|
||||
if (k==pinO[i]) continue;
|
||||
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
|
||||
if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff";
|
||||
}
|
||||
} else {
|
||||
switch (o.name) {
|
||||
case "SDA": break;
|
||||
case "SCL": break;
|
||||
case "MOSI": break;
|
||||
case "SCLK": break;
|
||||
case "CS": break;
|
||||
default: return;
|
||||
}
|
||||
for (var i=0; i<pins.length; i++) {
|
||||
if (k==pinO[i]) continue;
|
||||
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
|
||||
if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff";
|
||||
}
|
||||
}
|
||||
}
|
||||
function getPins(o) {
|
||||
if (isO(o)) {
|
||||
for (const [k,v] of Object.entries(o)) {
|
||||
if (isO(v)) {
|
||||
owner = k;
|
||||
getPins(v);
|
||||
continue;
|
||||
}
|
||||
if (k.replace("[]","").substr(-3)=="pin") {
|
||||
if (Array.isArray(v)) {
|
||||
for (var i=0; i<v.length; i++) if (v[i]>=0) { pins.push(v[i]); pinO.push(owner); }
|
||||
} else {
|
||||
if (v>=0) { pins.push(v); pinO.push(owner); }
|
||||
}
|
||||
} else if (Array.isArray(v)) {
|
||||
for (var i=0; i<v.length; i++) getPins(v[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function addField(k,f,o,a=false) { //key, field, (sub)object, isArray
|
||||
if (isO(o)) {
|
||||
urows += '<hr style="width:260px">';
|
||||
for (const [s,v] of Object.entries(o)) {
|
||||
// possibility to nest objects (only 1 level)
|
||||
if (f!=='unknown' && !k.includes(":")) addField(k+":"+f,s,v);
|
||||
else addField(k,s,v);
|
||||
}
|
||||
} else if (Array.isArray(o)) {
|
||||
for (var j=0; j<o.length; j++) {
|
||||
addField(k,f,o[j],true);
|
||||
}
|
||||
} else {
|
||||
var c, t = typeof o;
|
||||
switch (t) {
|
||||
case "boolean":
|
||||
t = "checkbox"; c = 'value="true"' + (o ? ' checked' : '');
|
||||
break;
|
||||
case "number":
|
||||
c = `value="${o}"`;
|
||||
if (f.substr(-3)==="pin") {
|
||||
c += ' max="39" min="-1" class="s"';
|
||||
t = "int";
|
||||
} else {
|
||||
c += ' step="any" class="xxl"';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
t = "text"; c = `value="${o}" style="width:250px;"`;
|
||||
break;
|
||||
}
|
||||
if (k.includes(":")) urows += k.substr(k.indexOf(":")+1);
|
||||
urows += ` ${f}: `;
|
||||
// https://stackoverflow.com/questions/11657123/posting-both-checked-and-unchecked-checkboxes
|
||||
if (t=="checkbox") urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="false">`;
|
||||
else if (!a) urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="${t}">`;
|
||||
urows += `<input type="${t==="int"?"number":t}" name="${k}:${f}${a?"[]":""}" ${c} oninput="check(this,'${k.substr(k.indexOf(":")+1)}')"><br>`;
|
||||
}
|
||||
}
|
||||
// https://stackoverflow.com/questions/39729741/javascript-change-input-text-to-select-option
|
||||
function addDropdown(um,fld) {
|
||||
let sel = d.createElement('select');
|
||||
let arr = d.getElementsByName(um+":"+fld);
|
||||
let inp = arr[1]; // assume 1st field to be hidden (type)
|
||||
if (inp && inp.tagName === "INPUT" && (inp.type === "text" || inp.type === "number")) { // may also use nodeName
|
||||
let v = inp.value;
|
||||
let n = inp.name;
|
||||
// copy the existing input element's attributes to the new select element
|
||||
for (var i = 0; i < inp.attributes.length; ++ i) {
|
||||
var att = inp.attributes[i];
|
||||
// type and value don't apply, so skip them
|
||||
// ** you might also want to skip style, or others -- modify as needed **
|
||||
if (att.name != 'type' && att.name != 'value' && att.name != 'class' && att.name != 'style') {
|
||||
sel.setAttribute(att.name, att.value);
|
||||
}
|
||||
}
|
||||
sel.setAttribute("data-val", v);
|
||||
// finally, replace the old input element with the new select element
|
||||
inp.parentElement.replaceChild(sel, inp);
|
||||
return sel;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function addOption(sel,txt,val) {
|
||||
if (sel===null) return; // select object missing
|
||||
let opt = d.createElement("option");
|
||||
opt.value = val;
|
||||
opt.text = txt;
|
||||
sel.appendChild(opt);
|
||||
for (let i=0; i<sel.childNodes.length; i++) {
|
||||
let c = sel.childNodes[i];
|
||||
if (c.value == sel.dataset.val) sel.selectedIndex = i;
|
||||
}
|
||||
}
|
||||
// https://stackoverflow.com/questions/26440494/insert-text-after-this-input-element-with-javascript
|
||||
function addInfo(name,el,txt) {
|
||||
let obj = d.getElementsByName(name);
|
||||
if (!obj.length) return;
|
||||
if (typeof el === "string" && obj[0]) obj[0].placeholder = el;
|
||||
else if (obj[el]) obj[el].insertAdjacentHTML('afterend', ' '+txt);
|
||||
}
|
||||
// load settings and insert values into DOM
|
||||
function ldS() {
|
||||
var url = (loc?`http://${locip}`:'') + '/cfg.json';
|
||||
fetch(url, {
|
||||
method: 'get'
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) gId('lserr').style.display = "inline";
|
||||
return res.json();
|
||||
})
|
||||
.then(json => {
|
||||
umCfg = json.um;
|
||||
getPins(json);
|
||||
urows="";
|
||||
if (isO(umCfg)) {
|
||||
for (const [k,o] of Object.entries(umCfg)) {
|
||||
urows += `<hr><h3>${k}</h3>`;
|
||||
addField(k,'unknown',o);
|
||||
}
|
||||
}
|
||||
if (urows==="") urows = "Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults.";
|
||||
gId("um").innerHTML = urows;
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=8';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
})
|
||||
.catch((error)=>{
|
||||
gId('lserr').style.display = "inline";
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
function svS(e) {
|
||||
e.preventDefault();
|
||||
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
function S() {
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
ldS();
|
||||
if (!numM) gId("um").innerHTML = "No Usermods installed.";
|
||||
}
|
||||
// https://stackoverflow.com/questions/3885817/how-do-i-check-that-a-number-is-float-or-integer
|
||||
function isF(n) { return n === +n && n !== (n|0); }
|
||||
function isI(n) { return n === +n && n === (n|0); }
|
||||
function check(o,k) { // input object, pin owner key
|
||||
var n = o.name.replace("[]","").substr(-3);
|
||||
if (o.type=="number" && n.substr(0,3)=="pin") {
|
||||
for (var i=0; i<pins.length; i++) {
|
||||
if (k==pinO[i]) continue;
|
||||
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
|
||||
if (o.value==pins[i] || o.value<-1 || o.value>d.max_gpio) { o.style.color="red"; break; } else o.style.color=d.ro_gpio.some((e)=>e==parseInt(o.value,10))?"orange":"#fff";
|
||||
}
|
||||
} else {
|
||||
switch (o.name) {
|
||||
case "SDA": break;
|
||||
case "SCL": break;
|
||||
case "MOSI": break;
|
||||
case "SCLK": break;
|
||||
case "MISO": break;
|
||||
default: return;
|
||||
}
|
||||
for (var i=0; i<pins.length; i++) {
|
||||
//if (k==pinO[i]) continue; // same owner
|
||||
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="tomato"; break; }
|
||||
if (o.value==pins[i] || o.value<-1 || o.value>d.max_gpio) { o.style.color="red"; break; } else o.style.color=d.ro_gpio.some((e)=>e==parseInt(o.value,10))?"orange":"#fff";
|
||||
}
|
||||
}
|
||||
}
|
||||
function getPins(o) {
|
||||
if (isO(o)) {
|
||||
for (const [k,v] of Object.entries(o)) {
|
||||
if (isO(v)) {
|
||||
owner = k;
|
||||
getPins(v);
|
||||
continue;
|
||||
}
|
||||
if (k.replace("[]","").substr(-3)=="pin") {
|
||||
if (Array.isArray(v)) {
|
||||
for (var i=0; i<v.length; i++) if (v[i]>=0) { pins.push(v[i]); pinO.push(owner); }
|
||||
} else {
|
||||
if (v>=0) { pins.push(v); pinO.push(owner); }
|
||||
}
|
||||
} else if (Array.isArray(v)) {
|
||||
for (var i=0; i<v.length; i++) getPins(v[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function addField(k,f,o,a=false) { //key, field, (sub)object, isArray
|
||||
if (isO(o)) {
|
||||
urows += '<hr style="width:260px">';
|
||||
for (const [s,v] of Object.entries(o)) {
|
||||
// possibility to nest objects (only 1 level)
|
||||
if (f!=='unknown' && !k.includes(":")) addField(k+":"+f,s,v);
|
||||
else addField(k,s,v);
|
||||
}
|
||||
} else if (Array.isArray(o)) {
|
||||
for (var j=0; j<o.length; j++) {
|
||||
addField(k,f,o[j],true);
|
||||
}
|
||||
} else {
|
||||
var c, t = typeof o;
|
||||
switch (t) {
|
||||
case "boolean":
|
||||
t = "checkbox"; c = 'value="true"' + (o ? ' checked' : '');
|
||||
break;
|
||||
case "number":
|
||||
c = `value="${o}"`;
|
||||
if (f.substr(-3)==="pin") {
|
||||
c += ` max="${d.max_gpio}" min="-1" class="s"`;
|
||||
t = "int";
|
||||
} else {
|
||||
c += ' step="any" class="xxl"';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
t = "text"; c = `value="${o}" style="width:250px;"`;
|
||||
break;
|
||||
}
|
||||
if (k.includes(":")) urows += k.substr(k.indexOf(":")+1);
|
||||
urows += ` ${f}: `;
|
||||
// https://stackoverflow.com/questions/11657123/posting-both-checked-and-unchecked-checkboxes
|
||||
if (t=="checkbox") urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="false">`;
|
||||
else if (!a) urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="${t}">`;
|
||||
urows += `<input type="${t==="int"?"number":t}" name="${k}:${f}${a?"[]":""}" ${c} oninput="check(this,'${k.substr(k.indexOf(":")+1)}')"><br>`;
|
||||
}
|
||||
}
|
||||
// https://stackoverflow.com/questions/39729741/javascript-change-input-text-to-select-option
|
||||
function addDropdown(um,fld) {
|
||||
let sel = d.createElement('select');
|
||||
let arr = d.getElementsByName(um+":"+fld);
|
||||
let inp = arr[1]; // assume 1st field to be hidden (type)
|
||||
if (inp && inp.tagName === "INPUT" && (inp.type === "text" || inp.type === "number")) { // may also use nodeName
|
||||
let v = inp.value;
|
||||
let n = inp.name;
|
||||
// copy the existing input element's attributes to the new select element
|
||||
for (var i = 0; i < inp.attributes.length; ++ i) {
|
||||
var att = inp.attributes[i];
|
||||
// type and value don't apply, so skip them
|
||||
// ** you might also want to skip style, or others -- modify as needed **
|
||||
if (att.name != 'type' && att.name != 'value' && att.name != 'class' && att.name != 'style') {
|
||||
sel.setAttribute(att.name, att.value);
|
||||
}
|
||||
}
|
||||
sel.setAttribute("data-val", v);
|
||||
// finally, replace the old input element with the new select element
|
||||
inp.parentElement.replaceChild(sel, inp);
|
||||
return sel;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function addOption(sel,txt,val) {
|
||||
if (sel===null) return; // select object missing
|
||||
let opt = d.createElement("option");
|
||||
opt.value = val;
|
||||
opt.text = txt;
|
||||
sel.appendChild(opt);
|
||||
for (let i=0; i<sel.childNodes.length; i++) {
|
||||
let c = sel.childNodes[i];
|
||||
if (c.value == sel.dataset.val) sel.selectedIndex = i;
|
||||
}
|
||||
}
|
||||
// https://stackoverflow.com/questions/26440494/insert-text-after-this-input-element-with-javascript
|
||||
function addInfo(name,el,txt) {
|
||||
let obj = d.getElementsByName(name);
|
||||
if (!obj.length) return;
|
||||
if (typeof el === "string" && obj[0]) obj[0].placeholder = el;
|
||||
else if (obj[el]) obj[el].insertAdjacentHTML('afterend', ' '+txt);
|
||||
}
|
||||
// load settings and insert values into DOM
|
||||
function ldS() {
|
||||
var url = (loc?`http://${locip}`:'') + '/cfg.json';
|
||||
fetch(url, {
|
||||
method: 'get'
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) gId('lserr').style.display = "inline";
|
||||
return res.json();
|
||||
})
|
||||
.then(json => {
|
||||
umCfg = json.um;
|
||||
getPins(json);
|
||||
urows="";
|
||||
if (isO(umCfg)) {
|
||||
for (const [k,o] of Object.entries(umCfg)) {
|
||||
urows += `<hr><h3>${k}</h3>`;
|
||||
addField(k,'unknown',o);
|
||||
}
|
||||
}
|
||||
if (urows==="") urows = "Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults.";
|
||||
gId("um").innerHTML = urows;
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=8';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
})
|
||||
.catch((error)=>{
|
||||
gId('lserr').style.display = "inline";
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
function svS(e) {
|
||||
e.preventDefault();
|
||||
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
|
||||
<body onload="S()">
|
||||
@ -222,17 +232,17 @@
|
||||
<span id="lserr" style="color:red; display:none">⚠ Could not load configuration.</span><hr>
|
||||
</div>
|
||||
<h2>Usermod Setup</h2>
|
||||
Global I<sup>2</sup>C GPIOs (HW)<br>
|
||||
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
||||
SDA:<input type="number" min="-1" max="33" name="SDA" onchange="check(this,'if')" class="s" placeholder="SDA">
|
||||
SCL:<input type="number" min="-1" max="33" name="SCL" onchange="check(this,'if')" class="s" placeholder="SCL">
|
||||
<hr style="width:260px">
|
||||
Global SPI GPIOs (HW)<br>
|
||||
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
||||
MOSI:<input type="number" min="-1" max="33" name="MOSI" onchange="check(this,'if')" class="s" placeholder="MOSI">
|
||||
MISO:<input type="number" min="-1" max="33" name="MISO" onchange="check(this,'if')" class="s" placeholder="MISO">
|
||||
SCLK:<input type="number" min="-1" max="33" name="SCLK" onchange="check(this,'if')" class="s" placeholder="SCLK">
|
||||
<div id="um">Loading settings...</div>
|
||||
Global I<sup>2</sup>C GPIOs (HW)<br>
|
||||
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
||||
SDA:<input type="number" min="-1" max="48" name="SDA" onchange="check(this,'if')" class="s" placeholder="SDA">
|
||||
SCL:<input type="number" min="-1" max="48" name="SCL" onchange="check(this,'if')" class="s" placeholder="SCL">
|
||||
<hr style="width:260px">
|
||||
Global SPI GPIOs (HW)<br>
|
||||
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
||||
MOSI:<input type="number" min="-1" max="48" name="MOSI" onchange="check(this,'if')" class="s" placeholder="MOSI">
|
||||
MISO:<input type="number" min="-1" max="48" name="MISO" onchange="check(this,'if')" class="s" placeholder="MISO">
|
||||
SCLK:<input type="number" min="-1" max="48" name="SCLK" onchange="check(this,'if')" class="s" placeholder="SCLK">
|
||||
<div id="um">Loading settings...</div>
|
||||
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
|
@ -191,8 +191,8 @@ int16_t loadPlaylist(JsonObject playlistObject, byte presetId = 0);
|
||||
void handlePlaylist();
|
||||
|
||||
//presets.cpp
|
||||
void handlePresets(bool force = false);
|
||||
bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE, bool fromJson = false);
|
||||
void handlePresets();
|
||||
bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE);
|
||||
inline bool applyTemporaryPreset() {return applyPreset(255);};
|
||||
void savePreset(byte index, const char* pname = nullptr, JsonObject saveobj = JsonObject());
|
||||
inline void saveTemporaryPreset() {savePreset(255);};
|
||||
|
File diff suppressed because it is too large
Load Diff
2763
wled00/html_ui.h
2763
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -728,7 +728,7 @@ void handleIR()
|
||||
{
|
||||
if (results.value != 0) // only print results if anything is received ( != 0 )
|
||||
{
|
||||
if (!pinManager.isPinAllocated(1) || pinManager.getPinOwner(1) == PinOwner::DebugOut) //GPIO 1 - Serial TX pin
|
||||
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut) // Serial TX pin (GPIO 1 on ESP32 and ESP8266)
|
||||
Serial.printf_P(PSTR("IR recv: 0x%lX\n"), (unsigned long)results.value);
|
||||
}
|
||||
decodeIR(results.value);
|
||||
|
@ -680,7 +680,11 @@ void serializeInfo(JsonObject root)
|
||||
wifi_info[F("txPower")] = (int) WiFi.getTxPower();
|
||||
wifi_info[F("sleep")] = (bool) WiFi.getSleep();
|
||||
#endif
|
||||
root[F("arch")] = "esp32";
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
root[F("arch")] = "esp32";
|
||||
#else
|
||||
root[F("arch")] = ESP.getChipModel();
|
||||
#endif
|
||||
root[F("core")] = ESP.getSdkVersion();
|
||||
//root[F("maxalloc")] = ESP.getMaxAllocHeap();
|
||||
#ifdef WLED_DEBUG
|
||||
|
@ -160,7 +160,23 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
|
||||
{
|
||||
// HW I2C & SPI pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair
|
||||
if (!isPinOk(gpio, output) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) return false;
|
||||
if (!isPinOk(gpio, output) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) {
|
||||
#ifdef WLED_DEBUG
|
||||
if (gpio < 255) { // 255 (-1) is the "not defined GPIO"
|
||||
if (!isPinOk(gpio, output)) {
|
||||
DEBUG_PRINT(F("PIN ALLOC: FAIL for owner "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
DEBUG_PRINT(F(": GPIO ")); DEBUG_PRINT(gpio);
|
||||
if (output) DEBUG_PRINTLN(F(" cannot be used for i/o on this MCU."));
|
||||
else DEBUG_PRINTLN(F(" cannot be used as input on this MCU."));
|
||||
} else {
|
||||
DEBUG_PRINT(F("PIN ALLOC: FAIL: GPIO ")); DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINTLN(F(" - HW I2C & SPI pins have to be allocated using allocateMultiplePins()"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if (isPinAllocated(gpio)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Pin "));
|
||||
@ -179,7 +195,7 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Pin "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" allocated by "));
|
||||
DEBUG_PRINT(F(" successfully allocated by "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
DEBUG_PRINTLN(F(""));
|
||||
#endif
|
||||
@ -198,6 +214,45 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag)
|
||||
return bitRead(pinAlloc[by], bi);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
// ESP32-S3 GPIO layout
|
||||
/* see https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/gpio.html
|
||||
* The ESP32-S3 chip features 45 physical GPIO pins (GPIO0 ~ GPIO21 and GPIO26 ~ GPIO48). Each pin can be used as a general-purpose I/O
|
||||
* Strapping pins: GPIO0, GPIO3, GPIO45 and GPIO46 are strapping pins. For more infomation, please refer to ESP32-S3 datasheet.
|
||||
* Serial TX = GPIO43, RX = GPIO44; LED BUILTIN is usually GPIO39
|
||||
* USB-JTAG: GPIO 19 and 20 are used by USB-JTAG by default. In order to use them as GPIOs, USB-JTAG will be disabled by the drivers.
|
||||
* SPI0/1: GPIO26-32 are usually used for SPI flash and PSRAM and not recommended for other uses.
|
||||
* When using Octal Flash or Octal PSRAM or both, GPIO33~37 are connected to SPIIO4 ~ SPIIO7 and SPIDQS. Therefore, on boards embedded with ESP32-S3R8 / ESP32-S3R8V chip, GPIO33~37 are also not recommended for other uses.
|
||||
*
|
||||
* see https://docs.espressif.com/projects/esp-idf/en/v4.4.2/esp32s3/api-reference/peripherals/adc.html
|
||||
* https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/adc_oneshot.html
|
||||
* ADC1: GPIO1 - GPIO10 (channel 0..9)
|
||||
* ADC2: GPIO11 - GPIO20 (channel 0..9)
|
||||
* adc_power_acquire(): Please do not use the interrupt of GPIO36 and GPIO39 when using ADC or Wi-Fi and Bluetooth with sleep mode enabled. As a workaround, call adc_power_acquire() in the APP.
|
||||
* Since the ADC2 module is also used by the Wi-Fi, reading operation of adc2_get_raw() may fail between esp_wifi_start() and esp_wifi_stop(). Use the return code to see whether the reading is successful.
|
||||
*/
|
||||
bool PinManagerClass::isPinOk(byte gpio, bool output)
|
||||
{
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
if ((gpio > 10) && (gpio < 18)) return false; // 11-17 SPI FLASH
|
||||
if (gpio < 22) return true;
|
||||
#else // S2 & S3
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
if (gpio < 19) return true; // 00 to 18 are for general use. Be careful about straping pins GPIO0 and GPIO3 - these may be pulled-up or pulled-down on your board.
|
||||
if (gpio < 21) return false; // 19 + 20 = USB-JTAG. Not recommended for other uses.
|
||||
if ((gpio > 21) && (gpio < 33)) return false; // 22 to 32: not connected + SPI FLASH
|
||||
//if (gpio <38) return false; // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM
|
||||
if (gpio < 49) return true; // 38 to 48 are for general use. Be careful about straping pins GPIO45 and GPIO46 - these may be pull-up or pulled-down on your board.
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
if (gpio < 22) return true; // 00 to 21 are for general use.
|
||||
if ((gpio > 21) && (gpio < 33)) return false; // 22 to 32: not connected + SPI FLASH
|
||||
if (gpio < 46) return true; // 33 to 45 are for general use.
|
||||
if (gpio == 46 && !output) return true; // 46 input only
|
||||
#endif
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#else // ESP32 and ESP8266 GPIO layout
|
||||
bool PinManagerClass::isPinOk(byte gpio, bool output)
|
||||
{
|
||||
if (gpio < 6) return true;
|
||||
@ -212,6 +267,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
PinOwner PinManagerClass::getPinOwner(byte gpio) {
|
||||
if (!isPinOk(gpio, false)) return PinOwner::None;
|
||||
@ -219,11 +275,20 @@ PinOwner PinManagerClass::getPinOwner(byte gpio) {
|
||||
}
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define MAX_LED_CHANNELS 6
|
||||
#else
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
#define MAX_LED_CHANNELS 8
|
||||
#else
|
||||
#define MAX_LED_CHANNELS 16
|
||||
#endif
|
||||
#endif
|
||||
byte PinManagerClass::allocateLedc(byte channels)
|
||||
{
|
||||
if (channels > 16 || channels == 0) return 255;
|
||||
if (channels > MAX_LED_CHANNELS || channels == 0) return 255;
|
||||
byte ca = 0;
|
||||
for (byte i = 0; i < 16; i++) {
|
||||
for (byte i = 0; i < MAX_LED_CHANNELS; i++) {
|
||||
byte by = i >> 3;
|
||||
byte bi = i - 8*by;
|
||||
if (bitRead(ledcAlloc[by], bi)) { //found occupied pin
|
||||
@ -248,7 +313,7 @@ byte PinManagerClass::allocateLedc(byte channels)
|
||||
void PinManagerClass::deallocateLedc(byte pos, byte channels)
|
||||
{
|
||||
for (byte j = pos; j < pos + channels; j++) {
|
||||
if (j > 16) return;
|
||||
if (j > MAX_LED_CHANNELS) return;
|
||||
byte by = j >> 3;
|
||||
byte bi = j - 8*by;
|
||||
bitWrite(ledcAlloc[by], bi, false);
|
||||
|
@ -11,33 +11,43 @@ static char *tmpRAMbuffer = nullptr;
|
||||
static volatile byte presetToApply = 0;
|
||||
static volatile byte callModeToApply = 0;
|
||||
|
||||
bool applyPreset(byte index, byte callMode, bool fromJson)
|
||||
bool applyPreset(byte index, byte callMode)
|
||||
{
|
||||
DEBUG_PRINT(F("Request to apply preset: "));
|
||||
DEBUG_PRINTLN(index);
|
||||
presetToApply = index;
|
||||
callModeToApply = callMode;
|
||||
/*
|
||||
// the following is needed in case of HTTP JSON API call to return correct state to the caller
|
||||
// fromJson is true in case when deserializeState() was called with presetId==0
|
||||
if (fromJson) handlePresets(true); // force immediate processing
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
void handlePresets(bool force)
|
||||
void handlePresets()
|
||||
{
|
||||
bool changePreset = false;
|
||||
uint8_t tmpPreset = presetToApply; // store temporary since deserializeState() may call applyPreset()
|
||||
uint8_t tmpMode = callModeToApply;
|
||||
|
||||
if (tmpPreset == 0 || (fileDoc && !force)) return; // JSON buffer already allocated and not force apply or no preset waiting
|
||||
if (tmpPreset == 0 || (fileDoc /*&& !force*/)) return; // JSON buffer already allocated and not force apply or no preset waiting
|
||||
|
||||
JsonObject fdo;
|
||||
const char *filename = tmpPreset < 255 ? "/presets.json" : "/tmp.json";
|
||||
|
||||
/*
|
||||
* The following code is no longer needed as handlePreset() is never run from
|
||||
* network callback.
|
||||
* **************************************************************************
|
||||
*
|
||||
//crude way to determine if this was called by a network request
|
||||
uint8_t core = 1;
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
core = xPortGetCoreID();
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
// this does not make sense on single core
|
||||
core = xPortGetCoreID();
|
||||
#endif
|
||||
#endif
|
||||
//only allow use of fileDoc from the core responsible for network requests (AKA HTTP JSON API)
|
||||
//do not use active network request doc from preset called by main loop (playlist, schedule, ...)
|
||||
@ -77,7 +87,7 @@ void handlePresets(bool force)
|
||||
}
|
||||
|
||||
if (force) return; // something went wrong with force option (most likely WS request), quit and wait for async load
|
||||
|
||||
*/
|
||||
// allocate buffer
|
||||
if (!requestJSONBufferLock(9)) return; // will also assign fileDoc
|
||||
|
||||
|
@ -478,8 +478,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (!requestJSONBufferLock(5)) return;
|
||||
|
||||
// global I2C & SPI pins
|
||||
int8_t hw_sda_pin = !request->arg(F("SDA")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SDA")).toInt()));
|
||||
int8_t hw_scl_pin = !request->arg(F("SCL")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SCL")).toInt()));
|
||||
int8_t hw_sda_pin = !request->arg(F("SDA")).length() ? -1 : (int)request->arg(F("SDA")).toInt();
|
||||
int8_t hw_scl_pin = !request->arg(F("SCL")).length() ? -1 : (int)request->arg(F("SCL")).toInt();
|
||||
#ifdef ESP8266
|
||||
// cannot change pins on ESP8266
|
||||
if (hw_sda_pin >= 0 && hw_sda_pin != HW_PIN_SDA) hw_sda_pin = HW_PIN_SDA;
|
||||
@ -501,9 +501,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
i2c_sda = -1;
|
||||
i2c_scl = -1;
|
||||
}
|
||||
int8_t hw_mosi_pin = !request->arg(F("MOSI")).length() ? -1 : max(-1,min(33,(int)request->arg(F("MOSI")).toInt()));
|
||||
int8_t hw_miso_pin = !request->arg(F("MISO")).length() ? -1 : max(-1,min(33,(int)request->arg(F("MISO")).toInt()));
|
||||
int8_t hw_sclk_pin = !request->arg(F("SCLK")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SCLK")).toInt()));
|
||||
int8_t hw_mosi_pin = !request->arg(F("MOSI")).length() ? -1 : (int)request->arg(F("MOSI")).toInt();
|
||||
int8_t hw_miso_pin = !request->arg(F("MISO")).length() ? -1 : (int)request->arg(F("MISO")).toInt();
|
||||
int8_t hw_sclk_pin = !request->arg(F("SCLK")).length() ? -1 : (int)request->arg(F("SCLK")).toInt();
|
||||
#ifdef ESP8266
|
||||
// cannot change pins on ESP8266
|
||||
if (hw_mosi_pin >= 0 && hw_mosi_pin != HW_PIN_DATASPI) hw_mosi_pin = HW_PIN_DATASPI;
|
||||
@ -607,7 +607,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
}
|
||||
}
|
||||
usermods.readFromConfig(um); // force change of usermod parameters
|
||||
|
||||
DEBUG_PRINTLN(F("Done re-init usermods."));
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
|
||||
@ -638,7 +638,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
#endif
|
||||
|
||||
lastEditTime = millis();
|
||||
if (subPage != 2 && !doReboot) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init)
|
||||
if (subPage != 2 && !doReboot) doSerializeConfig = true; //serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init)
|
||||
if (subPage == 4) alexaInit();
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,8 @@ void WLED::loop()
|
||||
|
||||
yield();
|
||||
|
||||
if (doSerializeConfig) serializeConfig();
|
||||
|
||||
if (doReboot && !doInitBusses) // if busses have to be inited & saved, wait until next iteration
|
||||
reset();
|
||||
|
||||
@ -265,6 +267,9 @@ void WLED::setup()
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.setTimeout(50);
|
||||
#if defined(WLED_DEBUG) && (defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3))
|
||||
delay(2500); // allow CDC USB serial to initialise
|
||||
#endif
|
||||
DEBUG_PRINTLN();
|
||||
DEBUG_PRINT(F("---WLED "));
|
||||
DEBUG_PRINT(versionString);
|
||||
@ -274,6 +279,31 @@ void WLED::setup()
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
DEBUG_PRINT(F("esp32 "));
|
||||
DEBUG_PRINTLN(ESP.getSdkVersion());
|
||||
#if defined(ESP_ARDUINO_VERSION)
|
||||
//DEBUG_PRINTF(F("arduino-esp32 0x%06x\n"), ESP_ARDUINO_VERSION);
|
||||
DEBUG_PRINTF("arduino-esp32 v%d.%d.%d\n", int(ESP_ARDUINO_VERSION_MAJOR), int(ESP_ARDUINO_VERSION_MINOR), int(ESP_ARDUINO_VERSION_PATCH)); // availeable since v2.0.0
|
||||
#else
|
||||
DEBUG_PRINTLN(F("arduino-esp32 v1.0.x\n")); // we can't say in more detail.
|
||||
#endif
|
||||
|
||||
DEBUG_PRINT(F("CPU: ")); DEBUG_PRINT(ESP.getChipModel());
|
||||
DEBUG_PRINT(F(" rev.")); DEBUG_PRINT(ESP.getChipRevision());
|
||||
DEBUG_PRINT(F(", ")); DEBUG_PRINT(ESP.getChipCores()); DEBUG_PRINT(F(" core(s)"));
|
||||
DEBUG_PRINT(F(", ")); DEBUG_PRINT(ESP.getCpuFreqMHz()); DEBUG_PRINTLN(F("MHz."));
|
||||
DEBUG_PRINT(F("FLASH: ")); DEBUG_PRINT((ESP.getFlashChipSize()/1024)/1024);
|
||||
DEBUG_PRINT(F("MB, Mode ")); DEBUG_PRINT(ESP.getFlashChipMode());
|
||||
#ifdef WLED_DEBUG
|
||||
switch (ESP.getFlashChipMode()) {
|
||||
// missing: Octal modes
|
||||
case FM_QIO: DEBUG_PRINT(F(" (QIO)")); break;
|
||||
case FM_QOUT: DEBUG_PRINT(F(" (QOUT)"));break;
|
||||
case FM_DIO: DEBUG_PRINT(F(" (DIO)")); break;
|
||||
case FM_DOUT: DEBUG_PRINT(F(" (DOUT)"));break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
DEBUG_PRINT(F(", speed ")); DEBUG_PRINT(ESP.getFlashChipSpeed()/1000000);DEBUG_PRINTLN(F("MHz."));
|
||||
|
||||
#else
|
||||
DEBUG_PRINT(F("esp8266 "));
|
||||
DEBUG_PRINTLN(ESP.getCoreVersion());
|
||||
@ -283,17 +313,29 @@ void WLED::setup()
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound()) {
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// GPIO16/GPIO17 reserved for SPI RAM
|
||||
managed_pin_type pins[2] = { {16, true}, {17, true} };
|
||||
pinManager.allocateMultiplePins(pins, 2, PinOwner::SPI_RAM);
|
||||
}
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// S3: add GPIO 33-37 for "octal" PSRAM
|
||||
managed_pin_type pins[5] = { {33, true}, {34, true}, {35, true}, {36, true}, {37, true} };
|
||||
pinManager.allocateMultiplePins(pins, 5, PinOwner::SPI_RAM);
|
||||
#endif
|
||||
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
|
||||
DEBUG_PRINT(F("Free PSRAM : ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
|
||||
} else
|
||||
DEBUG_PRINTLN(F("No PSRAM found."));
|
||||
#endif
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && !defined(WLED_USE_PSRAM)
|
||||
DEBUG_PRINTLN(F("PSRAM not used."));
|
||||
#endif
|
||||
|
||||
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
|
||||
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
pinManager.allocatePin(1, true, PinOwner::DebugOut); // GPIO1 reserved for debug output
|
||||
pinManager.allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output
|
||||
#endif
|
||||
#ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin
|
||||
pinManager.allocatePin(2, true, PinOwner::DMX);
|
||||
@ -320,6 +362,7 @@ void WLED::setup()
|
||||
#endif
|
||||
updateFSInfo();
|
||||
|
||||
strcpy_P(apSSID, PSTR("WLED-AP")); // otherwise it is empty on first boot until config is saved
|
||||
DEBUG_PRINTLN(F("Reading config"));
|
||||
deserializeConfigFromFS();
|
||||
|
||||
@ -348,7 +391,7 @@ void WLED::setup()
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
//Serial RX (Adalight, Improv, Serial JSON) only possible if GPIO3 unused
|
||||
//Serial TX (Debug, Improv, Serial JSON) only possible if GPIO1 unused
|
||||
if (!pinManager.isPinAllocated(3) && !pinManager.isPinAllocated(1)) {
|
||||
if (!pinManager.isPinAllocated(hardwareRX) && !pinManager.isPinAllocated(hardwareTX)) {
|
||||
Serial.println(F("Ada"));
|
||||
}
|
||||
#endif
|
||||
@ -357,25 +400,16 @@ void WLED::setup()
|
||||
escapedMac = WiFi.macAddress();
|
||||
escapedMac.replace(":", "");
|
||||
escapedMac.toLowerCase();
|
||||
if (strcmp(cmDNS, "x") == 0) // fill in unique mdns default
|
||||
{
|
||||
strcpy_P(cmDNS, PSTR("wled-"));
|
||||
sprintf(cmDNS + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
if (mqttDeviceTopic[0] == 0) {
|
||||
strcpy_P(mqttDeviceTopic, PSTR("wled/"));
|
||||
sprintf(mqttDeviceTopic + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
if (mqttClientID[0] == 0) {
|
||||
strcpy_P(mqttClientID, PSTR("WLED-"));
|
||||
sprintf(mqttClientID + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
// fill in unique mdns default
|
||||
if (strcmp(cmDNS, "x") == 0) sprintf_P(cmDNS, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6);
|
||||
if (mqttDeviceTopic[0] == 0) sprintf_P(mqttDeviceTopic, PSTR("wled/%*s"), 6, escapedMac.c_str() + 6);
|
||||
if (mqttClientID[0] == 0) sprintf_P(mqttClientID, PSTR("WLED-%*s"), 6, escapedMac.c_str() + 6);
|
||||
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
if (Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket();
|
||||
#endif
|
||||
|
||||
strip.service();
|
||||
strip.service(); // why?
|
||||
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled) {
|
||||
@ -443,10 +477,10 @@ void WLED::initAP(bool resetAP)
|
||||
if (apBehavior == AP_BEHAVIOR_BUTTON_ONLY && !resetAP)
|
||||
return;
|
||||
|
||||
if (!apSSID[0] || resetAP)
|
||||
if (resetAP) {
|
||||
strcpy_P(apSSID, PSTR("WLED-AP"));
|
||||
if (resetAP)
|
||||
strcpy_P(apPass, PSTR(DEFAULT_AP_PASS));
|
||||
}
|
||||
DEBUG_PRINT(F("Opening access point "));
|
||||
DEBUG_PRINTLN(apSSID);
|
||||
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0));
|
||||
@ -800,7 +834,7 @@ void WLED::handleStatusLED()
|
||||
ledStatusType = 4;
|
||||
} else if (apActive) {
|
||||
c = RGBW32(0,0,255,0);
|
||||
ledStatusType = 2;
|
||||
ledStatusType = 1;
|
||||
}
|
||||
if (ledStatusType) {
|
||||
if (millis() - ledStatusLastMillis >= (1000/ledStatusType)) {
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2209091
|
||||
#define VERSION 2209201
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -251,6 +251,16 @@ WLED_GLOBAL int8_t irPin _INIT(-1);
|
||||
WLED_GLOBAL int8_t irPin _INIT(IRPIN);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || (defined(RX) && defined(TX))
|
||||
// use RX/TX as set by the framework - these boards do _not_ have RX=3 and TX=1
|
||||
constexpr uint8_t hardwareRX = RX;
|
||||
constexpr uint8_t hardwareTX = TX;
|
||||
#else
|
||||
// use defaults for RX/TX
|
||||
constexpr uint8_t hardwareRX = 3;
|
||||
constexpr uint8_t hardwareTX = 1;
|
||||
#endif
|
||||
|
||||
//WLED_GLOBAL byte presetToApply _INIT(0);
|
||||
|
||||
WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use
|
||||
@ -609,8 +619,9 @@ WLED_GLOBAL byte errorFlag _INIT(0);
|
||||
WLED_GLOBAL String messageHead, messageSub;
|
||||
WLED_GLOBAL byte optionType;
|
||||
|
||||
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
|
||||
WLED_GLOBAL bool doPublishMqtt _INIT(false);
|
||||
WLED_GLOBAL bool doSerializeConfig _INIT(false); // flag to initiate saving of config
|
||||
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
|
||||
WLED_GLOBAL bool doPublishMqtt _INIT(false);
|
||||
|
||||
// status led
|
||||
#if defined(STATUSLED)
|
||||
|
@ -26,7 +26,7 @@ void updateBaudRate(uint32_t rate){
|
||||
if (rate100 == currentBaud || rate100 < 96) return;
|
||||
currentBaud = rate100;
|
||||
|
||||
if (!pinManager.isPinAllocated(1) || pinManager.getPinOwner(1) == PinOwner::DebugOut){
|
||||
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut){
|
||||
Serial.print(F("Baud is now ")); Serial.println(rate);
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ void updateBaudRate(uint32_t rate){
|
||||
|
||||
void handleSerial()
|
||||
{
|
||||
if (pinManager.isPinAllocated(3)) return;
|
||||
if (pinManager.isPinAllocated(hardwareRX)) return;
|
||||
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
static auto state = AdaState::Header_A;
|
||||
@ -72,7 +72,7 @@ void handleSerial()
|
||||
} else if (next == 0xB7) {updateBaudRate(1500000);
|
||||
|
||||
} else if (next == 'l') { //RGB(W) LED data return as JSON array. Slow, but easy to use on the other end.
|
||||
if (!pinManager.isPinAllocated(1) || pinManager.getPinOwner(1) == PinOwner::DebugOut){
|
||||
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut){
|
||||
uint16_t used = strip.getLengthTotal();
|
||||
Serial.write('[');
|
||||
for (uint16_t i=0; i<used; i+=1) {
|
||||
@ -82,7 +82,7 @@ void handleSerial()
|
||||
Serial.println("]");
|
||||
}
|
||||
} else if (next == 'L') { //RGB LED data returned as bytes in tpm2 format. Faster, and slightly less easy to use on the other end.
|
||||
if (!pinManager.isPinAllocated(1) || pinManager.getPinOwner(1) == PinOwner::DebugOut) {
|
||||
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut) {
|
||||
Serial.write(0xC9); Serial.write(0xDA);
|
||||
uint16_t used = strip.getLengthTotal();
|
||||
uint16_t len = used*3;
|
||||
@ -107,7 +107,7 @@ void handleSerial()
|
||||
}
|
||||
verboseResponse = deserializeState(doc.as<JsonObject>());
|
||||
//only send response if TX pin is unused for other purposes
|
||||
if (verboseResponse && (!pinManager.isPinAllocated(1) || pinManager.getPinOwner(1) == PinOwner::DebugOut)) {
|
||||
if (verboseResponse && (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut)) {
|
||||
doc.clear();
|
||||
JsonObject state = doc.createNestedObject("state");
|
||||
serializeState(state);
|
||||
|
@ -207,7 +207,7 @@ void initServer()
|
||||
if (!isConfig) {
|
||||
serveJson(request); return; //if JSON contains "v"
|
||||
} else {
|
||||
serializeConfig(); //Save new settings to FS
|
||||
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
|
||||
}
|
||||
}
|
||||
request->send(200, "application/json", F("{\"success\":true}"));
|
||||
|
@ -111,13 +111,18 @@ void sendDataWs(AsyncWebSocketClient * client)
|
||||
DEBUG_PRINTF("JSON buffer size: %u for WS request (%u).\n", doc.memoryUsage(), len);
|
||||
|
||||
size_t heap1 = ESP.getFreeHeap();
|
||||
buffer = ws.makeBuffer(len); // will not allocate correct memory sometimes
|
||||
buffer = ws.makeBuffer(len); // will not allocate correct memory sometimes on ESP8266
|
||||
#ifdef ESP8266
|
||||
size_t heap2 = ESP.getFreeHeap();
|
||||
#else
|
||||
size_t heap2 = 0; // ESP32 variants do not have the same issue and will work without checking heap allocation
|
||||
#endif
|
||||
if (!buffer || heap1-heap2<len) {
|
||||
releaseJSONBufferLock();
|
||||
DEBUG_PRINTLN(F("WS buffer allocation failed."));
|
||||
ws.closeAll(1013); //code 1013 = temporary overload, try again later
|
||||
ws.cleanupClients(0); //disconnect all clients to release memory
|
||||
ws._cleanBuffers();
|
||||
return; //out of memory
|
||||
}
|
||||
|
||||
|
185
wled00/xml.cpp
185
wled00/xml.cpp
@ -167,6 +167,112 @@ void fillUMPins(JsonObject &mods)
|
||||
}
|
||||
}
|
||||
|
||||
void appendGPIOinfo() {
|
||||
char nS[8];
|
||||
|
||||
oappend(SET_F("d.um_p=[-1")); // has to have 1 element
|
||||
if (i2c_sda > -1 && i2c_scl > -1) {
|
||||
oappend(","); oappend(itoa(i2c_sda,nS,10));
|
||||
oappend(","); oappend(itoa(i2c_scl,nS,10));
|
||||
}
|
||||
if (spi_mosi > -1 && spi_sclk > -1) {
|
||||
oappend(","); oappend(itoa(spi_mosi,nS,10));
|
||||
oappend(","); oappend(itoa(spi_sclk,nS,10));
|
||||
}
|
||||
// usermod pin reservations will become unnecessary when settings pages will read cfg.json directly
|
||||
if (requestJSONBufferLock(6)) {
|
||||
// if we can't allocate JSON buffer ignore usermod pins
|
||||
JsonObject mods = doc.createNestedObject(F("um"));
|
||||
usermods.addToConfig(mods);
|
||||
if (!mods.isNull()) fillUMPins(mods);
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
oappend(SET_F("];"));
|
||||
|
||||
// add reserved and usermod pins as d.um_p array
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
oappend(SET_F("d.rsvd=[22,23,24,25,26,27,28,29,30,31,32"));
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
oappend(SET_F("d.rsvd=[19,20,22,23,24,25,26,27,28,29,30,31,32")); // includes 19+20 for USB OTG (JTAG)
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
oappend(SET_F("d.rsvd=[11,12,13,14,15,16,17"));
|
||||
#elif defined(ESP32)
|
||||
oappend(SET_F("d.rsvd=[6,7,8,9,10,11,24,28,29,30,31"));
|
||||
#else
|
||||
oappend(SET_F("d.rsvd=[6,7,8,9,10,11"));
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
oappend(SET_F(",2")); // DMX hardcoded pin
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
oappend(SET_F(",")); oappend(itoa(hardwareTX,nS,10));// debug output (TX) pin
|
||||
#endif
|
||||
|
||||
//Note: Using pin 3 (RX) disables Adalight / Serial JSON
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
if (psramFound()) oappend(SET_F(",16,17")); // GPIO16 & GPIO17 reserved for SPI RAM on ESP32 (not on S2, S3 or C3)
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
if (psramFound()) oappend(SET_F(",33,34,35,36,37")); // in use for "octal" PSRAM or "octal" FLASH -seems that octal PSRAM is very common on S3.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
|
||||
for (uint8_t p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { oappend(","); oappend(itoa(esp32_nonconfigurable_ethernet_pins[p].pin,nS,10)); }
|
||||
if (ethernetBoards[ethernetType].eth_power>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_power,nS,10)); }
|
||||
if (ethernetBoards[ethernetType].eth_mdc>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdc,nS,10)); }
|
||||
if (ethernetBoards[ethernetType].eth_mdio>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdio,nS,10)); }
|
||||
switch (ethernetBoards[ethernetType].eth_clk_mode) {
|
||||
case ETH_CLOCK_GPIO0_IN:
|
||||
case ETH_CLOCK_GPIO0_OUT:
|
||||
oappend(SET_F(",0"));
|
||||
break;
|
||||
case ETH_CLOCK_GPIO16_OUT:
|
||||
oappend(SET_F(",16"));
|
||||
break;
|
||||
case ETH_CLOCK_GPIO17_OUT:
|
||||
oappend(SET_F(",17"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
oappend(SET_F("];"));
|
||||
|
||||
// add info for read-only GPIO
|
||||
oappend(SET_F("d.ro_gpio=["));
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
oappendi(46);
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// none for S3
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
// none for C3
|
||||
#elif defined(ESP32)
|
||||
oappend(SET_F("34,35,36,37,38,39"));
|
||||
#else
|
||||
// none for ESP8266
|
||||
#endif
|
||||
oappend(SET_F("];"));
|
||||
|
||||
// add info about max. # of pins
|
||||
oappend(SET_F("d.max_gpio="));
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
oappendi(46);
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
oappendi(48);
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
oappendi(21);
|
||||
#elif defined(ESP32)
|
||||
oappendi(39);
|
||||
#else
|
||||
oappendi(16);
|
||||
#endif
|
||||
oappend(SET_F(";"));
|
||||
}
|
||||
|
||||
//get values for settings form in javascript
|
||||
void getSettingsJS(byte subPage, char* dest)
|
||||
@ -257,69 +363,13 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
{
|
||||
char nS[8];
|
||||
|
||||
// Pin reservations will become unnecessary when settings pages will read cfg.json directly
|
||||
// add reserved and usermod pins as d.um_p array
|
||||
oappend(SET_F("d.um_p=[6,7,8,9,10,11"));
|
||||
|
||||
if (i2c_sda > -1 && i2c_scl > -1) {
|
||||
oappend(","); oappend(itoa(i2c_sda,nS,10));
|
||||
oappend(","); oappend(itoa(i2c_scl,nS,10));
|
||||
}
|
||||
if (spi_mosi > -1 && spi_sclk > -1) {
|
||||
oappend(","); oappend(itoa(spi_mosi,nS,10));
|
||||
oappend(","); oappend(itoa(spi_sclk,nS,10));
|
||||
}
|
||||
|
||||
if (requestJSONBufferLock(6)) {
|
||||
// if we can't allocate JSON buffer ignore usermod pins
|
||||
JsonObject mods = doc.createNestedObject(F("um"));
|
||||
usermods.addToConfig(mods);
|
||||
if (!mods.isNull()) fillUMPins(mods);
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
oappend(SET_F(",2")); // DMX hardcoded pin
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
oappend(SET_F(",1")); // debug output (TX) pin
|
||||
#endif
|
||||
|
||||
//Note: Using pin 3 (RX) disables Adalight / Serial JSON
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound()) oappend(SET_F(",16,17")); // GPIO16 & GPIO17 reserved for SPI RAM
|
||||
#endif
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
|
||||
for (uint8_t p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { oappend(","); oappend(itoa(esp32_nonconfigurable_ethernet_pins[p].pin,nS,10)); }
|
||||
if (ethernetBoards[ethernetType].eth_power>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_power,nS,10)); }
|
||||
if (ethernetBoards[ethernetType].eth_mdc>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdc,nS,10)); }
|
||||
if (ethernetBoards[ethernetType].eth_mdio>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdio,nS,10)); }
|
||||
switch (ethernetBoards[ethernetType].eth_clk_mode) {
|
||||
case ETH_CLOCK_GPIO0_IN:
|
||||
case ETH_CLOCK_GPIO0_OUT:
|
||||
oappend(SET_F(",0"));
|
||||
break;
|
||||
case ETH_CLOCK_GPIO16_OUT:
|
||||
oappend(SET_F(",16"));
|
||||
break;
|
||||
case ETH_CLOCK_GPIO17_OUT:
|
||||
oappend(SET_F(",17"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
oappend(SET_F("];"));
|
||||
appendGPIOinfo();
|
||||
|
||||
// set limits
|
||||
oappend(SET_F("bLimits("));
|
||||
#if defined(ESP32) && defined(USERMOD_AUDIOREACTIVE)
|
||||
#if defined(ESP32) && defined(USERMOD_AUDIOREACTIVE) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
// requested by @softhack007 https://github.com/blazoncek/WLED/issues/33
|
||||
oappend(itoa(WLED_MAX_BUSSES-2,nS,10)); oappend(","); // prevent use of I2S buses if audio installed
|
||||
oappend(itoa(WLED_MAX_BUSSES-2,nS,10)); oappend(","); // prevent use of I2S buses if audio installed. ESP32-S3 currently does not support these busses.
|
||||
#else
|
||||
oappend(itoa(WLED_MAX_BUSSES,nS,10)); oappend(",");
|
||||
#endif
|
||||
@ -500,14 +550,14 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
char hueErrorString[25];
|
||||
switch (hueError)
|
||||
{
|
||||
case HUE_ERROR_INACTIVE : strcpy(hueErrorString,(char*)F("Inactive")); break;
|
||||
case HUE_ERROR_ACTIVE : strcpy(hueErrorString,(char*)F("Active")); break;
|
||||
case HUE_ERROR_UNAUTHORIZED : strcpy(hueErrorString,(char*)F("Unauthorized")); break;
|
||||
case HUE_ERROR_LIGHTID : strcpy(hueErrorString,(char*)F("Invalid light ID")); break;
|
||||
case HUE_ERROR_PUSHLINK : strcpy(hueErrorString,(char*)F("Link button not pressed")); break;
|
||||
case HUE_ERROR_JSON_PARSING : strcpy(hueErrorString,(char*)F("JSON parsing error")); break;
|
||||
case HUE_ERROR_TIMEOUT : strcpy(hueErrorString,(char*)F("Timeout")); break;
|
||||
default: sprintf(hueErrorString,(char*)F("Bridge Error %i"),hueError);
|
||||
case HUE_ERROR_INACTIVE : strcpy_P(hueErrorString,PSTR("Inactive")); break;
|
||||
case HUE_ERROR_ACTIVE : strcpy_P(hueErrorString,PSTR("Active")); break;
|
||||
case HUE_ERROR_UNAUTHORIZED : strcpy_P(hueErrorString,PSTR("Unauthorized")); break;
|
||||
case HUE_ERROR_LIGHTID : strcpy_P(hueErrorString,PSTR("Invalid light ID")); break;
|
||||
case HUE_ERROR_PUSHLINK : strcpy_P(hueErrorString,PSTR("Link button not pressed")); break;
|
||||
case HUE_ERROR_JSON_PARSING : strcpy_P(hueErrorString,PSTR("JSON parsing error")); break;
|
||||
case HUE_ERROR_TIMEOUT : strcpy_P(hueErrorString,PSTR("Timeout")); break;
|
||||
default: sprintf_P(hueErrorString,PSTR("Bridge Error %i"),hueError);
|
||||
}
|
||||
|
||||
sappends('m',SET_F("(\"sip\")[0]"),hueErrorString);
|
||||
@ -630,6 +680,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
if (subPage == 8) //usermods
|
||||
{
|
||||
appendGPIOinfo();
|
||||
oappend(SET_F("numM="));
|
||||
oappendi(usermods.getModCount());
|
||||
oappend(";");
|
||||
|
Loading…
Reference in New Issue
Block a user