mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
Merge pull request #3669 from TD-er/feature/GPIO_markup
[GPIO Selection] Filter possible GPIO pins based on needed properties
This commit is contained in:
+3
-3
@@ -638,11 +638,11 @@ bool CPlugin_018(CPlugin::Function function, struct EventStruct *event, String&
|
||||
addTableSeparator(F("Serial Port Configuration"), 2, 3);
|
||||
|
||||
// Optional reset pin RN2xx3
|
||||
addFormPinSelect(formatGpioName_output_optional(F("Reset")), F("taskdevicepin3"), resetpin);
|
||||
addFormPinSelect(PinSelectPurpose::Generic_output, formatGpioName_output_optional(F("Reset")), F("taskdevicepin3"), resetpin);
|
||||
|
||||
// Show serial port selection
|
||||
addFormPinSelect(formatGpioName_RX(false), F("taskdevicepin1"), rxpin);
|
||||
addFormPinSelect(formatGpioName_TX(false), F("taskdevicepin2"), txpin);
|
||||
addFormPinSelect(PinSelectPurpose::Generic_input, formatGpioName_RX(false), F("taskdevicepin1"), rxpin);
|
||||
addFormPinSelect(PinSelectPurpose::Generic_output, formatGpioName_TX(false), F("taskdevicepin2"), txpin);
|
||||
|
||||
// FIXME TD-er: Add port selector
|
||||
serialHelper_webformLoad(ESPEasySerialPort::not_set, rxpin, txpin, true);
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ boolean Plugin_002(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
#if defined(ESP32)
|
||||
addHtml(F("<TR><TD>Analog Pin:<TD>"));
|
||||
addADC_PinSelect(false, F("taskdevicepin1"), CONFIG_PIN1);
|
||||
addADC_PinSelect(AdcPinSelectPurpose::ADC_Touch_HallEffect, F("taskdevicepin1"), CONFIG_PIN1);
|
||||
|
||||
#endif // if defined(ESP32)
|
||||
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
|
||||
addRowLabel(F("Display button"));
|
||||
addPinSelect(false, F("taskdevicepin3"), CONFIG_PIN3);
|
||||
addPinSelect(PinSelectPurpose::Generic_input, F("taskdevicepin3"), CONFIG_PIN3);
|
||||
|
||||
addFormCheckBox(F("Inversed logic"), F("p012_inversed_btn"), P012_INVERSE_BTN == 1, false);
|
||||
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
|
||||
// FIXME TD-er: Why is this using pin3 and not pin1? And why isn't this using the normal pin selection functions?
|
||||
addFormPinSelect(F("Display button"), F("taskdevicepin3"), CONFIG_PIN3);
|
||||
addFormPinSelect(PinSelectPurpose::Generic_input, F("Display button"), F("taskdevicepin3"), CONFIG_PIN3);
|
||||
|
||||
addFormNumericBox(F("Display Timeout"), F("plugin_23_timer"), PCONFIG(2));
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string)
|
||||
}
|
||||
|
||||
// FIXME TD-er: Why is this using pin3 and not pin1? And why isn't this using the normal pin selection functions?
|
||||
addFormPinSelect(F("Display button"), F("taskdevicepin3"), CONFIG_PIN3);
|
||||
addFormPinSelect(PinSelectPurpose::Generic_input, F("Display button"), F("taskdevicepin3"), CONFIG_PIN3);
|
||||
bool tbPin3Invers = bitRead(PCONFIG_LONG(0), 16); // Bit 16
|
||||
|
||||
{
|
||||
|
||||
@@ -171,14 +171,10 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
|
||||
if (choice==0) {
|
||||
addHtml(F("<TR><TD>1st GPIO (5-MOSI):<TD>"));
|
||||
addPinSelect(false, F("taskdevicepin1"), PCONFIG(1));
|
||||
addHtml(F("<TR><TD>2nd GPIO (6-SCLK):<TD>"));
|
||||
addPinSelect(false, F("taskdevicepin2"), PCONFIG(2));
|
||||
addHtml(F("<TR><TD>3rd GPIO (7-nSEL):<TD>"));
|
||||
addPinSelect(false, F("taskdevicepin3"), PCONFIG(3));
|
||||
addHtml(F("<TR><TD>4th GPIO (8-MISO):<TD>"));
|
||||
addPinSelect(false, F("taskdeviceport"), PCONFIG(4));
|
||||
addFormPinSelect(PinSelectPurpose::SPI, F("1st GPIO (5-MOSI)"), F("taskdevicepin1"), PCONFIG(1));
|
||||
addFormPinSelect(PinSelectPurpose::SPI, F("2nd GPIO (6-SCLK)"), F("taskdevicepin2"), PCONFIG(2));
|
||||
addFormPinSelect(PinSelectPurpose::SPI, F("3rd GPIO (7-nSEL)"), F("taskdevicepin3"), PCONFIG(3));
|
||||
addFormPinSelect(PinSelectPurpose::SPI, F("4th GPIO (8-MISO)"), F("taskdeviceport"), PCONFIG(4));
|
||||
}
|
||||
|
||||
switch (choice)
|
||||
|
||||
@@ -139,7 +139,7 @@ boolean Plugin_055(byte function, struct EventStruct *event, String& string)
|
||||
PCONFIG(1) = 400;
|
||||
|
||||
// FIXME TD-er: Should we add support for 4 pin definitions?
|
||||
addFormPinSelect(formatGpioName_output(F("Driver#8")), F("TDP4"), (int)(Settings.TaskDevicePin[3][event->TaskIndex]));
|
||||
addFormPinSelect(PinSelectPurpose::Generic_output, formatGpioName_output(F("Driver#8")), F("TDP4"), (int)(Settings.TaskDevicePin[3][event->TaskIndex]));
|
||||
|
||||
addFormSubHeader(F("Timing"));
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ boolean Plugin_097(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
addHtml(F("<TR><TD>Analog Pin:<TD>"));
|
||||
addADC_PinSelect(true, F("taskdevicepin1"), CONFIG_PIN1);
|
||||
addADC_PinSelect(AdcPinSelectPurpose::TouchOnly, F("taskdevicepin1"), CONFIG_PIN1);
|
||||
|
||||
addFormSubHeader(F("Touch Settings"));
|
||||
|
||||
|
||||
@@ -136,6 +136,14 @@ bool pluginOptionalTaskIndexArgumentMatch(taskIndex_t taskIndex, const String& s
|
||||
return found_taskIndex == taskIndex;
|
||||
}
|
||||
|
||||
bool pluginWebformShowGPIOdescription(taskIndex_t taskIndex, const String& newline)
|
||||
{
|
||||
struct EventStruct TempEvent(taskIndex);
|
||||
TempEvent.String1 = newline;
|
||||
String dummy;
|
||||
return PluginCall(PLUGIN_WEBFORM_SHOW_GPIO_DESCR, &TempEvent, dummy);
|
||||
}
|
||||
|
||||
int getValueCountForTask(taskIndex_t taskIndex) {
|
||||
struct EventStruct TempEvent(taskIndex);
|
||||
String dummy;
|
||||
|
||||
@@ -143,6 +143,8 @@ bool pluginOptionalTaskIndexArgumentMatch(taskIndex_t taskIndex,
|
||||
const String& string,
|
||||
byte paramNr);
|
||||
|
||||
bool pluginWebformShowGPIOdescription(taskIndex_t taskIndex, const String& newline);
|
||||
|
||||
int getValueCountForTask(taskIndex_t taskIndex);
|
||||
|
||||
// Check if the DeviceVType is set and update if it isn't.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
// Forward declarations of functions used in this module
|
||||
// Normally those would be declared in the .h file as private members
|
||||
// But since these are not part of a class, forward declare them in the .cpp
|
||||
void createAndSetPortStatus_Mode_State(uint32_t key, byte newMode, int8_t newState);
|
||||
//void createAndSetPortStatus_Mode_State(uint32_t key, byte newMode, int8_t newState);
|
||||
bool getPluginIDAndPrefix(char selection, pluginID_t &pluginID, String &logPrefix);
|
||||
void logErrorGpioOffline(const String& prefix, int port);
|
||||
void logErrorGpioOutOfRange(const String& prefix, int port, const char* Line = nullptr);
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
// FIXME TD-er: This fwd declaration should not be in .h file.
|
||||
// Only needed till GPIO can be set from ESPEasy core.
|
||||
void createAndSetPortStatus_Mode_State(uint32_t key, byte newMode, int8_t newState);
|
||||
|
||||
|
||||
const __FlashStringHelper * Command_GPIO(struct EventStruct *event, const char* Line);
|
||||
const __FlashStringHelper * Command_GPIO_Toggle(struct EventStruct *event, const char* Line);
|
||||
const __FlashStringHelper * Command_GPIO_PWM(struct EventStruct *event, const char* Line);
|
||||
|
||||
@@ -11,12 +11,17 @@ bool DeviceStruct::connectedToGPIOpins() const {
|
||||
switch(Type) {
|
||||
case DEVICE_TYPE_SINGLE: // Single GPIO
|
||||
case DEVICE_TYPE_SPI:
|
||||
case DEVICE_TYPE_CUSTOM1:
|
||||
|
||||
case DEVICE_TYPE_DUAL: // Dual GPIOs
|
||||
case DEVICE_TYPE_SERIAL:
|
||||
case DEVICE_TYPE_SPI2:
|
||||
case DEVICE_TYPE_CUSTOM2:
|
||||
|
||||
case DEVICE_TYPE_TRIPLE: // Triple GPIOs
|
||||
case DEVICE_TYPE_SERIAL_PLUS1:
|
||||
case DEVICE_TYPE_SPI3:
|
||||
case DEVICE_TYPE_CUSTOM3:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -28,9 +33,14 @@ bool DeviceStruct::usesTaskDevicePin(int pin) const {
|
||||
case 1:
|
||||
return connectedToGPIOpins();
|
||||
case 2:
|
||||
return connectedToGPIOpins() && !(Type == DEVICE_TYPE_SINGLE || Type == DEVICE_TYPE_SPI);
|
||||
return connectedToGPIOpins() &&
|
||||
!(Type == DEVICE_TYPE_SINGLE || Type == DEVICE_TYPE_SPI ||
|
||||
Type == DEVICE_TYPE_CUSTOM1 || Type == DEVICE_TYPE_CUSTOM2);
|
||||
case 3:
|
||||
return Type == DEVICE_TYPE_TRIPLE || Type == DEVICE_TYPE_SERIAL_PLUS1 || Type == DEVICE_TYPE_SPI3;
|
||||
return Type == DEVICE_TYPE_TRIPLE ||
|
||||
Type == DEVICE_TYPE_SERIAL_PLUS1 ||
|
||||
Type == DEVICE_TYPE_SPI3 ||
|
||||
Type == DEVICE_TYPE_CUSTOM3;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
#define DEVICE_TYPE_SPI 23 // connected through SPI
|
||||
#define DEVICE_TYPE_SPI2 24 // connected through SPI, 2 GPIOs
|
||||
#define DEVICE_TYPE_SPI3 25 // connected through SPI, 3 GPIOs
|
||||
#define DEVICE_TYPE_CUSTOM0 30 // Custom labels, Not using TaskDevicePin1 ... TaskDevicePin3
|
||||
#define DEVICE_TYPE_CUSTOM1 31 // Custom labels, 1 GPIO
|
||||
#define DEVICE_TYPE_CUSTOM2 32 // Custom labels, 2 GPIOs
|
||||
#define DEVICE_TYPE_CUSTOM3 33 // Custom labels, 3 GPIOs
|
||||
#define DEVICE_TYPE_DUMMY 99 // Dummy device, has no physical connection
|
||||
|
||||
#define I2C_MULTIPLEXER_NONE -1 // None selected
|
||||
|
||||
@@ -469,6 +469,98 @@ void SettingsStruct_tmpl<N_TASKS>::setPinBootState(uint8_t gpio_pin, PinBootStat
|
||||
#endif
|
||||
}
|
||||
|
||||
template<unsigned int N_TASKS>
|
||||
bool SettingsStruct_tmpl<N_TASKS>::getSPI_pins(int8_t spi_gpios[3]) const {
|
||||
spi_gpios[0] = -1;
|
||||
spi_gpios[1] = -1;
|
||||
spi_gpios[2] = -1;
|
||||
if (InitSPI > 0) {
|
||||
# ifdef ESP32
|
||||
switch (InitSPI) {
|
||||
case 1:
|
||||
{
|
||||
spi_gpios[0] = 18; spi_gpios[1] = 19; spi_gpios[2] = 23;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
spi_gpios[0] = 14; // HSPI_SCLK
|
||||
spi_gpios[1] = 12; // HSPI_MISO
|
||||
spi_gpios[2] = 13; // HSPI_MOSI
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
# endif // ifdef ESP32
|
||||
# ifdef ESP8266
|
||||
spi_gpios[0] = 14; spi_gpios[1] = 12; spi_gpios[2] = 13;
|
||||
# endif // ifdef ESP8266
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<unsigned int N_TASKS>
|
||||
bool SettingsStruct_tmpl<N_TASKS>::isSPI_pin(int8_t pin) const {
|
||||
if (pin < 0) return false;
|
||||
int8_t spi_gpios[3];
|
||||
if (getSPI_pins(spi_gpios)) {
|
||||
for (byte i = 0; i < 3; ++i) {
|
||||
if (spi_gpios[i] == pin) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<unsigned int N_TASKS>
|
||||
bool SettingsStruct_tmpl<N_TASKS>::isI2C_pin(int8_t pin) const {
|
||||
if (pin < 0) return false;
|
||||
return Pin_i2c_sda == pin || Pin_i2c_scl == pin;
|
||||
}
|
||||
|
||||
template<unsigned int N_TASKS>
|
||||
bool SettingsStruct_tmpl<N_TASKS>::isEthernetPin(int8_t pin) const {
|
||||
#ifdef HAS_ETHERNET
|
||||
if (pin < 0) return false;
|
||||
if (NetworkMedium == NetworkMedium_t::Ethernet) {
|
||||
if (19 == pin) return true; // ETH TXD0
|
||||
if (21 == pin) return true; // ETH TX EN
|
||||
if (22 == pin) return true; // ETH TXD1
|
||||
if (25 == pin) return true; // ETH RXD0
|
||||
if (26 == pin) return true; // ETH RXD1
|
||||
if (27 == pin) return true; // ETH CRS_DV
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<unsigned int N_TASKS>
|
||||
bool SettingsStruct_tmpl<N_TASKS>::isEthernetPinOptional(int8_t pin) const {
|
||||
#ifdef HAS_ETHERNET
|
||||
if (pin < 0) return false;
|
||||
if (NetworkMedium == NetworkMedium_t::Ethernet) {
|
||||
if (ETH_Pin_mdc == pin) return true;
|
||||
if (ETH_Pin_mdio == pin) return true;
|
||||
if (ETH_Pin_power == pin) return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
template<unsigned int N_TASKS>
|
||||
int8_t SettingsStruct_tmpl<N_TASKS>::getTaskDevicePin(taskIndex_t taskIndex, byte pinnr) const {
|
||||
if (validTaskIndex(taskIndex)) {
|
||||
switch(pinnr) {
|
||||
case 1: return TaskDevicePin1[taskIndex];
|
||||
case 2: return TaskDevicePin2[taskIndex];
|
||||
case 3: return TaskDevicePin3[taskIndex];
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<unsigned int N_TASKS>
|
||||
float SettingsStruct_tmpl<N_TASKS>::getWiFi_TX_power() const {
|
||||
return WiFi_TX_power / 4.0f;
|
||||
|
||||
@@ -151,6 +151,24 @@ class SettingsStruct_tmpl
|
||||
PinBootState getPinBootState(uint8_t gpio_pin) const;
|
||||
void setPinBootState(uint8_t gpio_pin, PinBootState state);
|
||||
|
||||
bool getSPI_pins(int8_t spi_gpios[3]) const;
|
||||
|
||||
// Return true when pin is one of the SPI pins and SPI is enabled
|
||||
bool isSPI_pin(int8_t pin) const;
|
||||
|
||||
// Return true when pin is one of the configured I2C pins.
|
||||
bool isI2C_pin(int8_t pin) const;
|
||||
|
||||
// Return true when pin is one of the fixed Ethernet pins and Ethernet is enabled
|
||||
bool isEthernetPin(int8_t pin) const;
|
||||
|
||||
// Return true when pin is one of the optional Ethernet pins and Ethernet is enabled
|
||||
bool isEthernetPinOptional(int8_t pin) const;
|
||||
|
||||
// Access to TaskDevicePin1 ... TaskDevicePin3
|
||||
// @param pinnr 1 = TaskDevicePin1, ..., 3 = TaskDevicePin3
|
||||
int8_t getTaskDevicePin(taskIndex_t taskIndex, byte pinnr) const;
|
||||
|
||||
float getWiFi_TX_power() const;
|
||||
void setWiFi_TX_power(float dBm);
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#define PLUGIN_MQTT_CONNECTION_STATE 36 // Signal when connection to MQTT broker is re-established
|
||||
#define PLUGIN_MQTT_IMPORT 37 // For P037 MQTT import
|
||||
#define PLUGIN_FORMAT_USERVAR 38 // Allow plugin specific formatting of a task variable (event->idx = variable)
|
||||
#define PLUGIN_WEBFORM_SHOW_GPIO_DESCR 39 // Show GPIO description on devices overview tab
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -611,6 +611,7 @@ bool PluginCall(byte Function, struct EventStruct *event, String& str)
|
||||
case PLUGIN_WEBFORM_SHOW_CONFIG:
|
||||
case PLUGIN_WEBFORM_SHOW_I2C_PARAMS:
|
||||
case PLUGIN_WEBFORM_SHOW_SERIAL_PARAMS:
|
||||
case PLUGIN_WEBFORM_SHOW_GPIO_DESCR:
|
||||
case PLUGIN_FORMAT_USERVAR:
|
||||
case PLUGIN_SET_CONFIG:
|
||||
case PLUGIN_SET_DEFAULTS:
|
||||
|
||||
@@ -821,6 +821,19 @@ bool getGpioInfo(int gpio, int& pinnr, bool& input, bool& output, bool& warning)
|
||||
output = false;
|
||||
}
|
||||
|
||||
if (gpio == 37 || gpio == 38) {
|
||||
// Pins are not present on the ESP32
|
||||
input = false;
|
||||
output = false;
|
||||
}
|
||||
|
||||
if (gpio >= 6 && gpio <= 11) {
|
||||
// Connected to the integrated SPI flash.
|
||||
input = false;
|
||||
output = false;
|
||||
warning = true;
|
||||
}
|
||||
|
||||
if ((input == false) && (output == false)) {
|
||||
return false;
|
||||
}
|
||||
@@ -859,6 +872,7 @@ bool getGpioInfo(int gpio, int& pinnr, bool& input, bool& output, bool& warning)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// FIXME TD-er: Must we also check for pins used for MDC/MDIO and Eth PHY power?
|
||||
}
|
||||
|
||||
@@ -891,7 +905,9 @@ bool getGpioPullResistor(int gpio, bool& hasPullUp, bool& hasPullDown) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#else // ifdef ESP32
|
||||
#endif
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
// return true when pin can be used.
|
||||
bool getGpioInfo(int gpio, int& pinnr, bool& input, bool& output, bool& warning) {
|
||||
@@ -951,9 +967,8 @@ bool getGpioInfo(int gpio, int& pinnr, bool& input, bool& output, bool& warning)
|
||||
if (pinnr < 0 || pinnr > 16) {
|
||||
input = false;
|
||||
output = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return input || output;
|
||||
}
|
||||
|
||||
bool getGpioPullResistor(int gpio, bool& hasPullUp, bool& hasPullDown) {
|
||||
@@ -975,7 +990,7 @@ bool getGpioPullResistor(int gpio, bool& hasPullUp, bool& hasPullDown) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // ifdef ESP32
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
|
||||
#include "../Globals/Settings.h"
|
||||
#include "../Helpers/Hardware.h"
|
||||
#include "../../ESPEasy_common.h"
|
||||
|
||||
/*********************************************************************************************\
|
||||
Device GPIO name functions to share flash strings
|
||||
\*********************************************************************************************/
|
||||
String formatGpioDirection(gpio_direction direction) {
|
||||
const __FlashStringHelper* formatGpioDirection(gpio_direction direction) {
|
||||
switch (direction) {
|
||||
case gpio_input: return F("← ");
|
||||
case gpio_output: return F("→ ");
|
||||
case gpio_bidirectional: return F("⇄ ");
|
||||
}
|
||||
return "";
|
||||
return F("");
|
||||
}
|
||||
|
||||
String formatGpioLabel(int gpio, bool includeWarning) {
|
||||
@@ -139,14 +140,77 @@ String createGPIO_label(int gpio, int pinnr, bool input, bool output, bool warni
|
||||
if (warning) {
|
||||
result += ' ';
|
||||
result += F(HTML_SYMBOL_WARNING);
|
||||
|
||||
bool serialPinConflict = (Settings.UseSerial && (gpio == 1 || gpio == 3));
|
||||
|
||||
if (serialPinConflict) {
|
||||
if (gpio == 1) { result += F(" TX0"); }
|
||||
|
||||
if (gpio == 3) { result += F(" RX0"); }
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const __FlashStringHelper* getConflictingUse(int gpio, PinSelectPurpose purpose)
|
||||
{
|
||||
if (Settings.UseSerial) {
|
||||
if (gpio == 1) { return F("TX0"); }
|
||||
|
||||
if (gpio == 3) { return F("RX0"); }
|
||||
}
|
||||
bool includeI2C = true;
|
||||
bool includeSPI = true;
|
||||
|
||||
#ifdef HAS_ETHERNET
|
||||
bool includeEthernet = true;
|
||||
#endif // ifdef HAS_ETHERNET
|
||||
|
||||
switch (purpose) {
|
||||
case PinSelectPurpose::I2C:
|
||||
includeI2C = false;
|
||||
break;
|
||||
case PinSelectPurpose::SPI:
|
||||
includeSPI = false;
|
||||
break;
|
||||
case PinSelectPurpose::Ethernet:
|
||||
#ifdef HAS_ETHERNET
|
||||
includeEthernet = false;
|
||||
#endif // ifdef HAS_ETHERNET
|
||||
break;
|
||||
case PinSelectPurpose::Generic:
|
||||
case PinSelectPurpose::Generic_input:
|
||||
case PinSelectPurpose::Generic_output:
|
||||
case PinSelectPurpose::Generic_bidir:
|
||||
break;
|
||||
}
|
||||
|
||||
if (includeI2C && Settings.isI2C_pin(gpio)) {
|
||||
return (Settings.Pin_i2c_sda == gpio) ? F("I2C SDA") : F("I2C SCL");
|
||||
}
|
||||
|
||||
if (includeSPI && Settings.isSPI_pin(gpio)) {
|
||||
return F("SPI");
|
||||
}
|
||||
#ifdef HAS_ETHERNET
|
||||
|
||||
if (Settings.isEthernetPin(gpio)) {
|
||||
return F("Eth");
|
||||
}
|
||||
|
||||
if (includeEthernet && Settings.isEthernetPinOptional(gpio)) {
|
||||
if (Settings.ETH_Pin_mdc == gpio) { return F("Eth MDC"); }
|
||||
|
||||
if (Settings.ETH_Pin_mdio == gpio) { return F("Eth MDIO"); }
|
||||
|
||||
if (Settings.ETH_Pin_power == gpio) { return F("Eth Pwr"); }
|
||||
|
||||
return F("Eth");
|
||||
}
|
||||
#endif // ifdef HAS_ETHERNET
|
||||
return F("");
|
||||
}
|
||||
|
||||
String getConflictingUse_wrapped(int gpio, PinSelectPurpose purpose)
|
||||
{
|
||||
String conflict = getConflictingUse(gpio, purpose);
|
||||
|
||||
if (conflict.isEmpty()) { return conflict; }
|
||||
String res = F(" [");
|
||||
|
||||
res += conflict;
|
||||
res += ']';
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -17,11 +17,22 @@ enum gpio_direction {
|
||||
gpio_bidirectional
|
||||
};
|
||||
|
||||
enum class PinSelectPurpose {
|
||||
Generic,
|
||||
Generic_input,
|
||||
Generic_output,
|
||||
Generic_bidir,
|
||||
I2C,
|
||||
SPI,
|
||||
Ethernet
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
Device GPIO name functions to share flash strings
|
||||
\*********************************************************************************************/
|
||||
String formatGpioDirection(gpio_direction direction);
|
||||
const __FlashStringHelper * formatGpioDirection(gpio_direction direction);
|
||||
|
||||
String formatGpioLabel(int gpio,
|
||||
bool includeWarning);
|
||||
@@ -62,6 +73,9 @@ String createGPIO_label(int gpio,
|
||||
bool output,
|
||||
bool warning);
|
||||
|
||||
const __FlashStringHelper * getConflictingUse(int gpio, PinSelectPurpose purpose = PinSelectPurpose::Generic);
|
||||
|
||||
String getConflictingUse_wrapped(int gpio, PinSelectPurpose purpose = PinSelectPurpose::Generic);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -391,6 +391,25 @@ void handle_devices_CopySubmittedSettings(taskIndex_t taskIndex, pluginID_t task
|
||||
}
|
||||
}
|
||||
|
||||
void GpioToHtml(int8_t pin) {
|
||||
if (pin == -1) return;
|
||||
addHtml(formatGpioLabel(pin, false));
|
||||
if (Settings.isSPI_pin(pin) ||
|
||||
Settings.isI2C_pin(pin) ||
|
||||
Settings.isEthernetPin(pin) ||
|
||||
Settings.isEthernetPinOptional(pin)) {
|
||||
addHtml(' ');
|
||||
addHtml(F(HTML_SYMBOL_WARNING));
|
||||
}
|
||||
}
|
||||
|
||||
void Label_Gpio_toHtml(const __FlashStringHelper * label, const String& gpio_pin_descr) {
|
||||
addHtml(label);
|
||||
addHtml(':');
|
||||
addHtml(F(" "));
|
||||
addHtml(gpio_pin_descr);
|
||||
}
|
||||
|
||||
// ********************************************************************************
|
||||
// Show table with all selected Tasks/Devices
|
||||
// ********************************************************************************
|
||||
@@ -644,6 +663,26 @@ void handle_devicess_ShowAllTasksTable(byte page)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DEVICE_TYPE_CUSTOM3:
|
||||
showpin3 = true;
|
||||
|
||||
// fallthrough
|
||||
case DEVICE_TYPE_CUSTOM2:
|
||||
showpin2 = true;
|
||||
|
||||
// fallthrough
|
||||
case DEVICE_TYPE_CUSTOM1:
|
||||
case DEVICE_TYPE_CUSTOM0:
|
||||
{
|
||||
showpin1 = true;
|
||||
if (pluginWebformShowGPIOdescription(x, F("<BR>")) || Device[DeviceIndex].Type == DEVICE_TYPE_CUSTOM0) {
|
||||
showpin1 = false;
|
||||
showpin2 = false;
|
||||
showpin3 = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
showpin1 = true;
|
||||
showpin2 = true;
|
||||
@@ -651,51 +690,19 @@ void handle_devicess_ShowAllTasksTable(byte page)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((Settings.TaskDevicePin1[x] != -1) && showpin1)
|
||||
if (showpin1)
|
||||
{
|
||||
String html = formatGpioLabel(Settings.TaskDevicePin1[x], false);
|
||||
|
||||
if ((spi_gpios[0] == Settings.TaskDevicePin1[x])
|
||||
|| (spi_gpios[1] == Settings.TaskDevicePin1[x])
|
||||
|| (spi_gpios[2] == Settings.TaskDevicePin1[x])
|
||||
|| (Settings.Pin_i2c_sda == Settings.TaskDevicePin1[x])
|
||||
|| (Settings.Pin_i2c_scl == Settings.TaskDevicePin1[x])) {
|
||||
html += ' ';
|
||||
html += F(HTML_SYMBOL_WARNING);
|
||||
}
|
||||
addHtml(html);
|
||||
GpioToHtml(Settings.getTaskDevicePin(x, 1));
|
||||
}
|
||||
|
||||
if ((Settings.TaskDevicePin2[x] != -1) && showpin2)
|
||||
if (showpin2)
|
||||
{
|
||||
html_BR();
|
||||
String html = formatGpioLabel(Settings.TaskDevicePin2[x], false);
|
||||
|
||||
if ((spi_gpios[0] == Settings.TaskDevicePin2[x])
|
||||
|| (spi_gpios[1] == Settings.TaskDevicePin2[x])
|
||||
|| (spi_gpios[2] == Settings.TaskDevicePin2[x])
|
||||
|| (Settings.Pin_i2c_sda == Settings.TaskDevicePin2[x])
|
||||
|| (Settings.Pin_i2c_scl == Settings.TaskDevicePin2[x])) {
|
||||
html += ' ';
|
||||
html += F(HTML_SYMBOL_WARNING);
|
||||
}
|
||||
addHtml(html);
|
||||
GpioToHtml(Settings.getTaskDevicePin(x, 2));
|
||||
}
|
||||
|
||||
if ((Settings.TaskDevicePin3[x] != -1) && showpin3)
|
||||
if (showpin3)
|
||||
{
|
||||
html_BR();
|
||||
String html = formatGpioLabel(Settings.TaskDevicePin3[x], false);
|
||||
|
||||
if ((spi_gpios[0] == Settings.TaskDevicePin3[x])
|
||||
|| (spi_gpios[1] == Settings.TaskDevicePin3[x])
|
||||
|| (spi_gpios[2] == Settings.TaskDevicePin3[x])
|
||||
|| (Settings.Pin_i2c_sda == Settings.TaskDevicePin3[x])
|
||||
|| (Settings.Pin_i2c_scl == Settings.TaskDevicePin3[x])) {
|
||||
html += ' ';
|
||||
html += F(HTML_SYMBOL_WARNING);
|
||||
}
|
||||
addHtml(html);
|
||||
GpioToHtml(Settings.getTaskDevicePin(x, 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -774,60 +781,50 @@ void format_I2C_port_description(taskIndex_t x)
|
||||
|
||||
void format_SPI_port_description(int8_t spi_gpios[3])
|
||||
{
|
||||
if (Settings.InitSPI == 0) {
|
||||
if (!Settings.getSPI_pins(spi_gpios)) {
|
||||
addHtml(F("SPI (Not enabled)"));
|
||||
} else {
|
||||
# ifdef ESP32
|
||||
|
||||
switch (Settings.InitSPI) {
|
||||
case 1:
|
||||
{
|
||||
addHtml(F("VSPI"));
|
||||
spi_gpios[0] = 18; spi_gpios[1] = 19; spi_gpios[2] = 23;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
addHtml(F("HSPI"));
|
||||
spi_gpios[0] = 14; spi_gpios[1] = 12; spi_gpios[2] = 13;
|
||||
break;
|
||||
}
|
||||
}
|
||||
# endif // ifdef ESP32
|
||||
# ifdef ESP8266
|
||||
addHtml(F("SPI"));
|
||||
spi_gpios[0] = 14; spi_gpios[1] = 12; spi_gpios[2] = 13;
|
||||
# endif // ifdef ESP8266
|
||||
return;
|
||||
}
|
||||
# ifdef ESP32
|
||||
|
||||
switch (Settings.InitSPI) {
|
||||
case 1:
|
||||
{
|
||||
addHtml(F("VSPI"));
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
addHtml(F("HSPI"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
# endif // ifdef ESP32
|
||||
# ifdef ESP8266
|
||||
addHtml(F("SPI"));
|
||||
# endif // ifdef ESP8266
|
||||
}
|
||||
|
||||
void format_I2C_pin_description()
|
||||
{
|
||||
String html;
|
||||
|
||||
html.reserve(20);
|
||||
html += F("SDA: ");
|
||||
html += formatGpioLabel(Settings.Pin_i2c_sda, false);
|
||||
html += F("<BR>SCL: ");
|
||||
html += formatGpioLabel(Settings.Pin_i2c_scl, false);
|
||||
|
||||
addHtml(html);
|
||||
Label_Gpio_toHtml(F("SDA"), formatGpioLabel(Settings.Pin_i2c_sda, false));
|
||||
html_BR();
|
||||
Label_Gpio_toHtml(F("SCL"), formatGpioLabel(Settings.Pin_i2c_scl, false));
|
||||
}
|
||||
|
||||
void format_SPI_pin_description(int8_t spi_gpios[3], taskIndex_t x)
|
||||
{
|
||||
if (Settings.InitSPI != 0) {
|
||||
if (Settings.InitSPI > 0) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const String pin_descr = formatGpioLabel(spi_gpios[i], false);
|
||||
switch (i) {
|
||||
case 0: addHtml(F("CLK: ")); break;
|
||||
case 1: addHtml(F("MISO: ")); break;
|
||||
case 2: addHtml(F("MOSI: ")); break;
|
||||
case 0: Label_Gpio_toHtml(F("CLK"), pin_descr); break;
|
||||
case 1: Label_Gpio_toHtml(F("MISO"), pin_descr); break;
|
||||
case 2: Label_Gpio_toHtml(F("MOSI"), pin_descr); break;
|
||||
}
|
||||
addHtml(formatGpioLabel(spi_gpios[i], false));
|
||||
html_BR();
|
||||
}
|
||||
addHtml(F("CS: "));
|
||||
addHtml(formatGpioLabel(Settings.TaskDevicePin1[x], false));
|
||||
Label_Gpio_toHtml(F("CS"), formatGpioLabel(Settings.TaskDevicePin1[x], false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,12 +93,12 @@ void handle_hardware() {
|
||||
addFormHeader(F("Hardware Settings"), F("ESPEasy#Hardware_page"), F("Hardware/Hardware.html"));
|
||||
|
||||
addFormSubHeader(F("Wifi Status LED"));
|
||||
addFormPinSelect(formatGpioName_output("LED"), F("pled"), Settings.Pin_status_led);
|
||||
addFormPinSelect(PinSelectPurpose::Generic_output, formatGpioName_output("LED"), F("pled"), Settings.Pin_status_led);
|
||||
addFormCheckBox(F("Inversed LED"), F("pledi"), Settings.Pin_status_led_Inversed);
|
||||
addFormNote(F("Use ’GPIO-2 (D4)’ with ’Inversed’ checked for onboard LED"));
|
||||
|
||||
addFormSubHeader(F("Reset Pin"));
|
||||
addFormPinSelect(formatGpioName_input(F("Switch")), F("pres"), Settings.Pin_Reset);
|
||||
addFormPinSelect(PinSelectPurpose::Generic_input, formatGpioName_input(F("Switch")), F("pres"), Settings.Pin_Reset);
|
||||
addFormNote(F("Press about 10s for factory reset"));
|
||||
|
||||
addFormSubHeader(F("I2C Interface"));
|
||||
@@ -148,7 +148,7 @@ void handle_hardware() {
|
||||
}
|
||||
addFormSelector(F("I2C Multiplexer address"), F("pi2cmuxaddr"), mux_opt + 1, i2c_mux_options, i2c_mux_choices, Settings.I2C_Multiplexer_Addr);
|
||||
}
|
||||
addFormPinSelect(formatGpioName_output_optional("Reset"), F("pi2cmuxreset"), Settings.I2C_Multiplexer_ResetPin);
|
||||
addFormPinSelect(PinSelectPurpose::Generic_output, formatGpioName_output_optional("Reset"), F("pi2cmuxreset"), Settings.I2C_Multiplexer_ResetPin);
|
||||
addFormNote(F("Will be pulled low to force a reset. Reset is not available on PCA9540."));
|
||||
#endif
|
||||
|
||||
@@ -156,7 +156,10 @@ void handle_hardware() {
|
||||
addFormSubHeader(F("SPI Interface"));
|
||||
#ifdef ESP32
|
||||
{
|
||||
const __FlashStringHelper * spi_options[3] = { F("Disabled"), F("VSPI: CLK=GPIO-18, MISO=GPIO-19, MOSI=GPIO-23"), F("HSPI: CLK=GPIO-14, MISO=GPIO-12, MOSI=GPIO-13")};
|
||||
const __FlashStringHelper * spi_options[3] = {
|
||||
F("Disabled"),
|
||||
F("VSPI: CLK=GPIO-18, MISO=GPIO-19, MOSI=GPIO-23"),
|
||||
F("HSPI: CLK=GPIO-14, MISO=GPIO-12, MOSI=GPIO-13")};
|
||||
addFormSelector(F("Init SPI"), F("initspi"), 3, spi_options, NULL, Settings.InitSPI);
|
||||
addFormNote(F("Changing SPI settings requires to manualy restart"));
|
||||
}
|
||||
@@ -167,7 +170,7 @@ void handle_hardware() {
|
||||
addFormNote(F("Chip Select (CS) config must be done in the plugin"));
|
||||
|
||||
#ifdef FEATURE_SD
|
||||
addFormPinSelect(formatGpioName_output(F("SD Card CS")), F("sd"), Settings.Pin_sd_cs);
|
||||
addFormPinSelect(PinSelectPurpose::Generic_output, formatGpioName_output(F("SD Card CS")), F("sd"), Settings.Pin_sd_cs);
|
||||
#endif // ifdef FEATURE_SD
|
||||
|
||||
#ifdef HAS_ETHERNET
|
||||
@@ -190,9 +193,9 @@ void handle_hardware() {
|
||||
}
|
||||
addFormNumericBox(F("Ethernet PHY Address"), F("ethphy"), Settings.ETH_Phy_Addr, 0, 255);
|
||||
addFormNote(F("I²C-address of Ethernet PHY (0 or 1 for LAN8720, 31 for TLK110)"));
|
||||
addFormPinSelect(formatGpioName_output(F("Ethernet MDC pin")), F("ethmdc"), Settings.ETH_Pin_mdc);
|
||||
addFormPinSelect(formatGpioName_input(F("Ethernet MIO pin")), F("ethmdio"), Settings.ETH_Pin_mdio);
|
||||
addFormPinSelect(formatGpioName_output(F("Ethernet Power pin")), F("ethpower"), Settings.ETH_Pin_power);
|
||||
addFormPinSelect(PinSelectPurpose::Ethernet, formatGpioName_output(F("Ethernet MDC pin")), F("ethmdc"), Settings.ETH_Pin_mdc);
|
||||
addFormPinSelect(PinSelectPurpose::Ethernet, formatGpioName_input(F("Ethernet MIO pin")), F("ethmdio"), Settings.ETH_Pin_mdio);
|
||||
addFormPinSelect(PinSelectPurpose::Ethernet, formatGpioName_output(F("Ethernet Power pin")), F("ethpower"), Settings.ETH_Pin_power);
|
||||
addRowLabel_tr_id(F("Ethernet Clock"), F("ethclock"));
|
||||
{
|
||||
const __FlashStringHelper * ethClockOptions[4] = {
|
||||
|
||||
+187
-136
@@ -8,20 +8,21 @@
|
||||
#include "../Helpers/Hardware.h"
|
||||
#include "../Helpers/StringGenerator_GPIO.h"
|
||||
|
||||
#include "../../ESPEasy_common.h"
|
||||
|
||||
// ********************************************************************************
|
||||
// Add Selector
|
||||
// ********************************************************************************
|
||||
void addSelector(const String& id,
|
||||
int optionCount,
|
||||
const __FlashStringHelper * options[],
|
||||
const int indices[],
|
||||
const String attr[],
|
||||
int selectedIndex)
|
||||
void addSelector(const String & id,
|
||||
int optionCount,
|
||||
const __FlashStringHelper *options[],
|
||||
const int indices[],
|
||||
const String attr[],
|
||||
int selectedIndex)
|
||||
{
|
||||
addSelector(id, optionCount, options, indices, attr, selectedIndex, false, true, F("wide"));
|
||||
}
|
||||
|
||||
|
||||
void addSelector(const String& id,
|
||||
int optionCount,
|
||||
const String options[],
|
||||
@@ -32,19 +33,18 @@ void addSelector(const String& id,
|
||||
addSelector(id, optionCount, options, indices, attr, selectedIndex, false, true, F("wide"));
|
||||
}
|
||||
|
||||
void addSelector(const String& id,
|
||||
int optionCount,
|
||||
const __FlashStringHelper * options[],
|
||||
const int indices[],
|
||||
const String attr[],
|
||||
int selectedIndex,
|
||||
boolean reloadonchange,
|
||||
bool enabled)
|
||||
void addSelector(const String & id,
|
||||
int optionCount,
|
||||
const __FlashStringHelper *options[],
|
||||
const int indices[],
|
||||
const String attr[],
|
||||
int selectedIndex,
|
||||
boolean reloadonchange,
|
||||
bool enabled)
|
||||
{
|
||||
addSelector(id, optionCount, options, indices, attr, selectedIndex, reloadonchange, enabled, F("wide"));
|
||||
}
|
||||
|
||||
|
||||
void addSelector(const String& id,
|
||||
int optionCount,
|
||||
const String options[],
|
||||
@@ -57,15 +57,15 @@ void addSelector(const String& id,
|
||||
addSelector(id, optionCount, options, indices, attr, selectedIndex, reloadonchange, enabled, F("wide"));
|
||||
}
|
||||
|
||||
void addSelector(const String& id,
|
||||
int optionCount,
|
||||
const __FlashStringHelper * options[],
|
||||
const int indices[],
|
||||
const String attr[],
|
||||
int selectedIndex,
|
||||
boolean reloadonchange,
|
||||
bool enabled,
|
||||
const String& classname)
|
||||
void addSelector(const String & id,
|
||||
int optionCount,
|
||||
const __FlashStringHelper *options[],
|
||||
const int indices[],
|
||||
const String attr[],
|
||||
int selectedIndex,
|
||||
boolean reloadonchange,
|
||||
bool enabled,
|
||||
const String & classname)
|
||||
{
|
||||
// FIXME TD-er Change boolean to disabled
|
||||
if (reloadonchange)
|
||||
@@ -99,7 +99,7 @@ void addSelector(const String& id,
|
||||
addSelector_Foot();
|
||||
}
|
||||
|
||||
void addSelector_options(int optionCount, const __FlashStringHelper * options[], const int indices[], const String attr[], int selectedIndex)
|
||||
void addSelector_options(int optionCount, const __FlashStringHelper *options[], const int indices[], const String attr[], int selectedIndex)
|
||||
{
|
||||
int index;
|
||||
|
||||
@@ -176,7 +176,91 @@ void do_addSelector_Head(const String& id, const String& classname, const String
|
||||
addHtml('>');
|
||||
}
|
||||
|
||||
void addSelector_Item(const __FlashStringHelper * option, int index, boolean selected, boolean disabled, const String& attr)
|
||||
void addPinSelector_Item(PinSelectPurpose purpose, const String& gpio_label, int gpio, boolean selected, boolean disabled, const String& attr)
|
||||
{
|
||||
if (gpio != -1) // empty selection can never be disabled...
|
||||
{
|
||||
int pinnr = -1;
|
||||
bool input, output, warning;
|
||||
|
||||
if (getGpioInfo(gpio, pinnr, input, output, warning)) {
|
||||
bool includeI2C = true;
|
||||
bool includeSPI = true;
|
||||
#ifdef HAS_ETHERNET
|
||||
bool includeEthernet = true;
|
||||
#endif // ifdef HAS_ETHERNET
|
||||
|
||||
switch (purpose) {
|
||||
case PinSelectPurpose::SPI:
|
||||
includeSPI = false;
|
||||
break;
|
||||
case PinSelectPurpose::Ethernet:
|
||||
#ifdef HAS_ETHERNET
|
||||
includeEthernet = false;
|
||||
#endif // ifdef HAS_ETHERNET
|
||||
break;
|
||||
case PinSelectPurpose::Generic:
|
||||
|
||||
if (!input && !output) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case PinSelectPurpose::Generic_input:
|
||||
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case PinSelectPurpose::Generic_output:
|
||||
|
||||
if (!output) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case PinSelectPurpose::Generic_bidir:
|
||||
case PinSelectPurpose::I2C:
|
||||
includeI2C = false;
|
||||
|
||||
if (!output || !input) {
|
||||
// SDA is obviously bidirectional.
|
||||
// SCL is obviously output, but can be held down by a slave device to signal clock stretch limit.
|
||||
// Thus both must be capable of input & output.
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (includeI2C && Settings.isI2C_pin(gpio)) {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
if (Settings.UseSerial && ((gpio == 1) || (gpio == 3))) {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
if (includeSPI && Settings.isSPI_pin(gpio)) {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
#ifdef HAS_ETHERNET
|
||||
|
||||
if (Settings.isEthernetPin(gpio) || (includeEthernet && Settings.isEthernetPinOptional(gpio))) {
|
||||
disabled = true;
|
||||
}
|
||||
#endif // ifdef HAS_ETHERNET
|
||||
}
|
||||
}
|
||||
|
||||
addSelector_Item(gpio_label,
|
||||
gpio,
|
||||
selected,
|
||||
disabled);
|
||||
}
|
||||
|
||||
void addSelector_Item(const __FlashStringHelper *option, int index, boolean selected, boolean disabled, const String& attr)
|
||||
{
|
||||
addHtml(F("<option "));
|
||||
addHtmlAttribute(F("value"), index);
|
||||
@@ -227,7 +311,7 @@ void addSelector_Foot()
|
||||
addHtml(F("</select>"));
|
||||
}
|
||||
|
||||
void addUnit(const __FlashStringHelper * unit)
|
||||
void addUnit(const __FlashStringHelper *unit)
|
||||
{
|
||||
addHtml(F(" ["));
|
||||
addHtml(unit);
|
||||
@@ -248,12 +332,12 @@ void addUnit(char unit)
|
||||
addHtml(']');
|
||||
}
|
||||
|
||||
void addRowLabel_tr_id(const __FlashStringHelper * label, const __FlashStringHelper * id)
|
||||
void addRowLabel_tr_id(const __FlashStringHelper *label, const __FlashStringHelper *id)
|
||||
{
|
||||
addRowLabel_tr_id(String(label), String(id));
|
||||
}
|
||||
|
||||
void addRowLabel_tr_id(const __FlashStringHelper * label, const String& id)
|
||||
void addRowLabel_tr_id(const __FlashStringHelper *label, const String& id)
|
||||
{
|
||||
addRowLabel_tr_id(String(label), id);
|
||||
}
|
||||
@@ -266,7 +350,7 @@ void addRowLabel_tr_id(const String& label, const String& id)
|
||||
addRowLabel(label, tr_id);
|
||||
}
|
||||
|
||||
void addRowLabel(const __FlashStringHelper * label)
|
||||
void addRowLabel(const __FlashStringHelper *label)
|
||||
{
|
||||
html_TR_TD();
|
||||
addHtml(label);
|
||||
@@ -294,7 +378,7 @@ void addRowLabel(const String& label, const String& id)
|
||||
}
|
||||
|
||||
// Add a row label and mark it with copy markers to copy it to clipboard.
|
||||
void addRowLabel_copy(const __FlashStringHelper * label) {
|
||||
void addRowLabel_copy(const __FlashStringHelper *label) {
|
||||
addHtml(F("<TR>"));
|
||||
html_copyText_TD();
|
||||
addHtml(label);
|
||||
@@ -331,18 +415,18 @@ void addRowLabelValue_copy(LabelType::Enum label) {
|
||||
// ********************************************************************************
|
||||
void addTableSeparator(const __FlashStringHelper *label, int colspan, int h_size)
|
||||
{
|
||||
addHtml(F("<TR><TD colspan="));
|
||||
addHtmlInt(colspan);
|
||||
addHtml(F("><H"));
|
||||
addHtmlInt(h_size);
|
||||
addHtml('>');
|
||||
addHtml(label);
|
||||
addHtml(F("</H"));
|
||||
addHtmlInt(h_size);
|
||||
addHtml(F("></TD></TR>"));
|
||||
addHtml(F("<TR><TD colspan="));
|
||||
addHtmlInt(colspan);
|
||||
addHtml(F("><H"));
|
||||
addHtmlInt(h_size);
|
||||
addHtml('>');
|
||||
addHtml(label);
|
||||
addHtml(F("</H"));
|
||||
addHtmlInt(h_size);
|
||||
addHtml(F("></TD></TR>"));
|
||||
}
|
||||
|
||||
void addTableSeparator(const __FlashStringHelper *label, int colspan, int h_size, const __FlashStringHelper * helpButton)
|
||||
void addTableSeparator(const __FlashStringHelper *label, int colspan, int h_size, const __FlashStringHelper *helpButton)
|
||||
{
|
||||
addTableSeparator(String(label), colspan, h_size, String(helpButton));
|
||||
}
|
||||
@@ -373,7 +457,7 @@ void addTableSeparator(const String& label, int colspan, int h_size, const Strin
|
||||
}
|
||||
}
|
||||
|
||||
void addFormHeader(const __FlashStringHelper * header) {
|
||||
void addFormHeader(const __FlashStringHelper *header) {
|
||||
html_TR();
|
||||
html_table_header(header, EMPTY_STRING, EMPTY_STRING, 225);
|
||||
html_table_header(F(""));
|
||||
@@ -393,7 +477,7 @@ void addFormHeader(const String& header, const String& helpButton, const String&
|
||||
// ********************************************************************************
|
||||
// Add a sub header
|
||||
// ********************************************************************************
|
||||
void addFormSubHeader(const __FlashStringHelper * header) {
|
||||
void addFormSubHeader(const __FlashStringHelper *header) {
|
||||
addTableSeparator(header, 2, 3);
|
||||
}
|
||||
|
||||
@@ -405,7 +489,7 @@ void addFormSubHeader(const String& header)
|
||||
// ********************************************************************************
|
||||
// Add a checkbox
|
||||
// ********************************************************************************
|
||||
void addCheckBox(const __FlashStringHelper * id, boolean checked, bool disabled)
|
||||
void addCheckBox(const __FlashStringHelper *id, boolean checked, bool disabled)
|
||||
{
|
||||
addCheckBox(String(id), checked, disabled);
|
||||
}
|
||||
@@ -432,7 +516,7 @@ void addCheckBox(const String& id, boolean checked, bool disabled)
|
||||
// ********************************************************************************
|
||||
// Add a numeric box
|
||||
// ********************************************************************************
|
||||
void addNumericBox(const __FlashStringHelper * id, int value, int min, int max)
|
||||
void addNumericBox(const __FlashStringHelper *id, int value, int min, int max)
|
||||
{
|
||||
addNumericBox(String(id), value, min, max);
|
||||
}
|
||||
@@ -479,8 +563,10 @@ void addFloatNumberBox(const String& id, float value, float min, float max, byte
|
||||
html += F(" max=");
|
||||
html += String(max, nrDecimals);
|
||||
html += F(" step=");
|
||||
|
||||
if (stepsize <= 0.0f) {
|
||||
html += F("0.");
|
||||
|
||||
for (byte i = 1; i < nrDecimals; ++i) {
|
||||
html += '0';
|
||||
}
|
||||
@@ -564,18 +650,19 @@ void addTextArea(const String& id, const String& value, int maxlength, int rows,
|
||||
|
||||
// adds a Help Button with points to the the given Wiki Subpage
|
||||
// If url starts with "RTD", it will be considered as a Read-the-docs link
|
||||
void addHelpButton(const __FlashStringHelper * url) {
|
||||
addHelpButton(String(url));
|
||||
void addHelpButton(const __FlashStringHelper *url) {
|
||||
addHelpButton(String(url));
|
||||
}
|
||||
|
||||
void addHelpButton(const String& url) {
|
||||
#ifndef WEBPAGE_TEMPLATE_HIDE_HELP_BUTTON
|
||||
|
||||
if (url.startsWith("RTD")) {
|
||||
addRTDHelpButton(url.substring(3));
|
||||
} else {
|
||||
addHelpButton(url, false);
|
||||
}
|
||||
#endif
|
||||
#endif // ifndef WEBPAGE_TEMPLATE_HIDE_HELP_BUTTON
|
||||
}
|
||||
|
||||
void addRTDHelpButton(const String& url)
|
||||
@@ -590,7 +677,7 @@ void addHelpButton(const String& url, bool isRTD)
|
||||
F("button help"),
|
||||
makeDocLink(url, isRTD),
|
||||
isRTD ? F("ℹ") : F("❔"));
|
||||
#endif
|
||||
#endif // ifndef WEBPAGE_TEMPLATE_HIDE_HELP_BUTTON
|
||||
}
|
||||
|
||||
void addRTDPluginButton(pluginID_t taskDeviceNumber) {
|
||||
@@ -631,133 +718,97 @@ String makeDocLink(const String& url, bool isRTD) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void addPinSelect(boolean forI2C, const __FlashStringHelper * id, int choice)
|
||||
void addPinSelect(PinSelectPurpose purpose, const __FlashStringHelper *id, int choice)
|
||||
{
|
||||
addPinSelect(forI2C, String(id), choice);
|
||||
addPinSelect(purpose, String(id), choice);
|
||||
}
|
||||
|
||||
void addPinSelect(boolean forI2C, const String& id, int choice)
|
||||
void addPinSelect(PinSelectPurpose purpose, const String& id, int choice)
|
||||
{
|
||||
#ifdef ESP32
|
||||
# define NR_ITEMS_PIN_DROPDOWN 35 // 34 GPIO + 1
|
||||
#else // ifdef ESP32
|
||||
# define NR_ITEMS_PIN_DROPDOWN 14 // 13 GPIO + 1
|
||||
#endif // ifdef ESP32
|
||||
|
||||
String *gpio_labels = new String[NR_ITEMS_PIN_DROPDOWN];
|
||||
int *gpio_numbers = new int[NR_ITEMS_PIN_DROPDOWN];
|
||||
addSelector_Head(id);
|
||||
|
||||
// At i == 0 && gpio == -1, add the "- None -" option first
|
||||
int i = 0;
|
||||
int gpio = -1;
|
||||
|
||||
while (i < NR_ITEMS_PIN_DROPDOWN && gpio <= MAX_GPIO) {
|
||||
while (gpio <= MAX_GPIO) {
|
||||
int pinnr = -1;
|
||||
bool input, output, warning;
|
||||
bool input, output, warning = false;
|
||||
|
||||
// Make sure getGpioInfo is called (compiler may optimize it away if (i == 0))
|
||||
const bool UsableGPIO = getGpioInfo(gpio, pinnr, input, output, warning);
|
||||
|
||||
if (UsableGPIO || (i == 0)) {
|
||||
String gpio_label = createGPIO_label(gpio, pinnr, input, output, warning);
|
||||
gpio_label += getConflictingUse_wrapped(gpio, purpose);
|
||||
addPinSelector_Item(
|
||||
purpose,
|
||||
gpio_label,
|
||||
gpio,
|
||||
choice == gpio);
|
||||
|
||||
if (getGpioInfo(gpio, pinnr, input, output, warning) || (i == 0)) {
|
||||
gpio_labels[i] = createGPIO_label(gpio, pinnr, input, output, warning);
|
||||
gpio_numbers[i] = gpio;
|
||||
++i;
|
||||
}
|
||||
++gpio;
|
||||
}
|
||||
renderHTMLForPinSelect(gpio_labels, gpio_numbers, forI2C, id, choice, NR_ITEMS_PIN_DROPDOWN);
|
||||
delete[] gpio_numbers;
|
||||
delete[] gpio_labels;
|
||||
#undef NR_ITEMS_PIN_DROPDOWN
|
||||
addSelector_Foot();
|
||||
}
|
||||
|
||||
#ifdef ESP32
|
||||
void addADC_PinSelect(bool touchOnly, const String& id, int choice)
|
||||
void addADC_PinSelect(AdcPinSelectPurpose purpose, const String& id, int choice)
|
||||
{
|
||||
int NR_ITEMS_PIN_DROPDOWN = touchOnly ? 10 : 19;
|
||||
String *gpio_labels = new String[NR_ITEMS_PIN_DROPDOWN];
|
||||
int *gpio_numbers = new int[NR_ITEMS_PIN_DROPDOWN];
|
||||
addSelector_Head(id);
|
||||
|
||||
// At i == 0 && gpio == -1, add the "Hall Effect" option first
|
||||
int i = 0;
|
||||
int gpio = -1;
|
||||
|
||||
while (i < NR_ITEMS_PIN_DROPDOWN && gpio <= MAX_GPIO) {
|
||||
if ((purpose == AdcPinSelectPurpose::ADC_Touch_HallEffect) ||
|
||||
(purpose == AdcPinSelectPurpose::ADC_Touch_Optional)) {
|
||||
addPinSelector_Item(
|
||||
PinSelectPurpose::Generic,
|
||||
purpose == AdcPinSelectPurpose::ADC_Touch_Optional ? F("- None -") : formatGpioName_ADC(gpio),
|
||||
gpio,
|
||||
choice == gpio);
|
||||
++i;
|
||||
}
|
||||
|
||||
while (i <= MAX_GPIO && gpio <= MAX_GPIO) {
|
||||
int pinnr = -1;
|
||||
bool input, output, warning;
|
||||
|
||||
if (touchOnly) {
|
||||
if (purpose == AdcPinSelectPurpose::TouchOnly) {
|
||||
// For touch only list, sort based on touch number
|
||||
// Default sort is on GPIO number.
|
||||
gpio = touchPinToGpio(i);
|
||||
} else {
|
||||
++gpio;
|
||||
}
|
||||
|
||||
if (getGpioInfo(gpio, pinnr, input, output, warning) || (i == 0)) {
|
||||
if (getGpioInfo(gpio, pinnr, input, output, warning)) {
|
||||
int adc, ch, t;
|
||||
|
||||
if (getADC_gpio_info(gpio, adc, ch, t)) {
|
||||
if (!touchOnly || (t >= 0)) {
|
||||
gpio_labels[i] = formatGpioName_ADC(gpio);
|
||||
if ((purpose != AdcPinSelectPurpose::TouchOnly) || (t >= 0)) {
|
||||
String gpio_label;
|
||||
gpio_label = formatGpioName_ADC(gpio);
|
||||
|
||||
if (adc != 0) {
|
||||
gpio_labels[i] += F(" / ");
|
||||
gpio_labels[i] += createGPIO_label(gpio, pinnr, input, output, warning);
|
||||
gpio_label += F(" / ");
|
||||
gpio_label += createGPIO_label(gpio, pinnr, input, output, warning);
|
||||
gpio_label += getConflictingUse_wrapped(gpio);
|
||||
}
|
||||
gpio_numbers[i] = gpio;
|
||||
++i;
|
||||
addPinSelector_Item(
|
||||
PinSelectPurpose::Generic,
|
||||
gpio_label,
|
||||
gpio,
|
||||
choice == gpio);
|
||||
}
|
||||
}
|
||||
}
|
||||
++gpio;
|
||||
}
|
||||
bool forI2C = false;
|
||||
|
||||
renderHTMLForPinSelect(gpio_labels, gpio_numbers, forI2C, id, choice, i);
|
||||
delete[] gpio_numbers;
|
||||
delete[] gpio_labels;
|
||||
}
|
||||
|
||||
#endif // ifdef ESP32
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
// Helper function actually rendering dropdown list for addPinSelect()
|
||||
// ********************************************************************************
|
||||
void renderHTMLForPinSelect(String options[], int optionValues[], boolean forI2C, const String& id, int choice, int count) {
|
||||
addSelector_Head(id);
|
||||
|
||||
for (byte x = 0; x < count; x++)
|
||||
{
|
||||
boolean disabled = false;
|
||||
|
||||
if (optionValues[x] != -1) // empty selection can never be disabled...
|
||||
{
|
||||
if (!forI2C && ((optionValues[x] == Settings.Pin_i2c_sda) || (optionValues[x] == Settings.Pin_i2c_scl))) {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
if (Settings.UseSerial && ((optionValues[x] == 1) || (optionValues[x] == 3))) {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
if (Settings.InitSPI != 0) {
|
||||
#ifdef ESP32
|
||||
|
||||
switch (Settings.InitSPI)
|
||||
{
|
||||
case 1:
|
||||
disabled = (optionValues[x] == 18 || optionValues[x] == 19 || optionValues[x] == 23);
|
||||
break;
|
||||
case 2:
|
||||
disabled = (optionValues[x] == 14 || optionValues[x] == 12 || optionValues[x] == 13);
|
||||
break;
|
||||
}
|
||||
#else // #ifdef ESP32
|
||||
disabled = (optionValues[x] == 14 || optionValues[x] == 12 || optionValues[x] == 13);
|
||||
#endif // ifdef ESP32
|
||||
}
|
||||
}
|
||||
addSelector_Item(options[x],
|
||||
optionValues[x],
|
||||
choice == optionValues[x],
|
||||
disabled);
|
||||
++i;
|
||||
}
|
||||
addSelector_Foot();
|
||||
}
|
||||
|
||||
#endif // ifdef ESP32
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "../WebServer/common.h"
|
||||
#include "../Globals/Plugins.h"
|
||||
#include "../Helpers/StringGenerator_GPIO.h"
|
||||
|
||||
// ********************************************************************************
|
||||
// Add Selector
|
||||
@@ -73,6 +74,8 @@ void addSelector_Head_reloadOnChange(const String& id, const String& classname,
|
||||
|
||||
void do_addSelector_Head(const String& id, const String& classname, const String& onChangeCall, const bool& disabled);
|
||||
|
||||
void addPinSelector_Item(PinSelectPurpose purpose, const String& gpio_label, int gpio, boolean selected, boolean disabled = false, const String& attr = EMPTY_STRING);
|
||||
|
||||
void addSelector_Item(const __FlashStringHelper * option, int index, boolean selected, boolean disabled = false, const String& attr = EMPTY_STRING);
|
||||
void addSelector_Item(const String& option, int index, boolean selected, boolean disabled = false, const String& attr = EMPTY_STRING);
|
||||
|
||||
@@ -158,18 +161,20 @@ void addRTDPluginButton(pluginID_t taskDeviceNumber);
|
||||
|
||||
String makeDocLink(const String& url, bool isRTD);
|
||||
|
||||
void addPinSelect(boolean forI2C, const __FlashStringHelper * id, int choice);
|
||||
void addPinSelect(boolean forI2C, const String& id, int choice);
|
||||
|
||||
void addPinSelect(PinSelectPurpose purpose, const __FlashStringHelper * id, int choice);
|
||||
void addPinSelect(PinSelectPurpose purpose, const String& id, int choice);
|
||||
|
||||
|
||||
#ifdef ESP32
|
||||
void addADC_PinSelect(bool touchOnly, const String& id, int choice);
|
||||
enum class AdcPinSelectPurpose {
|
||||
TouchOnly,
|
||||
ADC_Touch,
|
||||
ADC_Touch_HallEffect,
|
||||
ADC_Touch_Optional
|
||||
};
|
||||
void addADC_PinSelect(AdcPinSelectPurpose purpose, const String& id, int choice);
|
||||
#endif
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
// Helper function actually rendering dropdown list for addPinSelect()
|
||||
// ********************************************************************************
|
||||
void renderHTMLForPinSelect(String options[], int optionValues[], boolean forI2C, const String& id, int choice, int count);
|
||||
|
||||
#endif
|
||||
@@ -216,17 +216,23 @@ void addFormIPaccessControlSelect(const String& label, const String& id, int cho
|
||||
// ********************************************************************************
|
||||
// Add a selector form
|
||||
// ********************************************************************************
|
||||
void addFormPinSelect(PinSelectPurpose purpose, const String& label, const __FlashStringHelper * id, int choice)
|
||||
{
|
||||
addRowLabel_tr_id(label, id);
|
||||
addPinSelect(purpose, id, choice);
|
||||
}
|
||||
|
||||
|
||||
void addFormPinSelect(const String& label, const __FlashStringHelper * id, int choice)
|
||||
{
|
||||
addRowLabel_tr_id(label, id);
|
||||
addPinSelect(false, id, choice);
|
||||
addPinSelect(PinSelectPurpose::Generic, id, choice);
|
||||
}
|
||||
|
||||
void addFormPinSelectI2C(const String& label, const String& id, int choice)
|
||||
{
|
||||
addRowLabel_tr_id(label, id);
|
||||
addPinSelect(true, id, choice);
|
||||
addPinSelect(PinSelectPurpose::I2C, id, choice);
|
||||
}
|
||||
|
||||
void addFormSelectorI2C(const String& id, int addressCount, const int addresses[], int selectedIndex)
|
||||
@@ -340,18 +346,25 @@ void addFormPinStateSelect(int gpio, int choice)
|
||||
// do not add the pin state select for these pins.
|
||||
enabled = false;
|
||||
}
|
||||
if (Settings.isEthernetPin(gpio)) {
|
||||
// do not add the pin state select for non-optional Ethernet pins
|
||||
enabled = false;
|
||||
}
|
||||
int pinnr = -1;
|
||||
bool input, output, warning;
|
||||
|
||||
if (getGpioInfo(gpio, pinnr, input, output, warning)) {
|
||||
String label;
|
||||
label.reserve(32);
|
||||
label = F("Pin mode ");
|
||||
label += createGPIO_label(gpio, pinnr, input, output, warning);
|
||||
String id = "p";
|
||||
String id;
|
||||
id += 'p';
|
||||
id += gpio;
|
||||
{
|
||||
String label;
|
||||
label.reserve(32);
|
||||
label = F("Pin mode ");
|
||||
label += createGPIO_label(gpio, pinnr, input, output, warning);
|
||||
|
||||
addRowLabel_tr_id(label, id);
|
||||
addRowLabel_tr_id(label, id);
|
||||
}
|
||||
bool hasPullUp, hasPullDown;
|
||||
getGpioPullResistor(gpio, hasPullUp, hasPullDown);
|
||||
int nr_options = 0;
|
||||
@@ -390,6 +403,12 @@ void addFormPinStateSelect(int gpio, int choice)
|
||||
}
|
||||
}
|
||||
addSelector(id, nr_options, options, option_val, NULL, choice, false, enabled);
|
||||
{
|
||||
const String conflict = getConflictingUse(gpio);
|
||||
if (!conflict.isEmpty()) {
|
||||
addUnit(conflict);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../WebServer/common.h"
|
||||
|
||||
#include "../Globals/Plugins.h"
|
||||
#include "../Helpers/StringGenerator_GPIO.h"
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
@@ -100,6 +101,7 @@ void addFormIPaccessControlSelect(const String& label, const String& id, int cho
|
||||
// Add a selector form
|
||||
// ********************************************************************************
|
||||
|
||||
void addFormPinSelect(PinSelectPurpose purpose, const String& label, const __FlashStringHelper * id, int choice);
|
||||
void addFormPinSelect(const String& label, const __FlashStringHelper * id, int choice);
|
||||
|
||||
void addFormPinSelectI2C(const String& label, const String& id, int choice);
|
||||
|
||||
@@ -203,7 +203,7 @@ void handle_notifications() {
|
||||
if (Notification[NotificationProtocolIndex].usesGPIO > 0)
|
||||
{
|
||||
addRowLabel(F("1st GPIO"));
|
||||
addPinSelect(false, F("pin1"), NotificationSettings.Pin1);
|
||||
addPinSelect(PinSelectPurpose::Generic, F("pin1"), NotificationSettings.Pin1);
|
||||
}
|
||||
|
||||
addRowLabel(F("Enabled"));
|
||||
|
||||
Reference in New Issue
Block a user