diff --git a/docs/source/Plugin/P137.rst b/docs/source/Plugin/P137.rst index 4ef35bfe2c..6ed189a235 100644 --- a/docs/source/Plugin/P137.rst +++ b/docs/source/Plugin/P137.rst @@ -65,7 +65,7 @@ Hardware outputs AXP192 * *LilyGO T-Beam* Settings for the LilyGO T-Beam series of GPS/LoRa devices with optional OLed display. -* *User defined* To be able to configure are available output pins the User defined option is available, f.e. when using a custom designed, or not yet supported, hardware setup. +* *User defined* To be able to configure all available output pins the User defined option is available, f.e. when using a custom designed, or not yet supported, hardware setup. When available, new predefined devices will be added. The User defined option will stay the last option. diff --git a/docs/source/Plugin/P139.rst b/docs/source/Plugin/P139.rst new file mode 100644 index 0000000000..2136fccd57 --- /dev/null +++ b/docs/source/Plugin/P139.rst @@ -0,0 +1,198 @@ +.. include:: ../Plugin/_plugin_substitutions_p13x.repl +.. _P139_page: + +|P139_typename| +================================================== + +|P139_shortinfo| + +Plugin details +-------------- + +Type: |P139_type| + +Name: |P139_name| + +Status: |P139_status| + +GitHub: |P139_github|_ + +Maintainer: |P139_maintainer| + +Used libraries: |P139_usedlibraries| + +Description +----------- + +I2C Power management controller. As found in some ESP32 models of M5Stack and TTGO. + +Plugin is only available in ESP32 builds, as the library uses some software constructs that aren't available for ESP8266, and this controller is currently only found to be used with ESP32 boards. + +Configuration +-------------- + +.. image:: P139_DeviceConfiguration.png + :alt: Device configuration + +* **Name** A unique name should be entered here. + +* **Enabled** The device can be disabled or enabled. When not enabled the device should not use any resources. + +.. include:: PriorityTask.rst + +I2C Options +^^^^^^^^^^^^ + +The available settings here depend on the build used. At least the **Force Slow I2C speed** option is available, but selections for the I2C Multiplexer can also be shown. For details see the :ref:`Hardware_page` + +Device Settings +^^^^^^^^^^^^^^^^ + +* **Charge LED**: Select the working of the Charge LED (if that's available on your device). Available options: + +.. image:: P139_ChargeLEDOptions.png + +* *Off*: Do not turn the LED on during charging. + +* *Flash 1Hz*: The LED will flash in a slow 1Hz tempo during charging. + +* *Flash 4Hz*: The LED will flash in a somewhat faster 4Hz rate during charging. + +* *Steady On*: The LED will be on during charging. + +.. + +* **Generate events**: Generate events when the charging state changes. There are 2 event values for this event: ``#ChargingState=,``. + +Hardware ports AXP2101 +^^^^^^^^^^^^^^^^^^^^^^ + +* **Predefined device configuration** The plugin provides presets for some specific devices: + +.. image:: P139_PredefinedDeviceOptions.png + +* *Select an option to set default values*: This option will always be selected when opening the page. + +* *M5Stack Core2 v1.1*: Settings for the M5Stack Core2 v1.1, and some derived special models, hardware (not for v1.0 hardware). + +* *M5Stack Core S3*: Settings for the M5Stack S3 hardware. + +* *LilyGO T-Beam v1.2*: Settings for the LilyGO T-Beam v1.2 series of GPS/LoRa devices with optional OLed display (not for v1.0 or v1.1 models). + +* *LilyGO T-Beam S3 v3*: Settings for the LilyGO T-Beam S3 v3 series hardware. + +* *LilyGO T-Pcie v1.2*: Settings for the LilyGO T-Pcie v1.2 series hardware. + +* *User defined*: To be able to configure all available ports the User defined option is added, f.e. when using a custom designed, or not yet supported, hardware setup. + +When available, new predefined devices will be added. The User defined option will stay the last option. + +Depending on the selected configuration, the ports of the AXP2101 can be set at a predefined value. When setting a value below the minimum value (shown next to the voltage selector), the port will be turned off. Above the maximum voltage is not supported/allowed. Stepsize/resolution depends on the port, and can be found in the technical documentation of the AXP2101. + +.. warning:: Check board documentation for what each port is actually connected to, and the allowed voltage range for that port. + +For the available ports, the initial state can be selected. The available options are: + +.. image:: P139_InitialStateOptions.png + +* *Off*: Sets the state to off level (0 V). + +* *On*: Sets the state to on (high) level. + +* *Default*: Doesn't set the state of the port. + +If the column shows ``[Protected]`` or ``[Disabled]``, that port is not available for use in the current configuration or in the commands (see below). + +Output Configuration +^^^^^^^^^^^^^^^^^^^^ + +* **Number Output Values**: Select the number of values that have to be available. The default is set to *Quad*, as there are far more than 4 values available for display. + +Available options: *Single* (1), *Dual* (2), *Triple* (3) and *Quad* (4). + +* **Value 1..4**: Select the desired value to be available in the Values fields. The name of the Values will be set to a matching default automatically, but can be changed afterward. + +.. image:: P139_ValueOptions.png + +.. image:: P139_ValueOptionsB.png + +Available options: + +* *None*: To leave the value empty/0.00 + +* *DCDC1* .. *CPULDOS*: The voltage of the port. + +* *ChargeLed*: The state of the Charge LED, 0 = Off, 1 = Flash 1Hz, 2 = Flash 4Hz, 3 = Steady On. + +* *BatCharge*: The charge state percentage of the battery. + +* *ChargingState*: The state of charging, -1 = discharging, 0 = standby, 1 = charging. + +* *BatPresent*: Is a battery present (1) or disconnected (0). + +* *ChipID*: The ID set in the chip, 0 = not found, 71 = AXP2101. + +* *ChargingDetail*: The detailed state of charging. + + * 0: ``tri-charge`` + * 1: ``pre-charge`` + * 2: ``constant charge (CC)`` + * 3: ``constant voltage (CV)`` + * 4: ``charge done`` + * 5: ``not charging`` + +* *BatVoltage*: The battery voltage. + +* *BatTemp*: The temperature of the battery, (if a battery-temperature sensor is installed). + +* *BusVoltage*: The bus-voltage. + +* *SysVoltage*: The system-voltage. + +* *ChipTemp*: The internal temperature of the chip. + + +.. note:: Not all options hold usable values for all boards, some may even be not connected. Check the board documentation for available values. + +Data Acquisition +^^^^^^^^^^^^^^^^ + +This group of settings, **Single event with all values**, **Send to Controller** and **Interval** settings are standard available configuration items. Send to Controller is only visible when one or more Controllers are configured. + +* **Interval** By default, Interval will be set to 0 sec. as it is optional. When set > 0 it is the frequency used to read sensor values and send these to any Controllers configured for this device. + +Values +^^^^^^ + +The measured values are available in variables, where the initial names are determined by the selected **Value 1..4** settings. A formula can be set to recalculate. The number of decimals can be set as desired, and defaults to 2. + +In selected builds, per Value **Stats** options are available, that when enabled, will gather the measured data and present most recent data in a graph, as described here: :ref:`Task Value Statistics: ` + +Commands +~~~~~~~~ + +.. include:: P139_commands.repl + + +Extra values +~~~~~~~~~~~~ + +As this plugin has more values available than can be set in the regular Values fields, all values are also available from the Get Config feature. + +.. include:: P139_values.repl + + +Extra events +~~~~~~~~~~~~ + +Besides the regular events, of ``#=`` or ``#All=,..`` when the **Interval** is set, there can be an extra event generated: + +.. include:: P139_events.repl + + +Change log +---------- + +.. versionchanged:: 2.0 + + |added| 2025-01-19 Initially added. diff --git a/docs/source/Plugin/P139_ChargeLEDOptions.png b/docs/source/Plugin/P139_ChargeLEDOptions.png new file mode 100644 index 0000000000..dc1f155e7f Binary files /dev/null and b/docs/source/Plugin/P139_ChargeLEDOptions.png differ diff --git a/docs/source/Plugin/P139_DeviceConfiguration.png b/docs/source/Plugin/P139_DeviceConfiguration.png new file mode 100644 index 0000000000..be65f35e55 Binary files /dev/null and b/docs/source/Plugin/P139_DeviceConfiguration.png differ diff --git a/docs/source/Plugin/P139_InitialStateOptions.png b/docs/source/Plugin/P139_InitialStateOptions.png new file mode 100644 index 0000000000..1628edddb0 Binary files /dev/null and b/docs/source/Plugin/P139_InitialStateOptions.png differ diff --git a/docs/source/Plugin/P139_PredefinedDeviceOptions.png b/docs/source/Plugin/P139_PredefinedDeviceOptions.png new file mode 100644 index 0000000000..6c4034418d Binary files /dev/null and b/docs/source/Plugin/P139_PredefinedDeviceOptions.png differ diff --git a/docs/source/Plugin/P139_ValueOptions.png b/docs/source/Plugin/P139_ValueOptions.png new file mode 100644 index 0000000000..85a0a2479f Binary files /dev/null and b/docs/source/Plugin/P139_ValueOptions.png differ diff --git a/docs/source/Plugin/P139_ValueOptionsB.png b/docs/source/Plugin/P139_ValueOptionsB.png new file mode 100644 index 0000000000..ec8a3a4c8a Binary files /dev/null and b/docs/source/Plugin/P139_ValueOptionsB.png differ diff --git a/docs/source/Plugin/P139_commands.repl b/docs/source/Plugin/P139_commands.repl new file mode 100644 index 0000000000..b9fbe22dac --- /dev/null +++ b/docs/source/Plugin/P139_commands.repl @@ -0,0 +1,53 @@ +.. csv-table:: + :header: "Command Syntax", "Extra information" + :widths: 20, 30 + + " + | Commands to control the AXP2101 port voltages & states. + "," + | **Attention**: Commands will fail if the selected port is 'Protected' or 'Disabled' according to the selected Predefined device configuration. + " + " + | ``axp,readchip`` + + "," + | List the current values as configured in the chip. The logging level must be set to ``INFO``. This data can be used to configure additional predefined devices. + " + " + | ``axp,voltage,,`` + + | ``port`` one of the available ports. + | ``voltage`` range: 0.. mV. + "," + | Set selected port to the specified voltage. When set to 0 mV the port will be turned off. + | Ports of the AXP2101: ``DCDC1`` .. ``DCDC4``, ``ALDO1`` .. ``ALDO4``, ``BLDO1``, ``BLDO2``, ``DLDO1``, ``DLDO2`` or ``CPULDOS``. + + | The max port voltage depends on the selected port, and is available in the technical documentation of the AXP2101. + " + " + | ``axp,on,`` + + | ``port`` one of the available ports. + "," + | Set the selected AXP2101 port ON. + | Ports of the AXP2101: ``DCDC1`` .. ``DCDC4``, ``ALDO1`` .. ``ALDO4``, ``BLDO1``, ``BLDO2``, ``DLDO1``, ``DLDO2`` or ``CPULDOS``. + " + " + | ``axp,off,`` + + | ``port`` one of the available ports. + "," + | Set the selected AXP2101 port OFF. + | Ports of the AXP2101: ``DCDC1`` .. ``DCDC4``, ``ALDO1`` .. ``ALDO4``, ``BLDO1``, ``BLDO2``, ``DLDO1``, ``DLDO2`` or ``CPULDOS``. + " + " + | ``axp,percentage,,`` + + | ``port`` one of the available Ports. + | ``percentage``: 0 (off/low) or 1..100% + "," + | Set the selected port to Off for 0%, or On in range .. for 1..100%. + | Ports of the AXP2101: ``DCDC1`` .. ``DCDC4``, ``ALDO1`` .. ``ALDO4``, ``BLDO1``, ``BLDO2``, ``DLDO1``, ``DLDO2`` or ``CPULDOS``. + + | The min and max port voltages depend on the selected port, and are available in the technical documentation of the AXP2101. + " diff --git a/docs/source/Plugin/P139_events.repl b/docs/source/Plugin/P139_events.repl new file mode 100644 index 0000000000..5ccd127cdc --- /dev/null +++ b/docs/source/Plugin/P139_events.repl @@ -0,0 +1,12 @@ +.. csv-table:: + :header: "Event", "Extra information" + :widths: 20, 30 + + " + | ``#ChargingState=,`` + + | ``new_state`` / ``old_state``: ``-1`` (Discharging), ``0`` (Standby) or ``1`` (Charging). + + "," + | Event generated when the **Generate events** checkbox is enabled. + " diff --git a/docs/source/Plugin/P139_values.repl b/docs/source/Plugin/P139_values.repl new file mode 100644 index 0000000000..b9ff876efe --- /dev/null +++ b/docs/source/Plugin/P139_values.repl @@ -0,0 +1,79 @@ +.. csv-table:: + :escape: ^ + :widths: 20, 30 + + " + Most value options can be appended with ``.status`` (or ``.state`` for ``BatCharge`` and any of the ports) + "," + | ``.status``: A text representation of the value will be returned, where applicable. + | ``.state``: A numeric representation of the value will be returned (usually the same as if the plain value name was used.) + + | Example: ``[#ChargingDetail.status]`` will return ``constant charge (CC)`` for ``ChargingDetail`` = 2. + " + " + ``[#]`` + "," + | Ports of the AXP2101: ``DCDC1`` .. ``DCDC4``, ``ALDO1`` .. ``ALDO4``, ``BLDO1``, ``BLDO2``, ``DLDO1``, ``DLDO2`` or ``CPULDOS``. + " + " + ``[#ChargeLed]`` + "," + | The state of the Charge LED, 0 = ``Off``, 1 = ``Flash 1Hz``, 2 = ``Flash 4Hz``, 3 = ``Steady On``. + " + " + ``[#BatCharge]`` + "," + | The charge state percentage of the battery. + " + " + ``[#ChargingState]`` + "," + | The state of charging, -1 = ``Discharging``, 0 = ``Standby``, 1 = ``Charging``. + " + " + ``[#BatPresent]`` + "," + | Is a battery present (1) or disconnected (0). (no ``.status`` value available) + " + " + ``[#ChipID]`` + "," + | The ID set in the chip, 71 = ``AXP2101`` or any numeric value found, returning an empty value for the ``.status`` command-suffix. + " + " + ``[#ChargingDet]`` + "," + | The detailed state of charging. + + * 0: ``tri-charge`` + * 1: ``pre-charge`` + * 2: ``constant charge (CC)`` + * 3: ``constant voltage (CV)`` + * 4: ``charge done`` + * 5: ``not charging`` + " + " + ``[#BatVoltage]`` + "," + | The current voltage of the battery. + " + " + ``[#BatTemp]`` + "," + | The temperature of the battery, (if a battery-temperature sensor is installed). + " + " + ``[#VBus]`` + "," + | The bus-voltage. + " + " + ``[#VSys]`` + "," + | The charge state percentage of the battery. + " + " + ``[#ChipTemp]`` + "," + | The internal temperature of the chip. + " diff --git a/docs/source/Plugin/PriorityTask.rst b/docs/source/Plugin/PriorityTask.rst index 795a645f2b..180c792b3d 100644 --- a/docs/source/Plugin/PriorityTask.rst +++ b/docs/source/Plugin/PriorityTask.rst @@ -1,26 +1,26 @@ Priority task ^^^^^^^^^^^^^ -* **Priority task** The Priority task option is available in selected plugins only, where they can be configured to be initialized as part of the ESPEasy hardware initialization procedure. +* **Priority task**: The Priority task option is available in selected plugins only, where they can be configured to be initialized as part of the ESPEasy hardware initialization procedure. -For some ESP devices, the installed controllers need to be powered via a Power management device before they can be initialized, but as the Power management controllers are implemented as plugins, to use the available Device configuration infrastructure, a mechanism to load and initialize these plugins before parts of the hardware, like the SPI interface, are initialized, the Priority task option is available. +For some ESP devices, the installed controllers need to be powered on via a Power management device before they can be initialized, but as the Power management controllers are implemented as plugins, to use the available Device configuration infrastructure, a mechanism to load and initialize these plugins before parts of the hardware, like the SPI interface, are initialized, the Priority task option is available. Enable a Priority task ~~~~~~~~~~~~~~~~~~~~~~ -* *Configure the plugin as desired and required* All settings must be completed **before** assigning the Priority task setting, as once enabled, no settings can be changed, to avoid the unit getting into a hardware deadlock. +* **Configure the plugin as desired and required**: All settings must be completed **before** assigning the Priority task setting, as once enabled, no settings can be changed, to avoid the unit getting into a hardware deadlock. -* *Check if the settings are as intended* Just a double-check option to validate the plugin settings. This includes enabling the plugin. +* **Check if the settings are as intended**: Just a double-check option to validate the plugin settings. This includes enabling the plugin. -* *Enable the Priority task option* Once the plugin is enabled, the settings are saved in that state, and no other Power management plugin is enabled as Priority task, the checkbox will be enabled, and can be checked. +* **Enable the Priority task option**: Once the plugin is enabled, the settings are saved in that state, and no other Power management plugin is enabled as Priority task, the checkbox will be enabled, and can be checked. .. image:: PriorityTask_Unchecked.png -* *Save the plugin with enabled Priority task* Enable the checkbox, and Submit the device page. After the usual page reload, the Enabled checkbox, while it still *looks* available, can no longer be unchecked, the Predefined device configuration won't reload the page, and the *Submit* and *Delete* buttons are no longer available. +* **Save the plugin with enabled Priority task**: Enable the checkbox, and Submit the device page. After the usual page reload, the Enabled checkbox, while it still *looks* available, can no longer be unchecked, the Predefined device configuration won't reload the page, and the *Submit* and *Delete* buttons are no longer available. .. image:: PriorityTask_Buttons.png -* *Reboot the ESP* To complete the Priority task configuration, the device needs to be restarted. This can be achieved by a reboot command, or using the Reboot button on the Tools page, a power cycle, or by pressing the reset button, if available. +* **Reboot the ESP**: To complete the Priority task configuration, the device needs to be restarted. This can be achieved by a ``reboot`` command, or using the Reboot button on the Tools page, a power cycle, or by pressing the reset button, if available. When viewing the log during startup, these extra log messages are available at the Info level: @@ -31,6 +31,8 @@ When viewing the log during startup, these extra log messages are available at t 8035 : Info : INIT : Started Priority task 1, [AXP192] Power mgt - AXP192 Power management 8036 : Info : INIT : SPI not enabled +(The taskname and activated plugin can change, depending on the used Power mgt plugin.) + .. note:: An enabled Priority task can not be disabled, or re-enabled, using the ``TaskEnable,`` and ``TaskDisable,`` commands, to avoid hardware dead-lock situations. @@ -46,17 +48,17 @@ After configuring the SPI settings, any Device that needs the SPI interface, lik Disable a Priority task ~~~~~~~~~~~~~~~~~~~~~~~ -* *Prepare configuration to disable Priority task* If the Priority task needs to be disabled, it is required to execute a similar procedure as when enabling the Priority task, but in reverse order. +* **Prepare configuration to disable Priority task**: If the Priority task needs to be disabled, it is required to execute a similar procedure as when enabling the Priority task, but in reverse order. - * *Disable Devices/Tasks that use the specific hardware* Any task that uses the hardware, controlled via the Priority task, like a TFT controller, **must** be disabled (and saved). + * **Disable Devices/Tasks that use the specific hardware**: Any task that uses the hardware, controlled via the Priority task, like a TFT controller, **must** be disabled (and saved). - * *Disable the hardware interface* The same goes for the SPI interface, it **must** be disabled on the Hardware page, and the device should at least be rebooted, to activate that change. + * **Disable the hardware interface**: The same goes for the SPI interface, it **must** be disabled on the Hardware page, and the device should at least be rebooted, to activate that change. -* *Send the command to disable the priority task* To disable a priority task, a separate command is introduced: ``disableprioritytask,`` that takes 1 required argument, the name or number of a task that is a Priority task. This will disable the Priority task state in memory, **but not save that state!** +* **Send the command to disable the priority task**: To disable a priority task, a separate command is introduced: ``disableprioritytask,`` that takes 1 required argument, the name or number of a task that is a Priority task. This will disable the Priority task state in memory, **but not save that state!** -* *Open the Device configuration* To complete disabling of the former Priority task, open the device confguration page for that task. You will notice that the Enabled checkbox is still disabled (can't be clicked to change state). To complete this, the page should be saved using the Submit button. When the page is reloaded, also the task will be **Disabled** automatically! If so desired, instead of saving the page, the task can immediately be deleted by use of the Delete button. +* **Open the Device configuration**: To complete disabling of the former Priority task, open the device confguration page for that task. You will notice that the Enabled checkbox is still disabled (can't be clicked to change state). To complete this, the page should be saved using the Submit button. When the page is reloaded, also the task will be **Disabled** automatically! If so desired, instead of saving the page, the task can immediately be deleted by use of the Delete button. -* *Procedure completed* The Priority task is now disabled (or removed), and the settings are updated. After another reboot, the startup log will provide the matching information: +* **Procedure completed**: The Priority task is now disabled (or removed), and the settings are updated. After another reboot, the startup log will provide the matching information: .. code-block:: text @@ -66,3 +68,5 @@ Disable a Priority task (No mention of a Priority task being started.) + +[End of Priority task paragraph] diff --git a/docs/source/Plugin/_Plugin.rst b/docs/source/Plugin/_Plugin.rst index 842a6ed852..76a8cb6927 100644 --- a/docs/source/Plugin/_Plugin.rst +++ b/docs/source/Plugin/_Plugin.rst @@ -374,6 +374,7 @@ There are different released versions of ESP Easy: ":ref:`P135_page`","|P135_status|","P135" ":ref:`P137_page`","|P137_status|","P137" ":ref:`P138_page`","|P138_status|","P138" + ":ref:`P139_page`","|P139_status|","P139" ":ref:`P141_page`","|P141_status|","P141" ":ref:`P142_page`","|P142_status|","P142" ":ref:`P143_page`","|P143_status|","P143" diff --git a/docs/source/Plugin/_plugin_categories.repl b/docs/source/Plugin/_plugin_categories.repl index 6aad869d22..e7398a569b 100644 --- a/docs/source/Plugin/_plugin_categories.repl +++ b/docs/source/Plugin/_plugin_categories.repl @@ -24,7 +24,7 @@ .. |Plugin_Notify| replace:: :ref:`P055_page`, :ref:`P065_page` .. |Plugin_Output| replace:: :ref:`P029_page`, :ref:`P038_page`, :ref:`P041_page`, :ref:`P042_page`, :ref:`P043_page`, :ref:`P070_page`, :ref:`P124_page`, :ref:`P126_page`, :ref:`P128_page`, :ref:`P152_page`, :ref:`P162_page`, :ref:`P166_page` .. |Plugin_Position| replace:: :ref:`P082_page`, :ref:`P121_page`, :ref:`P142_page` -.. |Plugin_PowerMgt| replace:: :ref:`P137_page`, :ref:`P138_page` +.. |Plugin_PowerMgt| replace:: :ref:`P137_page`, :ref:`P138_page`, :ref:`P139_page` .. |Plugin_Presence| replace:: :ref:`P159_page` .. |Plugin_Regulator| replace:: :ref:`P021_page` .. |Plugin_RFID| replace:: :ref:`P008_page`, :ref:`P017_page`, :ref:`P040_page`, :ref:`P111_page` diff --git a/docs/source/Plugin/_plugin_substitutions_p13x.repl b/docs/source/Plugin/_plugin_substitutions_p13x.repl index 7816f26640..b409522581 100644 --- a/docs/source/Plugin/_plugin_substitutions_p13x.repl +++ b/docs/source/Plugin/_plugin_substitutions_p13x.repl @@ -88,3 +88,16 @@ .. |P138_maintainer| replace:: `tonhuisman` .. |P138_compileinfo| replace:: `.` .. |P138_usedlibraries| replace:: `https://github.com/codewitch-honey-crisis/htcw_ip5306` + +.. |P139_name| replace:: :cyan:`AXP2101 Power management ESP32` +.. |P139_type| replace:: :cyan:`Power mgt` +.. |P139_typename| replace:: :cyan:`Power mgt - AXP2101 Power management ESP32` +.. |P139_porttype| replace:: `.` +.. |P139_status| replace:: :yellow:`COLLECTION` :yellow:`DISPLAY` :yellow:`ENERGY` :yellow:`NEOPIXEL` +.. |P139_github| replace:: P139_AXP2101.ino +.. _P139_github: https://github.com/letscontrolit/ESPEasy/blob/mega/src/_P139_AXP2101.ino +.. |P139_usedby| replace:: `.` +.. |P139_shortinfo| replace:: `Power management controller` +.. |P139_maintainer| replace:: `tonhuisman` +.. |P139_compileinfo| replace:: `.` +.. |P139_usedlibraries| replace:: `Own AXP2101 library, loosely based on M5Stack Core2 code` diff --git a/docs/source/Reference/Command.rst b/docs/source/Reference/Command.rst index 6dd8a0cb38..b5980ed73a 100644 --- a/docs/source/Reference/Command.rst +++ b/docs/source/Reference/Command.rst @@ -763,6 +763,11 @@ P137 :ref:`P137_page` .. include:: ../Plugin/P137_commands.repl +P139 :ref:`P139_page` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. include:: ../Plugin/P139_commands.repl + P141 :ref:`P141_page` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/Reference/Events.rst b/docs/source/Reference/Events.rst index c49826b329..0de532e78d 100644 --- a/docs/source/Reference/Events.rst +++ b/docs/source/Reference/Events.rst @@ -550,6 +550,11 @@ P138 :ref:`P138_page` .. include:: ../Plugin/P138_events.repl +P139 :ref:`P139_page` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../Plugin/P139_events.repl + P143 :ref:`P143_page` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/lib/AXP2101/LICENSE b/lib/AXP2101/LICENSE new file mode 100644 index 0000000000..0e259d42c9 --- /dev/null +++ b/lib/AXP2101/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/lib/AXP2101/library.properties b/lib/AXP2101/library.properties new file mode 100644 index 0000000000..f20e161c9d --- /dev/null +++ b/lib/AXP2101/library.properties @@ -0,0 +1,11 @@ +name=AXP2101 Power management (I2C) +version=0.1.0 +author=M5Stack & Ton Huisman for ESPEasy +maintainer=Ton Huisman +sentence=This is a library for AXP2101, Power Management with I2C connectivity. Based on a M5Stack source, rewritten by tonhuisman. +paragraph=This is a library for AXP2101, Power Management with I2C connectivity. Based on a M5Stack source, rewritten by tonhuisman. +category=Device Control +url=https://github.com/tonhuisman/AXP2101 +architectures=* +includes=AXP2101.h +depends= diff --git a/lib/AXP2101/src/AXP2101.cpp b/lib/AXP2101/src/AXP2101.cpp new file mode 100644 index 0000000000..1246026860 --- /dev/null +++ b/lib/AXP2101/src/AXP2101.cpp @@ -0,0 +1,842 @@ +#include "AXP2101.h" + +#ifdef ESP32 + +// To check if we have implemented all cases of the enums +# pragma GCC diagnostic push +# pragma GCC diagnostic warning "-Wswitch-enum" + +bool AXP2101::begin(TwoWire *wire, + uint8_t addr, + AXP2101_device_model_e device) { + _wire = wire; + _addr = addr; + _device = device; + _wire->beginTransmission(_addr); + return 0 == _wire->endTransmission(); +} + +void AXP2101::setDevice(AXP2101_device_model_e device) { + _device = device; +} + +bool AXP2101::readRegister(uint8_t addr, + uint8_t reg, + uint8_t *result, + uint16_t length) { + uint8_t index = 0; + + _wire->beginTransmission(addr); + _wire->write(reg); + const uint8_t err = _wire->endTransmission(); + + _wire->requestFrom(addr, length); + + for (int i = 0; i < length; ++i) { + result[index++] = _wire->read(); + } + + return err == 0; +} + +uint8_t AXP2101::readRegister8(uint8_t addr, + uint8_t reg) { + _wire->beginTransmission(addr); + _wire->write(reg); + _wire->endTransmission(); + _wire->requestFrom(addr, 1); + return _wire->read(); +} + +bool AXP2101::writeRegister8(uint8_t addr, + uint8_t reg, + uint8_t data) { + _wire->beginTransmission(addr); + _wire->write(reg); + _wire->write(data); + return 0 == _wire->endTransmission(); +} + +bool AXP2101::bitOn(uint8_t addr, + uint8_t reg, + uint8_t data) { + const uint8_t temp = readRegister8(addr, reg); + const uint8_t write_back = (temp | data); + + return writeRegister8(addr, reg, write_back); +} + +bool AXP2101::bitOff(uint8_t addr, + uint8_t reg, + uint8_t data) { + const uint8_t temp = readRegister8(addr, reg); + const uint8_t write_back = (temp & (~data)); + + return writeRegister8(addr, reg, write_back); +} + +bool AXP2101::bitGet(uint8_t reg, + uint8_t data) { + const uint8_t temp = readRegister8(AXP2101_ADDR, reg); + + return (temp & data) == data; +} + +bool AXP2101::bitOnOff(bool sw, + uint8_t creg, + uint8_t mask) { + bool result = false; + + if (sw) { + result = bitOn(AXP2101_ADDR, creg, mask); + } else { + result = bitOff(AXP2101_ADDR, creg, mask); + } + + return result; +} + +/** + * Convert a voltage to the indicated register-data, using the matching offset and range(s) + */ +uint8_t AXP2101::voltageToRegister(uint16_t voltage, + AXP2101_registers_e reg) { + uint16_t min = 500; + uint16_t max = 0; + + switch (reg) { + case AXP2101_registers_e::dcdc2: + + if (0 == max) { max = 1540; } + case AXP2101_registers_e::dcdc3: + + if (0 == max) { max = 3400; } + + if (voltage <= min) { + return 0u; + } + else if (voltage > max) { + voltage = max; + } + else if ((voltage > 1540) && (voltage < 1600)) { + voltage = 1540u; + } + + if (voltage <= 1220) { + return (voltage - 500) / 10; + } + else if (voltage <= 1540) { + return (voltage - 1220) / 20 + (uint8_t)0b01000111; + } + return (voltage - 1600) / 100 + (uint8_t)0b01011000; + + case AXP2101_registers_e::dcdc4: + + if (voltage <= min) { + return 0; + } + else if (voltage > 1840) { + voltage = 1840u; + } + + if (voltage <= 1220) { + return (voltage - 500) / 10; + } + return (voltage - 1220) / 20 + (uint8_t)0b01000111; + + case AXP2101_registers_e::dcdc1: + + if (0 == max) { + min = 1500; + max = 3400; + } + case AXP2101_registers_e::dcdc5: + + if (0 == max) { + min = 1400; + max = 3700; + } + case AXP2101_registers_e::aldo1: + case AXP2101_registers_e::aldo2: + case AXP2101_registers_e::aldo3: + case AXP2101_registers_e::aldo4: + case AXP2101_registers_e::bldo1: + case AXP2101_registers_e::bldo2: + case AXP2101_registers_e::dldo1: + + if (0 == max) { max = 3400; } + case AXP2101_registers_e::dldo2: + case AXP2101_registers_e::cpuldos: + + if (0 == max) { max = 1400; } + + if (voltage <= min) { return 0u; } + + if (voltage > max) { voltage = max; } + + return (voltage - min) / 100; + case AXP2101_registers_e::chargeled: + case AXP2101_registers_e::batcharge: + case AXP2101_registers_e::charging: + case AXP2101_registers_e::batpresent: + case AXP2101_registers_e::chipid: + case AXP2101_registers_e::chargedet: + break; + + case AXP2101_registers_e::vbat: + case AXP2101_registers_e::battemp: + case AXP2101_registers_e::vbus: + case AXP2101_registers_e::vsys: + case AXP2101_registers_e::chiptemp: + break; + + } + return 0u; +} + +/** + * Convert read data from a register to a voltage for the indicated output + */ +uint16_t AXP2101::registerToVoltage(uint8_t data, + AXP2101_registers_e reg) { + uint16_t off = 0; + uint8_t mask = 0; + + switch (reg) { + case AXP2101_registers_e::dcdc2: + case AXP2101_registers_e::dcdc3: + data &= 0x7F; + + if (data < 0b01000111) { + return static_cast(data * 10) + 500; + } + else if (data < 0b01011000) { + return static_cast(data * 20) - 200; + } + return static_cast(data * 100) - 7200; + + case AXP2101_registers_e::dcdc4: + + if (data < 0b01000111) { + return static_cast(data * 10) + 500; + } + return static_cast(data * 20) - 200; + + case AXP2101_registers_e::dcdc1: + + if (0 == off) { off = 1500; } + case AXP2101_registers_e::dcdc5: + + if (0 == off) { off = 1400; } + case AXP2101_registers_e::aldo1: + case AXP2101_registers_e::aldo2: + case AXP2101_registers_e::aldo3: + case AXP2101_registers_e::aldo4: + case AXP2101_registers_e::bldo1: + case AXP2101_registers_e::bldo2: + case AXP2101_registers_e::dldo1: + case AXP2101_registers_e::dldo2: + case AXP2101_registers_e::cpuldos: + + if (0 == off) { off = 500; } + return off + (data * 100); + case AXP2101_registers_e::chargeled: + case AXP2101_registers_e::batcharge: + case AXP2101_registers_e::charging: + case AXP2101_registers_e::batpresent: + case AXP2101_registers_e::chipid: + case AXP2101_registers_e::chargedet: + break; + + case AXP2101_registers_e::vbat: + case AXP2101_registers_e::battemp: + case AXP2101_registers_e::vbus: + case AXP2101_registers_e::vsys: + case AXP2101_registers_e::chiptemp: + break; + } + return 0u; +} + +// Values in mVolt, raw ADC data is expressed in 0.5 mV +// LUT is based on 10k NTC with 50 uA current +constexpr uint16_t axp2101_TS_LUT[] { + 3150, // -20 + 2508, // -15 + 2013, // -10 + 1628, // -5 + 1325, // 0 + 1084, // 5 + 889, // 10 + 732, // 15 + 604, // 20 + 500, // 25 + 416, // 30 + 348, // 35 + 292, // 40 + 246, // 45 + 209, // 50 + 177, // 55 + 152}; // 60 + +uint16_t AXP2101::TS_tempToRegister(float temp_C) +{ + constexpr int NR_LUTS = sizeof(axp2101_TS_LUT) / sizeof(axp2101_TS_LUT[0]); + const int index_lo = (temp_C + 20) / 5; + const int index_hi = index_lo + 1; + if (index_lo < 0) return 0xFFFF; + if (index_hi >= NR_LUTS) return 0; + + const int mod5 = (static_cast(temp_C)) % 5; + const int offset = ((axp2101_TS_LUT[index_hi] - axp2101_TS_LUT[index_lo]) * mod5) / 5; + + // Need to apply a factor 2, to convert from mV to regvalue. + return 2* (axp2101_TS_LUT[index_lo] + offset); +} + +float AXP2101::TS_registerToTemp(uint16_t regValue) +{ + regValue /= 2; // Convert from regvalue to mV as used in LUT + constexpr int NR_LUTS = sizeof(axp2101_TS_LUT) / sizeof(axp2101_TS_LUT[0]); + if (regValue > axp2101_TS_LUT[0]) return -20.0f; + for (int index_hi = 1; index_hi < NR_LUTS; ++index_hi) { + if (regValue > axp2101_TS_LUT[index_hi]) { + const int index_lo = index_hi - 1; + const int step_lo = axp2101_TS_LUT[index_lo] - regValue; + const int step_hi = regValue - axp2101_TS_LUT[index_hi]; + float avg = axp2101_TS_LUT[index_hi] * step_hi + axp2101_TS_LUT[index_lo] * step_lo; + avg /= (step_hi + step_lo); + return avg; + } + } + + return 60.0f; +} + +/** + * Set a voltage to a port (output pin) of the AXP2101 + */ +bool AXP2101::setPortVoltage(uint16_t voltage, + AXP2101_registers_e reg) { + const uint8_t data = voltageToRegister(voltage, reg); + const uint8_t creg = static_cast(reg); + + return writeRegister8(AXP2101_ADDR, creg, data); +} + +/** + * Get the voltage of a port (output pin) of the AXP2101 + */ +uint16_t AXP2101::getPortVoltage(AXP2101_registers_e reg) { + const uint8_t creg = static_cast(reg); + const uint8_t data = readRegister8(AXP2101_ADDR, + creg); + + return registerToVoltage(data, + reg); +} + +/** + * Set the on/off state of a port (output pin) of the AXP2101 + */ +bool AXP2101::setPortState(bool sw, + AXP2101_registers_e reg) { + uint8_t ctrl = 0; + uint8_t mask = 0; + bool result = false; + + getControlRegisterMask(reg, ctrl, mask); + + if (ctrl) { + result = bitOnOff(sw, ctrl, mask); + } + return result; +} + +/** + * Get the on/off state of a port (output pin) of the AXP2101 + */ +bool AXP2101::getPortState(AXP2101_registers_e reg) { + uint8_t ctrl = 0; + uint8_t mask = 0; + bool result = false; + + getControlRegisterMask(reg, ctrl, mask); + + if (ctrl) { + result = bitGet(ctrl, mask); + } + return result; +} + +bool AXP2101::enableADC(AXP2101_registers_e reg, bool enable) +{ + uint8_t ctrl = 0; + uint8_t mask = 0; + getControlRegisterMask(reg, ctrl, mask); + + if (ctrl != AXP2101_ADC_ENABLE_REG) { + return false; + } + + uint8_t val = readRegister8(AXP2101_ADDR, AXP2101_ADC_ENABLE_REG); + + const bool bit_set = ((val & mask) != 0); + if (bit_set != enable) { + + if (enable) { + val |= mask; + } else { + val &= ~mask; + } + writeRegister8(AXP2101_ADDR, AXP2101_ADC_ENABLE_REG, val); + } + return true; +} + +uint16_t AXP2101::getADCVoltage(AXP2101_registers_e reg) +{ + if (!enableADC(reg, true)) return 0; + if (reg == AXP2101_registers_e::vbus && !isVbusIn()) { + return 0; + } + if (reg == AXP2101_registers_e::vbat && !isBatteryDetected()) { + return 0; + } + + const uint16_t mask = reg == AXP2101_registers_e::vbat ? 0x1F : 0x3F; + + const uint16_t hi = readRegister8(AXP2101_ADDR, static_cast(reg)); + const uint16_t lo = readRegister8(AXP2101_ADDR, static_cast(reg) + 1); + return ((hi & mask) << 8) | lo; +} + +/** + * Compound functions, device model dependent + */ + +// TODO Enable/disable these specific per device/models +void AXP2101::set_bus_3v3(uint16_t voltage) { + if (AXP2101_device_model_e::M5Stack_Core2_v1_1 == _device) { + if (!voltage) { + set_dcdc1_on_off(false); + set_dcdc3_on_off(false); + } else { + set_dcdc1_on_off(true); + set_dcdc3_on_off(true); + set_dcdc1_voltage(voltage); + set_dcdc3_voltage(voltage); + } + } // else... +} + +void AXP2101::set_lcd_back_light_voltage(uint16_t voltage) { + if (AXP2101_device_model_e::M5Stack_Core2_v1_1 == _device) { + if (!voltage) { + set_bldo1_on_off(false); + } else { + set_bldo1_on_off(true); + set_bldo1_voltage(voltage); + } + } // else... +} + +void AXP2101::set_bus_5v(uint8_t sw) { + if (sw) { + set_bldo2_on_off(true); + set_bldo2_voltage(3300); + } else { + set_bldo2_on_off(false); + } +} + +void AXP2101::set_spk(bool sw) { + if (AXP2101_device_model_e::M5Stack_Core2_v1_1 == _device) { + if (sw) { + set_aldo3_on_off(true); + set_aldo3_voltage(3300); + } else { + set_aldo3_on_off(false); + } + } // else... +} + +void AXP2101::set_lcd_rst(bool sw) { + if (AXP2101_device_model_e::M5Stack_Core2_v1_1 == _device) { + if (sw) { + set_aldo2_on_off(true); + set_aldo2_voltage(3300); + } else { + set_aldo2_on_off(false); + } + } // else... +} + +void AXP2101::set_lcd_and_tf_voltage(uint16_t voltage) { + if (AXP2101_device_model_e::M5Stack_Core2_v1_1 == _device) { + if (!voltage) { + set_aldo4_on_off(false); + } else { + set_aldo4_on_off(true); + set_aldo4_voltage(voltage); + } + } // else... +} + +void AXP2101::set_vib_motor_voltage(uint16_t voltage) { + if (AXP2101_device_model_e::M5Stack_Core2_v1_1 == _device) { + if (!voltage) { + set_dldo1_on_off(false); + } else { + set_dldo1_on_off(true); + set_dldo1_voltage(voltage); + } + } // else... +} + +/** + * Universal functions + */ +bool AXP2101::set_sys_led(bool sw) { + return bitOnOff(sw, AXP2101_CHGLED_REG, 0b00110000); +} + +bool AXP2101::setChargeLed(AXP2101_chargeled_d led) { + if (AXP2101_chargeled_d::Protected != led) { + const uint8_t temp = readRegister8(_addr, AXP2101_CHGLED_REG); + const uint8_t data = (static_cast(led) & 0x03) << 4; + const uint8_t write_back = ((temp & 0b11001111) | data); + + return writeRegister8(_addr, AXP2101_CHGLED_REG, write_back); + } + return false; +} + +AXP2101_chargeled_d AXP2101::getChargeLed() { + return static_cast((readRegister8(_addr, AXP2101_CHGLED_REG) >> 4) & 0x07); +} + +bool AXP2101::getTS_disabled() { + return bitGet(AXP2101_TS_PIN_CTRL_REG, 0b00010000); +} + +void AXP2101::setTS_disabled(bool val) { + bitOnOff(val, AXP2101_TS_PIN_CTRL_REG, 0b00010000); +} + +// Reg 61: Iprechg Charger settings +uint16_t AXP2101::getPreChargeCurrentLimit() { + // AXP2101_IPRECHG_REG + // bit 3:0 + uint8_t reg = readRegister8(_addr,AXP2101_IPRECHG_REG); + return (reg & 0b1111) * 25; +} +void AXP2101::setPreChargeCurrentLimit(uint16_t current_mA) { + if (current_mA > 200) { + current_mA = 200; + } + writeRegister8(_addr, AXP2101_IPRECHG_REG, current_mA / 25); +} + +// Reg 62: ICC Charger settings +uint16_t AXP2101::getConstChargeCurrentLimit() { + // AXP2101_ICC_CHARGER_SETTING_REG + // bit 4:0 + uint8_t reg = readRegister8(_addr, AXP2101_ICC_CHARGER_SETTING_REG); + reg &= 0b11111; + if (reg <= 8) { + return reg * 25; + } + return (reg - 8) * 100 + 200; +} +void AXP2101::setConstChargeCurrentLimit(uint16_t current_mA) { + if (current_mA > 1000) { + current_mA = 1000; + } + + const uint8_t reg = (current_mA <= 200) + ? current_mA / 25 + : ((current_mA - 200) / 100) + 8; + writeRegister8(_addr, AXP2101_ICC_CHARGER_SETTING_REG, reg); +} + +// Reg 63: Iterm Charger settings and Control +// Enable/Disable via chargeStates.term_cur_lim_en +uint16_t AXP2101::getTerminationChargeCurrentLimit() { + // AXP2101_CHARGER_SETTING_REG + // bit 4: enable/disable + // bit 3:0 + uint8_t reg = readRegister8(_addr,AXP2101_CHARGER_SETTING_REG); + return (reg & 0b1111) * 25; +} + +void AXP2101::setTerminationChargeCurrentLimit(uint16_t current_mA) { + constexpr uint8_t enable_mask = 0b00010000; + const bool enabled = bitGet(AXP2101_CHARGER_SETTING_REG, enable_mask); + setTerminationChargeCurrentLimit(current_mA, enabled); +} + +void AXP2101::setTerminationChargeCurrentLimit(uint16_t current_mA, bool enable) { + if (current_mA > 200) { + current_mA = 200; + } + uint8_t reg = current_mA / 25; + if (enable) { + constexpr uint8_t enable_mask = 0b00010000; + reg &= enable_mask; + } + writeRegister8(_addr, AXP2101_CHARGER_SETTING_REG, reg); +} + + +// Reg 64: CV Charger Voltage settings +AXP2101_CV_charger_voltage_e AXP2101::getCV_chargeVoltage() { + // AXP2101_CV_CHARGER_SETTING_REG + // bit 2:0 + uint8_t reg = readRegister8(_addr,AXP2101_CV_CHARGER_SETTING_REG); + reg &= 0b111; + return static_cast(reg); +} +void AXP2101::setCV_chargeVoltage(AXP2101_CV_charger_voltage_e voltage_mV) { + uint8_t reg = static_cast(voltage_mV); + if (reg > static_cast(AXP2101_CV_charger_voltage_e::limit_4_40V)) { + // Set to a default safe limit + reg = static_cast(AXP2101_CV_charger_voltage_e::limit_4_20V); + } + writeRegister8(_addr, AXP2101_CV_CHARGER_SETTING_REG, reg); +} + +// Reg 14: Minimum System Voltage Control +AXP2101_Linear_Charger_Vsys_dpm_e AXP2101::getLinear_Charger_Vsys_dpm() { + // AXP2101_MIN_VSYS_REG + // bit 6:4 + uint8_t reg = readRegister8(_addr, AXP2101_MIN_VSYS_REG); + reg &= 0b01110000; + reg >>= 4; + return static_cast(reg); +} +void AXP2101::setLinear_Charger_Vsys_dpm(AXP2101_Linear_Charger_Vsys_dpm_e voltage) { + uint8_t reg = static_cast(voltage); + reg <<= 4; + writeRegister8(_addr, AXP2101_MIN_VSYS_REG, reg); +} + +// Reg 15: Input Voltage Limit +AXP2101_VINDPM_e AXP2101::getVin_DPM() { + // AXP2101_VIN_DPM_REG + // bit 3:0 + uint8_t reg = readRegister8(_addr, AXP2101_VIN_DPM_REG); + reg &= 0b00001111; + return static_cast(reg); +} +void AXP2101::setVin_DPM(AXP2101_VINDPM_e voltage) { + uint8_t reg = static_cast(voltage); + reg &= 0b00001111; + writeRegister8(_addr, AXP2101_VIN_DPM_REG, reg); +} + +// Reg 16: Input Current Limit +AXP2101_InputCurrentLimit_e AXP2101::getInputCurrentLimit() { + // AXP2101_IN_CURRENT_LIMIT_REG + // bit 2:0 + uint8_t reg = readRegister8(_addr, AXP2101_IN_CURRENT_LIMIT_REG); + reg &= 0b00000111; + return static_cast(reg); +} + +void AXP2101::setInputCurrentLimit(AXP2101_InputCurrentLimit_e current) { + uint8_t reg = static_cast(current); + reg &= 0b00000111; + writeRegister8(_addr, AXP2101_IN_CURRENT_LIMIT_REG, reg); +} + +uint8_t AXP2101::getBatCharge() { + return readRegister8(_addr, AXP2101_BAT_CHARGE_REG); +} + +AXP2101_chargingState_e AXP2101::getChargingState() { + const uint8_t level = (readRegister8(_addr, AXP2101_COM_STAT1_REG) >> 5) & 0x03; + + return static_cast(0x01 == level ? 1 : (0x02 == level ? -1 : 0)); +} + +bool AXP2101::isBatteryDetected() { + return (readRegister8(_addr, AXP2101_COM_STAT0_REG) >> 3) & 0x01; +} + +bool AXP2101::isVbusGood() { + return bitGet(AXP2101_COM_STAT0_REG, (1 << 5)); +} + + +bool AXP2101::isVbusIn() { + return !bitGet(AXP2101_COM_STAT1_REG, (1 << 3)) && isVbusGood(); +} + +AXP2101_chargingDetail_e AXP2101::getChargingDetail() { + return static_cast(readRegister8(_addr, AXP2101_COM_STAT1_REG) & 0x07); +} + +uint8_t AXP2101::getChipIDRaw() { + return readRegister8(_addr, AXP2101_CHIP_ID_REG); +} + +AXP2101_chipid_e AXP2101::getChipID() { + return static_cast(getChipIDRaw()); +} + +bool AXP2101::set_charger_term_current_to_zero(void) { + return bitOff(AXP2101_ADDR, AXP2101_CHARGER_SETTING_REG, 0b00001111); +} + +bool AXP2101::setConstChargeCurrentLimit_to_50mA(void) { + return writeRegister8(AXP2101_ADDR, AXP2101_ICC_CHARGER_SETTING_REG, 2); +} + +void AXP2101::set_bat_charge(bool enable) { + uint8_t val = 0; + + if (readRegister(AXP2101_ADDR, AXP2101_CHARG_FGAUG_WDOG_REG, &val, 1)) { + writeRegister8(AXP2101_ADDR, AXP2101_CHARG_FGAUG_WDOG_REG, (val & 0xFD) + (enable << 1)); + } +} + +bool AXP2101::enable_pwrok_resets(void) { + return bitOn(AXP2101_ADDR, + AXP2101_PMU_CONFIG_REG, + 1 << 3); +} + +void AXP2101::set_IRQ_enable_0(uint8_t val) { + // Clear any IRQ flags + writeRegister8(AXP2101_ADDR, AXP2101_IRQ_STATUS_0_REG, 0); + writeRegister8(AXP2101_ADDR, AXP2101_IRQ_STATUS_1_REG, 0); + writeRegister8(AXP2101_ADDR, AXP2101_IRQ_STATUS_2_REG, 0); + writeRegister8(AXP2101_ADDR, AXP2101_IRQ_EN_0_REG, val); +} + +void AXP2101::power_off(void) { + // 1. AXP2101 Power off + bitOn(AXP2101_ADDR, AXP2101_IRQ_EN_1_REG, 1 << 1); // POWERON Negative Edge IRQ(ponne_irq_en) enable + writeRegister8(AXP2101_ADDR, AXP2101_PWROK_PWROFF_REG, 0b00011011); // sleep and wait for wakeup + delay(100); + writeRegister8(AXP2101_ADDR, AXP2101_PMU_CONFIG_REG, 0b00110001); // power off +} + +uint8_t AXP2101::get_dcdc_status(void) { + return readRegister8(_addr, + AXP2101_DCDC_CTRL_REG); +} + +void AXP2101::getControlRegisterMask(AXP2101_registers_e reg, + uint8_t & ctrl, + uint8_t & mask) { + switch (reg) { + case AXP2101_registers_e::dcdc1: + ctrl = AXP2101_DCDC_CTRL_REG; + mask = AXP2101_DCDC1_CTRL_MASK; + break; + case AXP2101_registers_e::dcdc2: + ctrl = AXP2101_DCDC_CTRL_REG; + mask = AXP2101_DCDC2_CTRL_MASK; + break; + case AXP2101_registers_e::dcdc3: + ctrl = AXP2101_DCDC_CTRL_REG; + mask = AXP2101_DCDC3_CTRL_MASK; + break; + case AXP2101_registers_e::dcdc4: + ctrl = AXP2101_DCDC_CTRL_REG; + mask = AXP2101_DCDC4_CTRL_MASK; + break; + case AXP2101_registers_e::dcdc5: + ctrl = AXP2101_DCDC_CTRL_REG; + mask = AXP2101_DCDC5_CTRL_MASK; + break; + case AXP2101_registers_e::aldo1: + ctrl = AXP2101_LDO_CTRL_REG; + mask = AXP2101_ALDO1_CTRL_MASK; + break; + case AXP2101_registers_e::aldo2: + ctrl = AXP2101_LDO_CTRL_REG; + mask = AXP2101_ALDO2_CTRL_MASK; + break; + case AXP2101_registers_e::aldo3: + ctrl = AXP2101_LDO_CTRL_REG; + mask = AXP2101_ALDO3_CTRL_MASK; + break; + case AXP2101_registers_e::aldo4: + ctrl = AXP2101_LDO_CTRL_REG; + mask = AXP2101_ALDO4_CTRL_MASK; + break; + case AXP2101_registers_e::bldo1: + ctrl = AXP2101_LDO_CTRL_REG; + mask = AXP2101_BLDO1_CTRL_MASK; + break; + case AXP2101_registers_e::bldo2: + ctrl = AXP2101_LDO_CTRL_REG; + mask = AXP2101_BLDO2_CTRL_MASK; + break; + case AXP2101_registers_e::dldo1: + ctrl = AXP2101_LDO_CTRL_REG; + mask = AXP2101_DLDO1_CTRL_MASK; + break; + case AXP2101_registers_e::dldo2: + ctrl = AXP2101_LDO_CTRL_REG1; + mask = AXP2101_DLDO2_CTRL_MASK; + break; + case AXP2101_registers_e::cpuldos: + ctrl = AXP2101_LDO_CTRL_REG; + mask = AXP2101_CPUSLDO_CTRL_MASK; + break; + case AXP2101_registers_e::chargeled: + ctrl = AXP2101_CHGLED_REG; + mask = AXP2101_CHGLED_CTRL_MASK; + break; + case AXP2101_registers_e::batcharge: + ctrl = AXP2101_BAT_CHARGE_REG; + mask = 0xFF; + break; + case AXP2101_registers_e::charging: + ctrl = AXP2101_COM_STAT1_REG; + mask = 0b01100000; + break; + case AXP2101_registers_e::batpresent: + ctrl = AXP2101_COM_STAT0_REG; + mask = 0b00001000; + break; + case AXP2101_registers_e::chipid: + ctrl = AXP2101_CHIP_ID_REG; + mask = 0b11111111; + break; + case AXP2101_registers_e::chargedet: + ctrl = AXP2101_COM_STAT1_REG; + mask = 0b00000111; + break; + + + case AXP2101_registers_e::vbat: + ctrl = AXP2101_ADC_ENABLE_REG; + mask = AXP2101_VBAT_CTRL_MASK; + break; + case AXP2101_registers_e::battemp: + ctrl = AXP2101_ADC_ENABLE_REG; + mask = AXP2101_BATTEMP_CTRL_MASK; + break; + case AXP2101_registers_e::vbus: + ctrl = AXP2101_ADC_ENABLE_REG; + mask = AXP2101_VBUS_CTRL_MASK; + break; + case AXP2101_registers_e::vsys: + ctrl = AXP2101_ADC_ENABLE_REG; + mask = AXP2101_VSYS_CTRL_MASK; + break; + case AXP2101_registers_e::chiptemp: + ctrl = AXP2101_ADC_ENABLE_REG; + mask = AXP2101_TDIE_CTRL_MASK; + break; + } +} + +# pragma GCC diagnostic pop + +#endif // ifdef ESP32 diff --git a/lib/AXP2101/src/AXP2101.h b/lib/AXP2101/src/AXP2101.h new file mode 100644 index 0000000000..7ef6151a27 --- /dev/null +++ b/lib/AXP2101/src/AXP2101.h @@ -0,0 +1,388 @@ +#ifndef __AXP2101_H +#define __AXP2101_H + +/** + * AXP2101 library adjusted for ESPEasy + * 2024-02-04 tonhuisman: Start. + * + * Based on the AXP2101 driver included in https://github.com/m5stack/M5Core2 + */ + +/** Changelog: + * 2024-02-21 tonhuisman: Add support for ChipId and ChargingDetail state + * 2024-02-18 tonhuisman: Add support for ChargingState, isBatteryDetected + * 2024-02-17 tonhuisman: Add support for Charge-led and battery charge level, limit to ESP32, as this chip is only available + * on ESP32 based units + * 2024-02-16 tonhuisman: Initial 'release' with AXP2101 plugin for ESPEasy, implementing all output pins + * Including predefined settings for M5Stack Core2 v1.1, M5Stack CoreS3, LilyGO_TBeam_v1_2, + * LilyGO_TBeamS3_v3, LilyGO_TPCie_v1_2. + * 2024-02-04 tonhuisman: Start development of the library + */ + +#include +#include +#include "AXP2101_settings.h" + +class AXP2101 { +private: + + uint8_t _addr; + TwoWire *_wire; + AXP2101_device_model_e _device = AXP2101_device_model_e::Unselected; + +public: + + AXP2101() {} + + ~AXP2101() {} + + bool begin(TwoWire *wire = & Wire, + uint8_t addr = AXP2101_ADDR, + AXP2101_device_model_e device = AXP2101_device_model_e::Unselected); + + void setDevice(AXP2101_device_model_e device); + +private: + + bool readRegister(uint8_t addr, + uint8_t reg, + uint8_t *result, + uint16_t length); + uint8_t readRegister8(uint8_t addr, + uint8_t reg); + bool writeRegister8(uint8_t addr, + uint8_t reg, + uint8_t data); + bool bitOn(uint8_t addr, + uint8_t reg, + uint8_t data); + bool bitOff(uint8_t addr, + uint8_t reg, + uint8_t data); + bool bitOnOff(bool sw, + uint8_t creg, + uint8_t mask); + bool bitGet(uint8_t reg, + uint8_t data); + void getControlRegisterMask(AXP2101_registers_e reg, + uint8_t & ctrl, + uint8_t & mask); + +public: + + // Utility + uint8_t voltageToRegister(uint16_t voltage, + AXP2101_registers_e reg); + uint16_t registerToVoltage(uint8_t data, + AXP2101_registers_e reg); + + // Convertion between NTC temperature sensor raw value and temperature + uint16_t TS_tempToRegister(float temp_C); + float TS_registerToTemp(uint16_t regValue); + + uint8_t get_dcdc_status(void); + bool setPortVoltage(uint16_t voltage, + AXP2101_registers_e reg); + uint16_t getPortVoltage(AXP2101_registers_e reg); + bool setPortState(bool sw, + AXP2101_registers_e reg); + bool getPortState(AXP2101_registers_e reg); + + bool enableADC(AXP2101_registers_e reg, bool enable); + uint16_t getADCVoltage(AXP2101_registers_e reg); + + bool setChargeLed(AXP2101_chargeled_d led); + AXP2101_chargeled_d getChargeLed(); + + bool getTS_disabled(); + void setTS_disabled(bool val); + + // Reg 61: Iprechg Charger Settings + uint16_t getPreChargeCurrentLimit() ; + void setPreChargeCurrentLimit(uint16_t current_mA); + + // Reg 62: ICC Charger Settings + uint16_t getConstChargeCurrentLimit() ; + void setConstChargeCurrentLimit(uint16_t current_mA); + + // Reg 63: Iterm Charger Settings and Control + // Enable/Disable via chargeStates.term_cur_lim_en + uint16_t getTerminationChargeCurrentLimit() ; + void setTerminationChargeCurrentLimit(uint16_t current_mA); + void setTerminationChargeCurrentLimit(uint16_t current_mA, bool enable); + + // Reg 64: CV Charger Voltage Settings + AXP2101_CV_charger_voltage_e getCV_chargeVoltage() ; + void setCV_chargeVoltage(AXP2101_CV_charger_voltage_e voltage_mV); + + // Reg 14: Minimum System Voltage Control + AXP2101_Linear_Charger_Vsys_dpm_e getLinear_Charger_Vsys_dpm() ; + void setLinear_Charger_Vsys_dpm(AXP2101_Linear_Charger_Vsys_dpm_e voltage); + + // Reg 15: Input Voltage Limit + AXP2101_VINDPM_e getVin_DPM() ; + void setVin_DPM(AXP2101_VINDPM_e voltage); + + // Reg 16: Input Current Limit + AXP2101_InputCurrentLimit_e getInputCurrentLimit() ; + void setInputCurrentLimit(AXP2101_InputCurrentLimit_e current); + + + uint8_t getBatCharge(); + AXP2101_chargingState_e getChargingState(); + bool isBatteryDetected(); + bool isVbusGood(); + bool isVbusIn(); + AXP2101_chargingDetail_e getChargingDetail(); + uint8_t getChipIDRaw(); + AXP2101_chipid_e getChipID(); + + // Device common functions + void set_bus_3v3(uint16_t voltage); + void set_lcd_back_light_voltage(uint16_t voltage); + void set_bus_5v(uint8_t sw); + bool set_sys_led(bool sw); + void set_spk(bool sw); + void set_lcd_rst(bool sw); + void set_lcd_and_tf_voltage(uint16_t voltage); + void set_vib_motor_voltage(uint16_t voltage); + void set_bat_charge(bool enable); + void power_off(void); + bool set_charger_term_current_to_zero(void); + bool setConstChargeCurrentLimit_to_50mA(void); + bool enable_pwrok_resets(void); + + void set_IRQ_enable_0(uint8_t val); + + + // Low-level output functions + bool set_dcdc1_voltage(uint16_t voltage) { // 1.5 - 3.4V 100mV/step, 20 steps + return setPortVoltage(voltage, AXP2101_registers_e::dcdc1); + } + + uint16_t get_dcdc1_voltage(void) { + return getPortVoltage(AXP2101_registers_e::dcdc1); + } + + bool set_dcdc2_voltage(uint16_t voltage) { // 0.5 - 1.2V 10mV/step, 71 steps, + // 1.22 - 1.54V 20mV/step, 17 steps, + return setPortVoltage(voltage, AXP2101_registers_e::dcdc2); + } + + uint16_t get_dcdc2_voltage(void) { + return getPortVoltage(AXP2101_registers_e::dcdc2); + } + + bool set_dcdc3_voltage(uint16_t voltage) { // 0.5 - 1.2V 10mV/step, 71 steps, + // 1.22 - 1.54V 20mV/step, 17 steps, + // 1.6 - 3.4V 100mV/step, 19 steps + return setPortVoltage(voltage, AXP2101_registers_e::dcdc3); + } + + uint16_t get_dcdc3_voltage(void) { + return getPortVoltage(AXP2101_registers_e::dcdc3); + } + + bool set_dcdc4_voltage(uint16_t voltage) { // 0.5 - 1.2V 10mV/step, 71 steps, + // 1.22 - 1.84V 20mV/step, 32 steps + return setPortVoltage(voltage, AXP2101_registers_e::dcdc4); + } + + uint16_t get_dcdc4_voltage(void) { + return getPortVoltage(AXP2101_registers_e::dcdc4); + } + + bool set_dcdc5_voltage(uint16_t voltage) { // 1.4 - 3.7V 100mV/step, 24 steps + return setPortVoltage(voltage, AXP2101_registers_e::dcdc5); + } + + uint16_t get_dcdc5_voltage(void) { + return getPortVoltage(AXP2101_registers_e::dcdc5); + } + + bool set_aldo1_voltage(uint16_t voltage) { // 0.5 - 3.5V 100mV/step, 31 steps + return setPortVoltage(voltage, AXP2101_registers_e::aldo1); + } + + uint16_t get_aldo1_voltage(void) { + return getPortVoltage(AXP2101_registers_e::aldo1); + } + + bool set_aldo2_voltage(uint16_t voltage) { // 0.5 - 3.5V 100mV/step, 31 steps + return setPortVoltage(voltage, AXP2101_registers_e::aldo2); + } + + uint16_t get_aldo2_voltage(void) { + return getPortVoltage(AXP2101_registers_e::aldo2); + } + + bool set_aldo3_voltage(uint16_t voltage) { // 0.5 - 3.5V 100mV/step, 31 steps + return setPortVoltage(voltage, AXP2101_registers_e::aldo3); + } + + uint16_t get_aldo3_voltage(void) { + return getPortVoltage(AXP2101_registers_e::aldo3); + } + + bool set_aldo4_voltage(uint16_t voltage) { // 0.5 - 3.5V 100mV/step, 31 steps + return setPortVoltage(voltage, AXP2101_registers_e::aldo4); + } + + uint16_t get_aldo4_voltage(void) { + return getPortVoltage(AXP2101_registers_e::aldo4); + } + + bool set_bldo1_voltage(uint16_t voltage) { // 0.5 - 3.5V 100mV/step, 31 steps + return setPortVoltage(voltage, AXP2101_registers_e::bldo1); + } + + uint16_t get_bldo1_voltage(void) { + return getPortVoltage(AXP2101_registers_e::bldo1); + } + + bool set_bldo2_voltage(uint16_t voltage) { // 0.5 - 3.5V 100mV/step, 31 steps + return setPortVoltage(voltage, AXP2101_registers_e::bldo2); + } + + uint16_t get_bldo2_voltage(void) { + return getPortVoltage(AXP2101_registers_e::bldo2); + } + + bool set_dldo1_voltage(uint16_t voltage) { // 0.5 - 3.5V 100mV/step, 31 steps + return setPortVoltage(voltage, AXP2101_registers_e::dldo1); + } + + uint16_t get_dldo1_voltage(void) { + return getPortVoltage(AXP2101_registers_e::dldo1); + } + + bool set_dldo2_voltage(uint16_t voltage) { // 0.5 - 1.4V 50mV/step, 20 steps + return setPortVoltage(voltage, AXP2101_registers_e::dldo2); + } + + uint16_t get_dldo2_voltage(void) { + return getPortVoltage(AXP2101_registers_e::dldo2); + } + + bool set_cpuldos_voltage(uint16_t voltage) { // 0.5 - 1.4V 50mV/step, 20 steps + return setPortVoltage(voltage, AXP2101_registers_e::cpuldos); + } + + uint16_t get_cpuldos_voltage(void) { + return getPortVoltage(AXP2101_registers_e::cpuldos); + } + + bool set_dcdc1_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::dcdc1); + } + + bool set_dcdc2_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::dcdc2); + } + + bool set_dcdc3_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::dcdc3); + } + + bool set_dcdc4_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::dcdc4); + } + + bool set_dcdc5_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::dcdc5); + } + + bool set_aldo1_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::aldo1); + } + + bool set_aldo2_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::aldo2); + } + + bool set_aldo3_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::aldo3); + } + + bool set_aldo4_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::aldo4); + } + + bool set_bldo1_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::bldo1); + } + + bool set_bldo2_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::bldo2); + } + + bool set_dldo1_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::dldo1); + } + + bool set_dldo2_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::dldo2); + } + + bool set_cpuldos_on_off(bool sw) { + return setPortState(sw, AXP2101_registers_e::cpuldos); + } + + bool get_dcdc1_on_off() { + return getPortState(AXP2101_registers_e::dcdc1); + } + + bool get_dcdc2_on_off() { + return getPortState(AXP2101_registers_e::dcdc2); + } + + bool get_dcdc3_on_off() { + return getPortState(AXP2101_registers_e::dcdc3); + } + + bool get_dcdc4_on_off() { + return getPortState(AXP2101_registers_e::dcdc4); + } + + bool get_dcdc5_on_off() { + return getPortState(AXP2101_registers_e::dcdc5); + } + + bool get_aldo1_on_off() { + return getPortState(AXP2101_registers_e::aldo1); + } + + bool get_aldo2_on_off() { + return getPortState(AXP2101_registers_e::aldo2); + } + + bool get_aldo3_on_off() { + return getPortState(AXP2101_registers_e::aldo3); + } + + bool get_aldo4_on_off() { + return getPortState(AXP2101_registers_e::aldo4); + } + + bool get_bldo1_on_off() { + return getPortState(AXP2101_registers_e::bldo1); + } + + bool get_bldo2_on_off() { + return getPortState(AXP2101_registers_e::bldo2); + } + + bool get_dldo1_on_off() { + return getPortState(AXP2101_registers_e::dldo1); + } + + bool get_dldo2_on_off() { + return getPortState(AXP2101_registers_e::dldo2); + } + + bool get_cpuldos_on_off() { + return getPortState(AXP2101_registers_e::cpuldos); + } +}; + +#endif // ifndef __AXP2101_H diff --git a/lib/AXP2101/src/AXP2101_settings.cpp b/lib/AXP2101/src/AXP2101_settings.cpp new file mode 100644 index 0000000000..c44ae79cd9 --- /dev/null +++ b/lib/AXP2101/src/AXP2101_settings.cpp @@ -0,0 +1,536 @@ +#include "AXP2101_settings.h" + +#ifdef ESP32 + +// To check if we have implemented all cases of the enums +# pragma GCC diagnostic push +# pragma GCC diagnostic warning "-Wswitch-enum" + +/** + * Utility functions + */ +const __FlashStringHelper* toString(AXP2101_device_model_e device, + bool displayString) { + switch (device) { + case AXP2101_device_model_e::Unselected: return displayString ? F("Select an option to set default values") : F("Unselected"); + case AXP2101_device_model_e::M5Stack_Core2_v1_1: return displayString ? F("M5Stack Core2 v1.1") : F("M5Core2v11"); + case AXP2101_device_model_e::M5Stack_CoreS3: return displayString ? F("M5Stack CoreS3") : F("M5CoreS3"); + case AXP2101_device_model_e::LilyGO_TBeam_v1_2: return displayString ? F("LilyGo TBeam v1.2") : F("TBeamv12"); + case AXP2101_device_model_e::LilyGO_TBeamS3_v3: return displayString ? F("LilyGo TBeam S3 v3") : F("TBeamS3v3"); + case AXP2101_device_model_e::LilyGO_TPCie_v1_2: return displayString ? F("LilyGo TPCie v1.2") : F("TPCiev12"); + case AXP2101_device_model_e::UserDefined: return displayString ? F("User defined") : F("Userdefined"); + case AXP2101_device_model_e::MAX: break; + } + return F(""); +} + +const __FlashStringHelper* toString(AXP2101_registers_e reg, + bool displayString) { + switch (reg) { + case AXP2101_registers_e::dcdc1: return displayString ? F("DCDC1") : F("dcdc1"); + case AXP2101_registers_e::dcdc2: return displayString ? F("DCDC2") : F("dcdc2"); + case AXP2101_registers_e::dcdc3: return displayString ? F("DCDC3") : F("dcdc3"); + case AXP2101_registers_e::dcdc4: return displayString ? F("DCDC4") : F("dcdc4"); + case AXP2101_registers_e::dcdc5: return displayString ? F("DCDC5") : F("dcdc5"); + case AXP2101_registers_e::aldo1: return displayString ? F("ALDO1") : F("aldo1"); + case AXP2101_registers_e::aldo2: return displayString ? F("ALDO2") : F("aldo2"); + case AXP2101_registers_e::aldo3: return displayString ? F("ALDO3") : F("aldo3"); + case AXP2101_registers_e::aldo4: return displayString ? F("ALDO4") : F("aldo4"); + case AXP2101_registers_e::bldo1: return displayString ? F("BLDO1") : F("bldo1"); + case AXP2101_registers_e::bldo2: return displayString ? F("BLDO2") : F("bldo2"); + case AXP2101_registers_e::dldo1: return displayString ? F("DLDO1") : F("dldo1"); + case AXP2101_registers_e::dldo2: return displayString ? F("DLDO2") : F("dldo2"); + case AXP2101_registers_e::cpuldos: return displayString ? F("CPULDOS") : F("cpuldos"); + case AXP2101_registers_e::chargeled: return displayString ? F("ChargeLed") : F("chargeled"); + case AXP2101_registers_e::batcharge: return displayString ? F("BatCharge") : F("batcharge"); + case AXP2101_registers_e::charging: return displayString ? F("ChargingState") : F("chargingstate"); + case AXP2101_registers_e::batpresent: return displayString ? F("BatPresent") : F("batpresent"); + case AXP2101_registers_e::chipid: return displayString ? F("ChipID") : F("chipid"); + case AXP2101_registers_e::chargedet: return displayString ? F("ChargingDetail") : F("chargingdet"); + + case AXP2101_registers_e::vbat: return displayString ? F("BatVoltage") : F("vbat"); + case AXP2101_registers_e::battemp: return displayString ? F("BatTemp") : F("battemp"); + case AXP2101_registers_e::vbus: return displayString ? F("BusVoltage") : F("vbus"); + case AXP2101_registers_e::vsys: return displayString ? F("SysVoltage") : F("vsys"); + case AXP2101_registers_e::chiptemp: return displayString ? F("ChipTemp") : F("chiptemp"); + } + return F(""); +} + +const __FlashStringHelper* toString(AXP_pin_s pin) { + switch (pin) { + case AXP_pin_s::Off: return F("Off"); + case AXP_pin_s::On: return F("On"); + case AXP_pin_s::Default: return F("Default"); + case AXP_pin_s::Disabled: return F("Disabled"); + case AXP_pin_s::Protected: return F("Protected"); + } + return F(""); +} + +const __FlashStringHelper* toString(AXP2101_chargeled_d led) { + switch (led) { + case AXP2101_chargeled_d::Off: return F("Off"); + case AXP2101_chargeled_d::Flash_1Hz: return F("Flash 1Hz"); + case AXP2101_chargeled_d::Flash_4Hz: return F("Flash 4Hz"); + case AXP2101_chargeled_d::Steady_On: return F("Steady On"); + case AXP2101_chargeled_d::Protected: return F("Protected"); + } + return F(""); +} + +const __FlashStringHelper* toString(AXP2101_chargingState_e state) { + switch (state) { + case AXP2101_chargingState_e::Discharging: return F("Discharging"); + case AXP2101_chargingState_e::Standby: return F("Standby"); + case AXP2101_chargingState_e::Charging: return F("Charging"); + } + return F(""); +} + +const __FlashStringHelper* toString(AXP2101_chipid_e chip) { + switch (chip) { + case AXP2101_chipid_e::axp2101: return F("AXP2101"); + } + return F(""); +} + +const __FlashStringHelper* toString(AXP2101_chargingDetail_e charge) { + switch (charge) { + case AXP2101_chargingDetail_e::tricharge: return F("tri-charge"); + case AXP2101_chargingDetail_e::precharge: return F("pre-charge"); + case AXP2101_chargingDetail_e::constcharge: return F("constant charge (CC)"); + case AXP2101_chargingDetail_e::constvoltage: return F("constant voltage (CV)"); + case AXP2101_chargingDetail_e::done: return F("charge done"); + case AXP2101_chargingDetail_e::notcharging: return F("not charging"); + } + return F(""); +} + +AXP2101_registers_e AXP2101_intToRegister(int reg) { + switch (reg) { + case 0: return AXP2101_registers_e::dcdc1; + case 1: return AXP2101_registers_e::dcdc2; + case 2: return AXP2101_registers_e::dcdc3; + case 3: return AXP2101_registers_e::dcdc4; + case 4: return AXP2101_registers_e::dcdc5; + case 5: return AXP2101_registers_e::aldo1; + case 6: return AXP2101_registers_e::aldo2; + case 7: return AXP2101_registers_e::aldo3; + case 8: return AXP2101_registers_e::aldo4; + case 9: return AXP2101_registers_e::bldo1; + case 10: return AXP2101_registers_e::bldo2; + case 11: return AXP2101_registers_e::dldo1; + case 12: return AXP2101_registers_e::dldo2; + case 13: return AXP2101_registers_e::cpuldos; + case 14: return AXP2101_registers_e::chargeled; + case 15: return AXP2101_registers_e::batcharge; + case 16: return AXP2101_registers_e::charging; + case 17: return AXP2101_registers_e::batpresent; + case 18: return AXP2101_registers_e::chipid; + case 19: return AXP2101_registers_e::chargedet; + + case 20: return AXP2101_registers_e::vbat; + case 21: return AXP2101_registers_e::battemp; + case 22: return AXP2101_registers_e::vbus; + case 23: return AXP2101_registers_e::vsys; + case 24: return AXP2101_registers_e::chiptemp; + } + return AXP2101_registers_e::dcdc1; // we shouldn't get here, just defaulting to the first value +} + +uint16_t AXP2101_minVoltage(AXP2101_registers_e reg) { + switch (reg) { + case AXP2101_registers_e::dcdc1: return AXP2101_DCDC1_MIN; + case AXP2101_registers_e::dcdc5: return AXP2101_DCDC5_MIN; + case AXP2101_registers_e::dcdc2: + case AXP2101_registers_e::dcdc3: + case AXP2101_registers_e::dcdc4: + case AXP2101_registers_e::aldo1: + case AXP2101_registers_e::aldo2: + case AXP2101_registers_e::aldo3: + case AXP2101_registers_e::aldo4: + case AXP2101_registers_e::bldo1: + case AXP2101_registers_e::bldo2: + case AXP2101_registers_e::dldo1: + case AXP2101_registers_e::dldo2: + case AXP2101_registers_e::cpuldos: return AXP2101_CPUSLDO_MIN; + + // not a voltage register + case AXP2101_registers_e::chargeled: + case AXP2101_registers_e::batcharge: + case AXP2101_registers_e::charging: + case AXP2101_registers_e::batpresent: + case AXP2101_registers_e::chipid: + case AXP2101_registers_e::chargedet: + + case AXP2101_registers_e::vbat: + case AXP2101_registers_e::battemp: + case AXP2101_registers_e::vbus: + case AXP2101_registers_e::vsys: + case AXP2101_registers_e::chiptemp: + break; + } + return 0u; +} + +uint16_t AXP2101_maxVoltage(AXP2101_registers_e reg) { + switch (reg) { + case AXP2101_registers_e::dcdc1: + case AXP2101_registers_e::dcdc3: return AXP2101_DCDC3_MAX; + case AXP2101_registers_e::dcdc2: return AXP2101_DCDC2_MAX; + case AXP2101_registers_e::dcdc4: return AXP2101_DCDC4_MAX; + case AXP2101_registers_e::dcdc5: return AXP2101_DCDC5_MAX; + case AXP2101_registers_e::aldo1: + case AXP2101_registers_e::aldo2: + case AXP2101_registers_e::aldo3: + case AXP2101_registers_e::aldo4: + case AXP2101_registers_e::bldo1: + case AXP2101_registers_e::bldo2: + case AXP2101_registers_e::dldo1: return AXP2101_DLDO1_MAX; + case AXP2101_registers_e::dldo2: + case AXP2101_registers_e::cpuldos: return AXP2101_CPUSLDO_MAX; + + // not a voltage register + case AXP2101_registers_e::chargeled: + case AXP2101_registers_e::batcharge: + case AXP2101_registers_e::charging: + case AXP2101_registers_e::batpresent: + case AXP2101_registers_e::chipid: + case AXP2101_registers_e::chargedet: + + case AXP2101_registers_e::vbat: + case AXP2101_registers_e::battemp: + case AXP2101_registers_e::vbus: + case AXP2101_registers_e::vsys: + case AXP2101_registers_e::chiptemp: + break; + } + return 0u; +} + +/** + * Is the pin Default, Disabled or Protected, then don't initialize + */ +bool AXP2101_isPinDefault(AXP_pin_s pin) { + return AXP_pin_s::Protected == pin || AXP_pin_s::Disabled == pin || AXP_pin_s::Default == pin; +} + +/** + * Is the pin Disabled or Protected, then don't change + */ +bool AXP2101_isPinProtected(AXP_pin_s pin) { + return AXP_pin_s::Protected == pin || AXP_pin_s::Disabled == pin; +} + +/** + * AXP2101_settings struct + */ + +// constructor +AXP2101_settings::AXP2101_settings() { + chargeStates.pre_chg_cur = 0b0101; + chargeStates.const_cur_lim = 0b01001; // 300 mA, however can be set via EFUSE + chargeStates.term_cur_lim_en = 1; + chargeStates.term_cur_lim = 0b0101; // 125 mA + chargeStates.chg_volt_lim = 0b011; // 4.2V + chargeStates.thermal_thresh = 0b10; // 100 deg + chargeStates.chg_timeout_ctrl = 0b11100110; + chargeStates.bat_detection = 1; + chargeStates.coincell_term_volt = 0b011; // 2.9V + chargeStates.min_sys_voltage = 0b110; // 4.7V + chargeStates.inp_volt_limit = 0b0110; // 4.36V + chargeStates.inp_cur_limit = 0b100; // 1500 mA +} + +// constructor +AXP2101_settings::AXP2101_settings(uint16_t _dcdc1, uint16_t _dcdc2, uint16_t _dcdc3, uint16_t _dcdc4, uint16_t _dcdc5, + uint16_t _aldo1, uint16_t _aldo2, uint16_t _aldo3, uint16_t _aldo4, + uint16_t _bldo1, uint16_t _bldo2, uint16_t _dldo1, uint16_t _dldo2, uint16_t _cpuldos, + AXP_pin_s _en_dcdc1, AXP_pin_s _en_dcdc2, AXP_pin_s _en_dcdc3, AXP_pin_s _en_dcdc4, AXP_pin_s _en_dcdc5, + AXP_pin_s _en_aldo1, AXP_pin_s _en_aldo2, AXP_pin_s _en_aldo3, AXP_pin_s _en_aldo4, + AXP_pin_s _en_bldo1, AXP_pin_s _en_bldo2, AXP_pin_s _en_dldo1, AXP_pin_s _en_dldo2, AXP_pin_s _en_cpuldos, + AXP2101_chargeled_d _chargeled) +{ + registers.dcdc1 = _dcdc1; registers.dcdc2 = _dcdc2; registers.dcdc3 = _dcdc3; registers.dcdc4 = _dcdc4; registers.dcdc5 = _dcdc5; + registers.aldo1 = _aldo1; registers.aldo2 = _aldo2; registers.aldo3 = _aldo3; registers.aldo4 = _aldo4; + registers.bldo1 = _bldo1; registers.bldo2 = _bldo2; registers.dldo1 = _dldo1; registers.dldo2 = _dldo2; registers.cpuldos = _cpuldos; + + pinStates.en_dcdc1 = static_cast(_en_dcdc1); pinStates.en_dcdc2 = static_cast(_en_dcdc2); + pinStates.en_dcdc3 = static_cast(_en_dcdc3); pinStates.en_dcdc4 = static_cast(_en_dcdc4); + pinStates.en_dcdc5 = static_cast(_en_dcdc5); pinStates.en_aldo1 = static_cast(_en_aldo1); + pinStates.en_aldo2 = static_cast(_en_aldo2); pinStates.en_aldo3 = static_cast(_en_aldo3); + pinStates.en_aldo4 = static_cast(_en_aldo4); pinStates.en_bldo1 = static_cast(_en_bldo1); + pinStates.en_bldo2 = static_cast(_en_bldo2); pinStates.en_dldo1 = static_cast(_en_dldo1); + pinStates.en_dldo2 = static_cast(_en_dldo2); pinStates.en_cpuldos = static_cast(_en_cpuldos); + pinStates.chargeled = static_cast(_chargeled); + + chargeStates.pre_chg_cur = 0b0101; + chargeStates.const_cur_lim = 0b01001; // 300 mA, however can be set via EFUSE + chargeStates.term_cur_lim_en = 1; + chargeStates.term_cur_lim = 0b0101; // 125 mA + chargeStates.chg_volt_lim = 0b011; // 4.2V + chargeStates.thermal_thresh = 0b10; // 100 deg + chargeStates.chg_timeout_ctrl = 0b11100110; + chargeStates.bat_detection = 1; + chargeStates.coincell_term_volt = 0b011; // 2.9V + chargeStates.min_sys_voltage = 0b110; // 4.7V + chargeStates.inp_volt_limit = 0b0110; // 4.36V + chargeStates.inp_cur_limit = 0b100; // 1500 mA +} + +void AXP2101_settings::setVoltage(AXP2101_registers_e reg, + int voltage) { + if (-1 == voltage) { voltage = 0xFFFF; } + + switch (reg) { + case AXP2101_registers_e::dcdc1: registers.dcdc1 = voltage; break; + case AXP2101_registers_e::dcdc2: registers.dcdc2 = voltage; break; + case AXP2101_registers_e::dcdc3: registers.dcdc3 = voltage; break; + case AXP2101_registers_e::dcdc4: registers.dcdc4 = voltage; break; + case AXP2101_registers_e::dcdc5: registers.dcdc5 = voltage; break; + case AXP2101_registers_e::aldo1: registers.aldo1 = voltage; break; + case AXP2101_registers_e::aldo2: registers.aldo2 = voltage; break; + case AXP2101_registers_e::aldo3: registers.aldo3 = voltage; break; + case AXP2101_registers_e::aldo4: registers.aldo4 = voltage; break; + case AXP2101_registers_e::bldo1: registers.bldo1 = voltage; break; + case AXP2101_registers_e::bldo2: registers.bldo2 = voltage; break; + case AXP2101_registers_e::dldo1: registers.dldo1 = voltage; break; + case AXP2101_registers_e::dldo2: registers.dldo2 = voltage; break; + case AXP2101_registers_e::cpuldos: registers.cpuldos = voltage; break; + case AXP2101_registers_e::chargeled: + case AXP2101_registers_e::batcharge: + case AXP2101_registers_e::charging: + case AXP2101_registers_e::batpresent: + case AXP2101_registers_e::chipid: + case AXP2101_registers_e::chargedet: + case AXP2101_registers_e::vbat: + case AXP2101_registers_e::battemp: + case AXP2101_registers_e::vbus: + case AXP2101_registers_e::vsys: + case AXP2101_registers_e::chiptemp: + break; + } +} + +int AXP2101_settings::getVoltage(AXP2101_registers_e reg, + bool realValue) { + int result = -1; + + switch (reg) { + case AXP2101_registers_e::dcdc1: result = registers.dcdc1; break; + case AXP2101_registers_e::dcdc2: result = registers.dcdc2; break; + case AXP2101_registers_e::dcdc3: result = registers.dcdc3; break; + case AXP2101_registers_e::dcdc4: result = registers.dcdc4; break; + case AXP2101_registers_e::dcdc5: result = registers.dcdc5; break; + case AXP2101_registers_e::aldo1: result = registers.aldo1; break; + case AXP2101_registers_e::aldo2: result = registers.aldo2; break; + case AXP2101_registers_e::aldo3: result = registers.aldo3; break; + case AXP2101_registers_e::aldo4: result = registers.aldo4; break; + case AXP2101_registers_e::bldo1: result = registers.bldo1; break; + case AXP2101_registers_e::bldo2: result = registers.bldo2; break; + case AXP2101_registers_e::dldo1: result = registers.dldo1; break; + case AXP2101_registers_e::dldo2: result = registers.dldo2; break; + case AXP2101_registers_e::cpuldos: result = registers.cpuldos; break; + case AXP2101_registers_e::chargeled: + case AXP2101_registers_e::batcharge: + case AXP2101_registers_e::charging: + case AXP2101_registers_e::batpresent: + case AXP2101_registers_e::chipid: + case AXP2101_registers_e::chargedet: + case AXP2101_registers_e::vbat: + case AXP2101_registers_e::battemp: + case AXP2101_registers_e::vbus: + case AXP2101_registers_e::vsys: + case AXP2101_registers_e::chiptemp: + return 0; + } + return 0xFFFFF == result ? (realValue ? 0 : -1) : result; +} + +void AXP2101_settings::setState(AXP2101_registers_e reg, + AXP_pin_s state) { + const uint8_t value = static_cast(state) & 0x03; + + switch (reg) { + case AXP2101_registers_e::dcdc1: pinStates.en_dcdc1 = value; break; + case AXP2101_registers_e::dcdc2: pinStates.en_dcdc2 = value; break; + case AXP2101_registers_e::dcdc3: pinStates.en_dcdc3 = value; break; + case AXP2101_registers_e::dcdc4: pinStates.en_dcdc4 = value; break; + case AXP2101_registers_e::dcdc5: pinStates.en_dcdc5 = value; break; + case AXP2101_registers_e::aldo1: pinStates.en_aldo1 = value; break; + case AXP2101_registers_e::aldo2: pinStates.en_aldo2 = value; break; + case AXP2101_registers_e::aldo3: pinStates.en_aldo3 = value; break; + case AXP2101_registers_e::aldo4: pinStates.en_aldo4 = value; break; + case AXP2101_registers_e::bldo1: pinStates.en_bldo1 = value; break; + case AXP2101_registers_e::bldo2: pinStates.en_bldo2 = value; break; + case AXP2101_registers_e::dldo1: pinStates.en_dldo1 = value; break; + case AXP2101_registers_e::dldo2: pinStates.en_dldo2 = value; break; + case AXP2101_registers_e::cpuldos: pinStates.en_cpuldos = value; break; + case AXP2101_registers_e::chargeled: + case AXP2101_registers_e::batcharge: + case AXP2101_registers_e::charging: + case AXP2101_registers_e::batpresent: + case AXP2101_registers_e::chipid: + case AXP2101_registers_e::chargedet: + case AXP2101_registers_e::vbat: + case AXP2101_registers_e::battemp: + case AXP2101_registers_e::vbus: + case AXP2101_registers_e::vsys: + case AXP2101_registers_e::chiptemp: + break; + } +} + +AXP_pin_s AXP2101_settings::getState(AXP2101_registers_e reg) { + switch (reg) { + case AXP2101_registers_e::dcdc1: return static_cast(pinStates.en_dcdc1); + case AXP2101_registers_e::dcdc2: return static_cast(pinStates.en_dcdc2); + case AXP2101_registers_e::dcdc3: return static_cast(pinStates.en_dcdc3); + case AXP2101_registers_e::dcdc4: return static_cast(pinStates.en_dcdc4); + case AXP2101_registers_e::dcdc5: return static_cast(pinStates.en_dcdc5); + case AXP2101_registers_e::aldo1: return static_cast(pinStates.en_aldo1); + case AXP2101_registers_e::aldo2: return static_cast(pinStates.en_aldo2); + case AXP2101_registers_e::aldo3: return static_cast(pinStates.en_aldo3); + case AXP2101_registers_e::aldo4: return static_cast(pinStates.en_aldo4); + case AXP2101_registers_e::bldo1: return static_cast(pinStates.en_bldo1); + case AXP2101_registers_e::bldo2: return static_cast(pinStates.en_bldo2); + case AXP2101_registers_e::dldo1: return static_cast(pinStates.en_dldo1); + case AXP2101_registers_e::dldo2: return static_cast(pinStates.en_dldo2); + case AXP2101_registers_e::cpuldos: return static_cast(pinStates.en_cpuldos); + case AXP2101_registers_e::chargeled: + case AXP2101_registers_e::batcharge: + case AXP2101_registers_e::charging: + case AXP2101_registers_e::batpresent: + case AXP2101_registers_e::chipid: + case AXP2101_registers_e::chargedet: + return AXP_pin_s::Protected; + case AXP2101_registers_e::vbat: + case AXP2101_registers_e::battemp: + case AXP2101_registers_e::vbus: + case AXP2101_registers_e::vsys: + case AXP2101_registers_e::chiptemp: + break; + } + return AXP_pin_s::Default; +} + +void AXP2101_settings::setChargeLed(AXP2101_chargeled_d led) { + pinStates.chargeled = static_cast(led); +} + +AXP2101_chargeled_d AXP2101_settings::getChargeLed() { + return static_cast(pinStates.chargeled); +} + +bool AXP2101_settings::getTS_disabled() { + return pinStates.dis_TS_pin; +} + +void AXP2101_settings::setTS_disabled(bool val) { + pinStates.dis_TS_pin = val; +} + +uint16_t AXP2101_settings::getPreChargeCurrentLimit() const { + return chargeStates.pre_chg_cur * 25; +} + +void AXP2101_settings::setPreChargeCurrentLimit(uint16_t current_mA) { + if (current_mA > 200) { + current_mA = 200; + } + chargeStates.pre_chg_cur = current_mA / 25; +} + +uint16_t AXP2101_settings::getConstChargeCurrentLimit() const { + if (chargeStates.const_cur_lim <= 8) { + return chargeStates.const_cur_lim * 25; + } + return (chargeStates.const_cur_lim - 8) * 100 + 200; +} + +void AXP2101_settings::setConstChargeCurrentLimit(uint16_t current_mA) { + if (current_mA > 1000) { + current_mA = 1000; + } + + if (current_mA <= 200) { + chargeStates.const_cur_lim = current_mA / 25; + } else { + chargeStates.const_cur_lim = ((current_mA - 200) / 100) + 8; + } +} + +uint16_t AXP2101_settings::getTerminationChargeCurrentLimit() const { + return chargeStates.term_cur_lim * 25; +} + +bool AXP2101_settings::getTerminationChargeCurrentLimitEnable() const { + return chargeStates.term_cur_lim_en; +} + +void AXP2101_settings::setTerminationChargeCurrentLimit(uint16_t current_mA, bool enable) { + if (current_mA > 200) { + current_mA = 200; + } + chargeStates.term_cur_lim = current_mA / 25; + chargeStates.term_cur_lim_en = enable; +} + +AXP2101_CV_charger_voltage_e AXP2101_settings::getCV_chargeVoltage() const { + return static_cast(chargeStates.chg_volt_lim); +} + +void AXP2101_settings::setCV_chargeVoltage(AXP2101_CV_charger_voltage_e voltage_mV) { + chargeStates.chg_volt_lim = static_cast(voltage_mV); + + if (chargeStates.chg_volt_lim > static_cast(AXP2101_CV_charger_voltage_e::limit_4_40V)) { + // Set to a default safe limit + chargeStates.chg_volt_lim = static_cast(AXP2101_CV_charger_voltage_e::limit_4_20V); + } +} + +AXP2101_Linear_Charger_Vsys_dpm_e AXP2101_settings::getLinear_Charger_Vsys_dpm() const { + return static_cast(chargeStates.min_sys_voltage); +} + +void AXP2101_settings::setLinear_Charger_Vsys_dpm(AXP2101_Linear_Charger_Vsys_dpm_e voltage) { + chargeStates.min_sys_voltage = static_cast(voltage); +} + +AXP2101_VINDPM_e AXP2101_settings::getVin_DPM() const { + return static_cast(chargeStates.inp_volt_limit); +} + +void AXP2101_settings::setVin_DPM(AXP2101_VINDPM_e voltage) { + chargeStates.inp_volt_limit = static_cast(voltage); +} + +AXP2101_InputCurrentLimit_e AXP2101_settings::getInputCurrentLimit() const { + return static_cast(chargeStates.inp_cur_limit); +} + +void AXP2101_settings::setInputCurrentLimit(AXP2101_InputCurrentLimit_e current) { + chargeStates.inp_cur_limit = static_cast(current); +} + +/** + * AXP2101 device class + */ + +// *INDENT-OFF* +AXP2101_settings AXP2101_deviceSettingsArray[] = +{ // voltages: dcdc1 | dcdc2 | dcdc3 | dcdc4 | dcdc5 | aldo1 | aldo2 | aldo3 | aldo4| bldo1 | bldo2 | dldo1 | dldo2 | cpuldos | en_dcdc1 | en_dcdc2 | en_dcdc3 | en_dcdc4 | en_dcdc5 | en_aldo1 | en_aldo2 | en_aldo3 | en_aldo4 | en_bldo1 | en_bldo2 | en_dldo1 | en_dldo2 | en_cpuldos | chargeled +/* Unselected */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP2101_chargeled_d::Off }, +/* M5Stack Core2 v1.1 */ { 3300, 0, 3300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AXP_pin_s::Protected, AXP_pin_s::Disabled, AXP_pin_s::Protected, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP2101_chargeled_d::Off }, +/* M5Stack CoreS3 */ { 3300, 0, 3300, 0, 0, 1800, 3300, 3300, 3300, 0, 0, 0, 0, 0, AXP_pin_s::Protected, AXP_pin_s::Disabled, AXP_pin_s::Protected, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Protected, AXP_pin_s::Protected, AXP_pin_s::Default, AXP_pin_s::Protected, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP2101_chargeled_d::Off }, +/* LilyGo TBeam v1.2 */ { 3300, 0, 2500, 0, 0, 0, 3300, 3300, 0, 0, 0, 0, 0, 0, AXP_pin_s::Protected, AXP_pin_s::Disabled, AXP_pin_s::Protected, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Default, AXP2101_chargeled_d::Off }, +/* LilyGo TBeamS3 */ { 3300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AXP_pin_s::Protected, AXP_pin_s::Disabled, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP2101_chargeled_d::Off }, +/* LilyGo TPCie v1.2 */ { 3300, 900, 900, 1100, 1200, 1800, 2800, 3300, 2900, 1800, 2800, 500, 1900, 1300, AXP_pin_s::Protected, AXP_pin_s::Disabled, AXP_pin_s::Protected, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP_pin_s::Disabled, AXP2101_chargeled_d::Off }, +/* Userdefined */ { 3300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP_pin_s::Default, AXP2101_chargeled_d::Off }, +}; +// *INDENT-ON* + +# pragma GCC diagnostic pop + +#endif // ifdef ESP32 diff --git a/lib/AXP2101/src/AXP2101_settings.h b/lib/AXP2101/src/AXP2101_settings.h new file mode 100644 index 0000000000..891d1d345d --- /dev/null +++ b/lib/AXP2101/src/AXP2101_settings.h @@ -0,0 +1,452 @@ +#ifndef __AXP2101_SETTINGS_H +#define __AXP2101_SETTINGS_H + +/** + * AXP2101 library adjusted for ESPEasy + * 2024-02-04 tonhuisman: Start. + * + * Based on the AXP2101 driver included in https://github.com/m5stack/M5Core2 + */ + +/** Changelog: + * 2024-02-21 tonhuisman: Add support for ChipId and ChargingDetail state + * 2024-02-18 tonhuisman: Add support for ChargingState, isBatteryDetected + * 2024-02-17 tonhuisman: Add support for Charge-led and battery charge level, limit to ESP32, as this chip is only available + * on ESP32 based units + * 2024-02-16 tonhuisman: Initial 'release' with AXP2101 plugin for ESPEasy, implementing all output pins + * Including predefined settings for M5Stack Core2 v1.1, M5Stack CoreS3, LilyGO_TBeam_v1_2, + * LilyGO_TBeamS3_v3, LilyGO_TPCie_v1_2. + * 2024-02-04 tonhuisman: Start development of the library + */ + +#include +#include + +#define AXP2101_ADDR (0x34) + +#define AXP2101_DCDC_CTRL_REG (0x80) +#define AXP2101_LDO_CTRL_REG (0x90) +#define AXP2101_LDO_CTRL_REG1 (0x91) + +#define AXP2101_DCDC1_VOLTAGE_REG (0x82) +#define AXP2101_DCDC2_VOLTAGE_REG (0x83) +#define AXP2101_DCDC3_VOLTAGE_REG (0x84) +#define AXP2101_DCDC4_VOLTAGE_REG (0x85) +#define AXP2101_DCDC5_VOLTAGE_REG (0x86) +#define AXP2101_ALDO1_VOLTAGE_REG (0x92) +#define AXP2101_ALDO2_VOLTAGE_REG (0x93) +#define AXP2101_ALDO3_VOLTAGE_REG (0x94) +#define AXP2101_ALDO4_VOLTAGE_REG (0x95) +#define AXP2101_BLDO1_VOLTAGE_REG (0x96) +#define AXP2101_BLDO2_VOLTAGE_REG (0x97) +#define AXP2101_DLDO1_VOLTAGE_REG (0x99) +#define AXP2101_DLDO2_VOLTAGE_REG (0x9A) +#define AXP2101_CPUSLDO_VOLTAGE_REG (0x98) + +// Measure V battery +#define AXP2101_VBAT_H_ADC_REG (0x34) +#define AXP2101_VBAT_L_ADC_REG (0x35) + +// Measure (optional) temperature sensor +#define AXP2101_TS_H_ADC_REG (0x36) +#define AXP2101_TS_L_ADC_REG (0x37) + +// Measure Vbus +#define AXP2101_VBUS_H_ADC_REG (0x38) +#define AXP2101_VBUS_L_ADC_REG (0x39) + +// Measure Vsys +#define AXP2101_VSYS_H_ADC_REG (0x3A) +#define AXP2101_VSYS_L_ADC_REG (0x3B) + +// Measure chip die temperature +#define AXP2101_TDIE_H_ADC_REG (0x3C) +#define AXP2101_TDIE_L_ADC_REG (0x3D) + + +#define AXP2101_VBAT_CTRL_MASK (1 << 0) +#define AXP2101_BATTEMP_CTRL_MASK (1 << 1) +#define AXP2101_VBUS_CTRL_MASK (1 << 2) +#define AXP2101_VSYS_CTRL_MASK (1 << 3) +#define AXP2101_TDIE_CTRL_MASK (1 << 4) + +// What to do with bit 5: "general purpose ADC channel enable"? + + +#define AXP2101_COM_STAT0_REG (0x00) +#define AXP2101_COM_STAT1_REG (0x01) +#define AXP2101_CHIP_ID_REG (0x03) +#define AXP2101_CHARGE_DET_REG (0x04) // Fake, not a usable register! +#define AXP2101_PMU_CONFIG_REG (0x10) +#define AXP2101_MIN_VSYS_REG (0x14) +#define AXP2101_VIN_DPM_REG (0x15) +#define AXP2101_IN_CURRENT_LIMIT_REG (0x16) +#define AXP2101_CHARG_FGAUG_WDOG_REG (0x18) +#define AXP2101_PWROK_PWROFF_REG (0x25) +#define AXP2101_ADC_ENABLE_REG (0x30) +#define AXP2101_IRQ_EN_0_REG (0x40) +#define AXP2101_IRQ_EN_1_REG (0x41) +#define AXP2101_IRQ_EN_2_REG (0x42) +#define AXP2101_IRQ_STATUS_0_REG (0x48) +#define AXP2101_IRQ_STATUS_1_REG (0x49) +#define AXP2101_IRQ_STATUS_2_REG (0x4A) +#define AXP2101_TS_PIN_CTRL_REG (0x50) +#define AXP2101_IPRECHG_REG (0x61) +#define AXP2101_ICC_CHARGER_SETTING_REG (0x62) +#define AXP2101_CHARGER_SETTING_REG (0x63) +#define AXP2101_CV_CHARGER_SETTING_REG (0x64) +#define AXP2101_CHGLED_REG (0x69) +#define AXP2101_BAT_CHARGE_REG (0xA4) /* pdf has a duplicate listed for register 0x04, should be 0xA4 */ + +#define AXP2101_DCDC1_CTRL_MASK (1 << 0) +#define AXP2101_DCDC2_CTRL_MASK (1 << 1) +#define AXP2101_DCDC3_CTRL_MASK (1 << 2) +#define AXP2101_DCDC4_CTRL_MASK (1 << 3) +#define AXP2101_DCDC5_CTRL_MASK (1 << 4) +#define AXP2101_ALDO1_CTRL_MASK (1 << 0) +#define AXP2101_ALDO2_CTRL_MASK (1 << 1) +#define AXP2101_ALDO3_CTRL_MASK (1 << 2) +#define AXP2101_ALDO4_CTRL_MASK (1 << 3) +#define AXP2101_BLDO1_CTRL_MASK (1 << 4) +#define AXP2101_BLDO2_CTRL_MASK (1 << 5) +#define AXP2101_DLDO1_CTRL_MASK (1 << 7) +#define AXP2101_DLDO2_CTRL_MASK (1 << 0) +#define AXP2101_CPUSLDO_CTRL_MASK (1 << 6) +#define AXP2101_CHGLED_CTRL_MASK (0x03 << 4) + +#define AXP2101_DCDC1_MIN (1500) +#define AXP2101_DCDC2_MIN (500) +#define AXP2101_DCDC3_MIN (500) +#define AXP2101_DCDC4_MIN (500) +#define AXP2101_DCDC5_MIN (1400) +#define AXP2101_ALDO1_MIN (500) +#define AXP2101_ALDO2_MIN (500) +#define AXP2101_ALDO3_MIN (500) +#define AXP2101_ALDO4_MIN (500) +#define AXP2101_BLDO1_MIN (500) +#define AXP2101_BLDO2_MIN (500) +#define AXP2101_DLDO1_MIN (500) +#define AXP2101_DLDO2_MIN (500) +#define AXP2101_CPUSLDO_MIN (500) + +#define AXP2101_DCDC1_MAX (3400) +#define AXP2101_DCDC2_MAX (1540) +#define AXP2101_DCDC3_MAX (3400) +#define AXP2101_DCDC4_MAX (1840) +#define AXP2101_DCDC5_MAX (3700) +#define AXP2101_ALDO1_MAX (3500) +#define AXP2101_ALDO2_MAX (3500) +#define AXP2101_ALDO3_MAX (3500) +#define AXP2101_ALDO4_MAX (3500) +#define AXP2101_BLDO1_MAX (3500) +#define AXP2101_BLDO2_MAX (3500) +#define AXP2101_DLDO1_MAX (3500) +#define AXP2101_DLDO2_MAX (1400) +#define AXP2101_CPUSLDO_MAX (1400) + +enum class AXP2101_device_model_e : uint8_t { + Unselected = 0u, // >>>>> Don't change these values, they are probably stored in user-settings <<<<< + M5Stack_Core2_v1_1 = 1u, // https://docs.m5stack.com/en/core/Core2%20v1.1 + M5Stack_CoreS3 = 2u, // https://docs.m5stack.com/en/core/CoreS3 + LilyGO_TBeam_v1_2 = 3u, // https://github.com/Xinyuan-LilyGO/LilyGo-LoRa-Series/blob/master/schematic/LilyGo_TBeam_V1.2.pdf + LilyGO_TBeamS3_v3 = 4u, // https://github.com/Xinyuan-LilyGO/LilyGo-LoRa-Series/blob/master/schematic/LilyGo_TBeam_S3_Core_V3.0.pdf + LilyGO_TPCie_v1_2 = 5u, // https://github.com/Xinyuan-LilyGO/LilyGo-T-PCIE/blob/master/schematic/T-PCIE-V1.2.pdf + + MAX, // Keep MAX as first after last device, devices must be sequentially numbered + UserDefined = 99u, // Keep UserDefined as last!!! +}; + +// The voltage registers mapped into an enum, don't change order without also changing AXP2101_intToRegister() +enum class AXP2101_registers_e : uint8_t { + dcdc1 = AXP2101_DCDC1_VOLTAGE_REG, + dcdc2 = AXP2101_DCDC2_VOLTAGE_REG, + dcdc3 = AXP2101_DCDC3_VOLTAGE_REG, + dcdc4 = AXP2101_DCDC4_VOLTAGE_REG, + dcdc5 = AXP2101_DCDC5_VOLTAGE_REG, + aldo1 = AXP2101_ALDO1_VOLTAGE_REG, + aldo2 = AXP2101_ALDO2_VOLTAGE_REG, + aldo3 = AXP2101_ALDO3_VOLTAGE_REG, + aldo4 = AXP2101_ALDO4_VOLTAGE_REG, + bldo1 = AXP2101_BLDO1_VOLTAGE_REG, + bldo2 = AXP2101_BLDO2_VOLTAGE_REG, + dldo1 = AXP2101_DLDO1_VOLTAGE_REG, + dldo2 = AXP2101_DLDO2_VOLTAGE_REG, + cpuldos = AXP2101_CPUSLDO_VOLTAGE_REG, + + // ADC inputs + vbat = AXP2101_VBAT_H_ADC_REG, + battemp = AXP2101_TS_H_ADC_REG, + vbus = AXP2101_VBUS_H_ADC_REG, + vsys = AXP2101_VSYS_H_ADC_REG, + chiptemp = AXP2101_TDIE_H_ADC_REG, + + // Above are settable pinstates/voltages of the AXP2101 + // Below are non-voltage and read-only values of the AXP2101, also update AXP2101_register_count when adding values + chargeled = AXP2101_CHGLED_REG, + batcharge = AXP2101_BAT_CHARGE_REG, + charging = AXP2101_COM_STAT1_REG, + batpresent = AXP2101_COM_STAT0_REG, + chipid = AXP2101_CHIP_ID_REG, + chargedet = AXP2101_CHARGE_DET_REG, +}; +constexpr int AXP2101_settings_count = 14; // Changeable settings +constexpr int AXP2101_register_count = 25; // All registers + +enum class AXP_pin_s : uint8_t { + Off = 0x00, // Max. 3 bits can be stored in settings! + On = 0x01, + Default = 0x02, // Don't update value or state on boot + Disabled = 0x03, // Port not connected, don't use + Protected = 0x07 // Don't try to change port value, can make the unit fail! +}; + +enum class AXP2101_chargeled_d : uint8_t { + Off = 0x00, + Flash_1Hz = 0x01, + Flash_4Hz = 0x02, + Steady_On = 0x03, + Protected = 0x07 // Don't try to change or not connected +}; + +enum class AXP2101_chargingState_e : int8_t { + Discharging = -1, + Standby = 0, + Charging = 1, +}; + +enum class AXP2101_chipid_e : uint8_t { + axp2101 = 0b01000111, // AXP2101 +}; + +enum class AXP2101_chargingDetail_e : uint8_t { + tricharge = 0b000, + precharge = 0b001, + constcharge = 0b010, + constvoltage = 0b011, + done = 0b100, + notcharging = 0b101, +}; + +enum class AXP2101_CV_charger_voltage_e : uint8_t { + reserved = 0, + limit_4_00V = 0b001, + limit_4_10V = 0b010, + limit_4_20V = 0b011, // default + limit_4_35V = 0b100, + limit_4_40V = 0b101, + MAX +}; + +enum class AXP2101_Linear_Charger_Vsys_dpm_e : uint8_t { + vsys_4_1V = 0, + vsys_4_2V, + vsys_4_3V, + vsys_4_4V, + vsys_4_5V, + vsys_4_6V, + vsys_4_7V, + vsys_4_8V, + MAX +}; + +enum class AXP2101_VINDPM_e : uint8_t { + Vin_3_88V = 0, + Vin_3_96V, + Vin_4_04V, + Vin_4_12V, + Vin_4_20V, + Vin_4_28V, + Vin_4_36V, + Vin_4_44V, + Vin_4_52V, + Vin_4_60V, + Vin_4_68V, + Vin_4_76V, + Vin_4_84V, + Vin_4_92V, + Vin_5_00V, + Vin_5_08V, + MAX +}; + +enum class AXP2101_InputCurrentLimit_e : uint8_t { + limit_100mA = 0, + limit_500mA, + limit_900mA, + limit_1000mA, + limit_1500mA, + limit_2000mA, + MAX +}; + + +AXP2101_registers_e AXP2101_intToRegister(int reg); +uint16_t AXP2101_maxVoltage(AXP2101_registers_e reg); +uint16_t AXP2101_minVoltage(AXP2101_registers_e reg); +bool AXP2101_isPinDefault(AXP_pin_s pin); // Default, Disabled or Protected +bool AXP2101_isPinProtected(AXP_pin_s pin); // Disabled or Protected + +const __FlashStringHelper* toString(AXP2101_registers_e reg, + bool displayString = true); +const __FlashStringHelper* toString(AXP2101_device_model_e device, + bool displayString = true); +const __FlashStringHelper* toString(AXP_pin_s pin); +const __FlashStringHelper* toString(AXP2101_chargeled_d led); +const __FlashStringHelper* toString(AXP2101_chargingState_e state); +const __FlashStringHelper* toString(AXP2101_chipid_e chip); +const __FlashStringHelper* toString(AXP2101_chargingDetail_e charge); + +class AXP2101_settings { // Voltages in mV, range 0..3700, max. depending on the AXP2101 pin/port used. +public: + + AXP2101_settings(); + AXP2101_settings(uint16_t _dcdc1, + uint16_t _dcdc2, + uint16_t _dcdc3, + uint16_t _dcdc4, + uint16_t _dcdc5, + uint16_t _aldo1, + uint16_t _aldo2, + uint16_t _aldo3, + uint16_t _aldo4, + uint16_t _bldo1, + uint16_t _bldo2, + uint16_t _dldo1, + uint16_t _dldo2, + uint16_t _cpuldos, + AXP_pin_s _en_dcdc1, + AXP_pin_s _en_dcdc2, + AXP_pin_s _en_dcdc3, + AXP_pin_s _en_dcdc4, + AXP_pin_s _en_dcdc5, + AXP_pin_s _en_aldo1, + AXP_pin_s _en_aldo2, + AXP_pin_s _en_aldo3, + AXP_pin_s _en_aldo4, + AXP_pin_s _en_bldo1, + AXP_pin_s _en_bldo2, + AXP_pin_s _en_dldo1, + AXP_pin_s _en_dldo2, + AXP_pin_s _en_cpuldos, + AXP2101_chargeled_d _chargeled); + void setVoltage(AXP2101_registers_e reg, + int voltage); + int getVoltage(AXP2101_registers_e reg, + bool realValue = true); + void setState(AXP2101_registers_e reg, + AXP_pin_s state); + AXP_pin_s getState(AXP2101_registers_e reg); + void setChargeLed(AXP2101_chargeled_d led); + AXP2101_chargeled_d getChargeLed(); + + bool getTS_disabled(); + void setTS_disabled(bool val); + + + // Reg 61: Iprechg Charger Settings + uint16_t getPreChargeCurrentLimit() const; + void setPreChargeCurrentLimit(uint16_t current_mA); + + // Reg 62: ICC Charger Settings + uint16_t getConstChargeCurrentLimit() const; + void setConstChargeCurrentLimit(uint16_t current_mA); + + // Reg 63: Iterm Charger Settings and Control + // Enable/Disable via chargeStates.term_cur_lim_en + uint16_t getTerminationChargeCurrentLimit() const; + bool getTerminationChargeCurrentLimitEnable() const; + void setTerminationChargeCurrentLimit(uint16_t current_mA, + bool enable); + + // Reg 64: CV Charger Voltage Settings + AXP2101_CV_charger_voltage_e getCV_chargeVoltage() const; + void setCV_chargeVoltage(AXP2101_CV_charger_voltage_e voltage_mV); + + // Reg 14: Minimum System Voltage Control + AXP2101_Linear_Charger_Vsys_dpm_e getLinear_Charger_Vsys_dpm() const; + void setLinear_Charger_Vsys_dpm(AXP2101_Linear_Charger_Vsys_dpm_e voltage); + + // Reg 15: Input Voltage Limit + AXP2101_VINDPM_e getVin_DPM() const; + void setVin_DPM(AXP2101_VINDPM_e voltage); + + // Reg 16: Input Current Limit + AXP2101_InputCurrentLimit_e getInputCurrentLimit() const; + void setInputCurrentLimit(AXP2101_InputCurrentLimit_e current); + +private: + + union { + struct { + uint16_t dcdc1; + uint16_t dcdc2; + uint16_t dcdc3; + uint16_t dcdc4; + uint16_t dcdc5; + uint16_t aldo1; + uint16_t aldo2; + uint16_t aldo3; + uint16_t aldo4; + uint16_t bldo1; + uint16_t bldo2; + uint16_t dldo1; + uint16_t dldo2; + uint16_t cpuldos; + } registers; + uint16_t registers_[AXP2101_settings_count]{}; + }; + union { + struct { // AXP_pin_s: Off / On / default / disabled / unavailable? / unused? / Protected + uint64_t en_dcdc1 : 3; // bit 0/1/2 + uint64_t en_dcdc2 : 3; // bit 3/4/5 + uint64_t en_dcdc3 : 3; // bit 6/7/8 + uint64_t en_dcdc4 : 3; // bit 9/10/11 + uint64_t en_dcdc5 : 3; // bit 12/13/14 + uint64_t en_aldo1 : 3; // bit 15/16/17 + uint64_t en_aldo2 : 3; // bit 18/19/20 + uint64_t en_aldo3 : 3; // bit 21/22/23 + uint64_t en_aldo4 : 3; // bit 24/25/26 + uint64_t en_bldo1 : 3; // bit 27/28/29 + uint64_t en_bldo2 : 3; // bit 30/31/32 + uint64_t en_dldo1 : 3; // bit 33/34/35 + uint64_t en_dldo2 : 3; // bit 36/37/38 + uint64_t en_cpuldos : 3; // bit 39/40/41 + uint64_t chargeled : 3; // bit 42/43/44 + + // Settings for external temperature sensor (TS) + uint64_t dis_TS_pin : 1; // bit 45, reg50 bit 4 + uint64_t TS_cur_src : 2; // bit 46/47, reg50 bit 3:2 + uint64_t TS_current : 2; // bit 48/49, reg50 bit 1:0 + + uint64_t en_unused : 13; // bit 50..63 // All bits defined + } pinStates; + uint64_t pinStates_{}; // 8 bytes + }; + + union { + struct { + uint64_t pre_chg_cur : 4; // reg 0x61: 25* N mA + uint64_t const_cur_lim : 5; // reg 0x62: 25* N mA if N <= 8, 200+100*(N-8) mA if N > 8 + uint64_t term_cur_lim_en : 1; // reg 0x63: Charging termination of current enable + uint64_t term_cur_lim : 4; // reg 0x63: 25* N mA + uint64_t chg_volt_lim : 3; // reg 0x64: + uint64_t thermal_thresh : 2; // reg 0x65: 00: 60deg, 01: 80deg, 10: 100deg, 11:120deg + uint64_t chg_timeout_ctrl : 8; // reg 0x67: + uint64_t bat_detection : 1; // reg 0x68: + uint64_t coincell_term_volt : 3; // reg 0x6A: 2.6~3.3V, 100mV/step, 8 steps + + uint64_t min_sys_voltage : 3; // reg 0x14: 4.1 + N*0.1V Linear Charger Vsys Voltage dpm + uint64_t inp_volt_limit : 4; // reg 0x15: Vindpm 3.88+N*0.08V + uint64_t inp_cur_limit : 3; // reg 0x16: + + + uint64_t en_unused : 23; + } chargeStates; + uint64_t chargeStates_{}; // 8 bytes + }; +}; + +extern AXP2101_settings AXP2101_deviceSettingsArray[]; + + +#endif // ifndef __AXP2101_SETTINGS_H diff --git a/platformio_esp82xx_base.ini b/platformio_esp82xx_base.ini index 90a1b999e4..c64d7e2851 100644 --- a/platformio_esp82xx_base.ini +++ b/platformio_esp82xx_base.ini @@ -146,6 +146,7 @@ lib_ignore = ESP32_ping ESP8266mDNS I2C AXP192 Power management EspSoftwareSerial + AXP2101 Power management (I2C) diff --git a/src/_C011.cpp b/src/_C011.cpp index b4d1aab50b..ef641abd6d 100644 --- a/src/_C011.cpp +++ b/src/_C011.cpp @@ -102,13 +102,17 @@ bool CPlugin_011(CPlugin::Function function, struct EventStruct *event, String& uint8_t choice = 0; const __FlashStringHelper * methods[] = { F("GET"), F("POST"), F("PUT"), F("HEAD"), F("PATCH") }; - for (uint8_t i = 0; i < 5; i++) + constexpr int nrOptions = NR_ELEMENTS(methods); + + for (uint8_t i = 0; i < nrOptions; i++) { if (HttpMethod.equals(methods[i])) { choice = i; } } - addFormSelector(F("Method"), F("P011httpmethod"), 5, methods, nullptr, choice); + + const FormSelectorOptions selector(nrOptions, methods); + selector.addFormSelector(F("Method"), F("P011httpmethod"), choice); } addFormTextBox(F("URI"), F("P011httpuri"), HttpUri, C011_HTTP_URI_MAX_LEN - 1); diff --git a/src/_P001_Switch.ino b/src/_P001_Switch.ino index 2d16e8858c..bc5fd78087 100644 --- a/src/_P001_Switch.ino +++ b/src/_P001_Switch.ino @@ -86,7 +86,8 @@ boolean Plugin_001(uint8_t function, struct EventStruct *event, String& string) const int optionValues[] = { PLUGIN_001_TYPE_SWITCH, PLUGIN_001_TYPE_DIMMER }; const uint8_t switchtype = P001_data_struct::P001_getSwitchType(event); constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Switch Type"), F("type"), optionCount, options, optionValues, switchtype); + const FormSelectorOptions selector(optionCount, options, optionValues); + selector.addFormSelector(F("Switch Type"), F("type"), switchtype); if (switchtype == PLUGIN_001_TYPE_DIMMER) { @@ -99,16 +100,18 @@ boolean Plugin_001(uint8_t function, struct EventStruct *event, String& string) F("Normal Switch"), F("Push Button Active Low"), F("Push Button Active High") }; +/* const int buttonOptionValues[] = { SWITCH_TYPE_NORMAL_SWITCH, SWITCH_TYPE_PUSH_ACTIVE_LOW, SWITCH_TYPE_PUSH_ACTIVE_HIGH }; - addFormSelector( +*/ + const FormSelectorOptions selector( + NR_ELEMENTS(buttonOptions), + buttonOptions); // buttonOptionValues); + selector.addFormSelector( F("Switch Button Type"), F("button"), - NR_ELEMENTS(buttonOptionValues), - buttonOptions, - buttonOptionValues, P001_BUTTON_TYPE); } diff --git a/src/_P003_Pulse.ino b/src/_P003_Pulse.ino index dfbeeee601..18bc731dde 100644 --- a/src/_P003_Pulse.ino +++ b/src/_P003_Pulse.ino @@ -163,8 +163,10 @@ boolean Plugin_003(uint8_t function, struct EventStruct *event, String& string) F("Time/Delta"), # endif // if P003_USE_EXTRA_COUNTERTYPES }; - constexpr size_t optionCount = NR_ELEMENTS(options); - addFormSelector(F("Counter Type"), F("countertype"), optionCount, options, nullptr, choice); + const FormSelectorOptions selector( + NR_ELEMENTS(options), + options); + selector.addFormSelector(F("Counter Type"), F("countertype"), choice); if (choice != 0) { addHtml(F("Total count is not persistent!")); diff --git a/src/_P004_Dallas.ino b/src/_P004_Dallas.ino index 01b1ce4105..1c4a740054 100644 --- a/src/_P004_Dallas.ino +++ b/src/_P004_Dallas.ino @@ -138,20 +138,24 @@ boolean Plugin_004(uint8_t function, struct EventStruct *event, String& string) int resolutionChoice = P004_RESOLUTION; if ((resolutionChoice < 9) || (resolutionChoice > 12)) { resolutionChoice = activeRes; } - const __FlashStringHelper *resultsOptions[] = { F("9"), F("10"), F("11"), F("12") }; - const int resultsOptionValues[] = { 9, 10, 11, 12 }; - constexpr size_t optionCount = NR_ELEMENTS(resultsOptionValues); - addFormSelector(F("Device Resolution"), F("res"), optionCount, resultsOptions, resultsOptionValues, resolutionChoice); - addHtml(F(" Bit")); + constexpr int resultsOptionValues[] { 9, 10, 11, 12 }; + + const FormSelectorOptions selector( + NR_ELEMENTS(resultsOptionValues), + resultsOptionValues); + selector.addFormSelector(F("Device Resolution"), F("res"), resolutionChoice); + addUnit(F("bit")); } { // Value in case of Error const __FlashStringHelper *resultsOptions[] = { F("NaN"), F("-127"), F("0"), F("125"), F("Ignore") }; - int resultsOptionValues[] = - { P004_ERROR_NAN, P004_ERROR_MIN_RANGE, P004_ERROR_ZERO, P004_ERROR_MAX_RANGE, P004_ERROR_IGNORE }; - constexpr size_t optionCount = NR_ELEMENTS(resultsOptionValues); - addFormSelector(F("Error State Value"), F("err"), optionCount, resultsOptions, resultsOptionValues, P004_ERROR_STATE_OUTPUT); + constexpr int resultsOptionValues[] { P004_ERROR_NAN, P004_ERROR_MIN_RANGE, P004_ERROR_ZERO, P004_ERROR_MAX_RANGE, P004_ERROR_IGNORE }; + + const FormSelectorOptions selector( + NR_ELEMENTS(resultsOptionValues), + resultsOptions, resultsOptionValues); + selector.addFormSelector(F("Error State Value"), F("err"), P004_ERROR_STATE_OUTPUT); } addFormNote(F("External pull up resistor is needed, see docs!")); diff --git a/src/_P005_DHT.ino b/src/_P005_DHT.ino index 592fd08aa9..9b83d51692 100644 --- a/src/_P005_DHT.ino +++ b/src/_P005_DHT.ino @@ -62,11 +62,11 @@ boolean Plugin_005(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *options[] = { F("DHT 11"), F("DHT 22"), F("DHT 12"), F("Sonoff am2301"), F("Sonoff si7021"), F("Sonoff MS01") }; - const int indices[] = { P005_DHT11, P005_DHT22, P005_DHT12, P005_AM2301, P005_SI7021, P005_MS01 }; - + constexpr int indices[]{ P005_DHT11, P005_DHT22, P005_DHT12, P005_AM2301, P005_SI7021, P005_MS01 }; constexpr size_t nrElements = NR_ELEMENTS(indices); - addFormSelector(F("Sensor model"), F("dhttype"), nrElements, options, indices, PCONFIG(0)); + const FormSelectorOptions selector(nrElements, options, indices); + selector.addFormSelector(F("Sensor model"), F("dhttype"), PCONFIG(0)); success = true; break; diff --git a/src/_P007_PCF8591.ino b/src/_P007_PCF8591.ino index 241fb92214..e1e1378fed 100644 --- a/src/_P007_PCF8591.ino +++ b/src/_P007_PCF8591.ino @@ -105,7 +105,8 @@ boolean Plugin_007(uint8_t function, struct EventStruct *event, String& string) portNames[x] += x; } addFormSelectorI2C(F("pi2c"), 8, i2cAddressValues, address); - addFormSelector(F("Port"), F("pport"), 4, portNames, portValues, port); + const FormSelectorOptions selector(4, portNames, portValues); + selector.addFormSelector(F("Port"), F("pport"), port); addFormNote(F( "Selected Port value will be stored in first 'Values' field and consecutively for 'Number Output Values' > Single.")); } else { @@ -142,7 +143,8 @@ boolean Plugin_007(uint8_t function, struct EventStruct *event, String& string) 0b00110000, }; constexpr size_t optionCount = NR_ELEMENTS(inputModeValues); - addFormSelector(F("Input mode"), F("input_mode"), optionCount, inputModeOptions, inputModeValues, P007_INPUT_MODE); + const FormSelectorOptions selector(optionCount, inputModeOptions, inputModeValues); + selector.addFormSelector(F("Input mode"), F("input_mode"), P007_INPUT_MODE); addFormCheckBox(F("Enable Analog output (AOUT)"), F("output_mode"), P007_OUTPUT_MODE == P007_OUTPUT_ENABLED); diff --git a/src/_P009_MCP.ino b/src/_P009_MCP.ino index 8bbfb00785..88e590d3ef 100644 --- a/src/_P009_MCP.ino +++ b/src/_P009_MCP.ino @@ -71,7 +71,8 @@ boolean Plugin_009(uint8_t function, struct EventStruct *event, String& string) portNames[x] += (x < 8 ? x : x - 8); } addFormSelectorI2C(F("pi2c"), 8, i2cAddressValues, address); - addFormSelector(F("Port"), F("pport"), 16, portNames, portValues, port); + const FormSelectorOptions selector(16, portNames, portValues); + selector.addFormSelector(F("Port"), F("pport"), port); } else { success = intArrayContains(8, i2cAddressValues, event->Par1); } diff --git a/src/_P010_BH1750.ino b/src/_P010_BH1750.ino index b62be65a69..67c731b0cd 100644 --- a/src/_P010_BH1750.ino +++ b/src/_P010_BH1750.ino @@ -85,7 +85,8 @@ boolean Plugin_010(uint8_t function, struct EventStruct *event, String& string) RESOLUTION_AUTO_HIGH, }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode); - addFormSelector(F("Measurement mode"), F("pmode"), optionCount, optionsMode, optionValuesMode, PCONFIG(1)); + const FormSelectorOptions selector(optionCount, optionsMode, optionValuesMode); + selector.addFormSelector(F("Measurement mode"), F("pmode"), PCONFIG(1)); addFormCheckBox(F("Send sensor to sleep"), F("psleep"), PCONFIG(2)); diff --git a/src/_P011_PME.ino b/src/_P011_PME.ino index f867281c10..47c97c57aa 100644 --- a/src/_P011_PME.ino +++ b/src/_P011_PME.ino @@ -84,7 +84,8 @@ boolean Plugin_011(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *options[] = { F("Digital"), F("Analog"), F("Input (switch)") }; const int optionValues[] = { P011_TYPE_DIGITAL, P011_TYPE_ANALOG, P011_TYPE_SWITCH }; constexpr size_t optionCount = NR_ELEMENTS(options); - addFormSelector(F("Port Type"), F("p011"), optionCount, options, optionValues, P011_PORT_TYPE); + const FormSelectorOptions selector(optionCount, options, optionValues); + selector.addFormSelector(F("Port Type"), F("p011"), P011_PORT_TYPE); success = true; break; diff --git a/src/_P012_LCD.ino b/src/_P012_LCD.ino index 416b83036f..11d5b63843 100644 --- a/src/_P012_LCD.ino +++ b/src/_P012_LCD.ino @@ -97,7 +97,8 @@ boolean Plugin_012(uint8_t function, struct EventStruct *event, String& string) }; const int optionValues2[2] = { 1, 2 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues2); - addFormSelector(F("Display Size"), F("psize"), optionCount, options2, optionValues2, P012_SIZE); + const FormSelectorOptions selector(optionCount, options2, optionValues2); + selector.addFormSelector(F("Display Size"), F("psize"), P012_SIZE); } { @@ -125,7 +126,8 @@ boolean Plugin_012(uint8_t function, struct EventStruct *event, String& string) }; const int optionValues3[] = { 0, 1, 2 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues3); - addFormSelector(F("LCD command Mode"), F("pmode"), optionCount, options3, optionValues3, P012_MODE); + const FormSelectorOptions selector(optionCount, options3, optionValues3); + selector.addFormSelector(F("LCD command Mode"), F("pmode"), P012_MODE); } success = true; diff --git a/src/_P013_HCSR04.ino b/src/_P013_HCSR04.ino index 1a2f15902e..688e9e0a8a 100644 --- a/src/_P013_HCSR04.ino +++ b/src/_P013_HCSR04.ino @@ -131,7 +131,8 @@ boolean Plugin_013(uint8_t function, struct EventStruct *even # endif // if P013_FEATURE_COMBINED_MODE }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesOpMode); - addFormSelector(F("Mode"), F("pmode"), optionCount, optionsOpMode, optionValuesOpMode, P013_OPERATINGMODE); + const FormSelectorOptions selector(optionCount, optionsOpMode, optionValuesOpMode); + selector.addFormSelector(F("Mode"), F("pmode"), P013_OPERATINGMODE); } if ((P013_OPERATINGMODE == OPMODE_STATE) @@ -155,7 +156,8 @@ boolean Plugin_013(uint8_t function, struct EventStruct *even F("Imperial"), }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesUnit); - addFormSelector(F("Unit"), F("pUnit"), optionCount, optionsUnit, optionValuesUnit, P013_MEASURINGUNIT); + const FormSelectorOptions selector(optionCount, optionsUnit, optionValuesUnit); + selector.addFormSelector(F("Unit"), F("pUnit"), P013_MEASURINGUNIT); } { @@ -165,7 +167,8 @@ boolean Plugin_013(uint8_t function, struct EventStruct *even F("Median"), }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesFilter); - addFormSelector(F("Filter"), F("fltr"), optionCount, optionsFilter, optionValuesFilter, P013_FILTERTYPE); + const FormSelectorOptions selector(optionCount, optionsFilter, optionValuesFilter); + selector.addFormSelector(F("Filter"), F("fltr"), P013_FILTERTYPE); } // enable filtersize option if filter is used, diff --git a/src/_P014_SI70xx.ino b/src/_P014_SI70xx.ino index 20aca65c4d..904148bf54 100644 --- a/src/_P014_SI70xx.ino +++ b/src/_P014_SI70xx.ino @@ -117,7 +117,8 @@ boolean Plugin_014(uint8_t function, struct EventStruct *event, String& string) SI70xx_RESOLUTION_11T_11RH, }; constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Resolution"), F("pres"), optionCount, options, optionValues, P014_RESOLUTION); + const FormSelectorOptions selector(optionCount, options, optionValues); + selector.addFormSelector(F("Resolution"), F("pres"), P014_RESOLUTION); addFormNumericBox("ADC Filter Power", F("pfilter"), P014_FILTER_POWER, 0, 4); diff --git a/src/_P015_TSL2561.ino b/src/_P015_TSL2561.ino index aed807dca1..b1ea93d6f4 100644 --- a/src/_P015_TSL2561.ino +++ b/src/_P015_TSL2561.ino @@ -97,12 +97,14 @@ boolean Plugin_015(uint8_t function, struct EventStruct *event, String& string) { { const __FlashStringHelper *options[] = { - F("13.7 ms"), - F("101 ms"), - F("402 ms"), + F("13.7"), + F("101"), + F("402"), }; constexpr size_t optionCount = NR_ELEMENTS(options); - addFormSelector(F("Integration time"), F("pintegration"), optionCount, options, nullptr, P015_INTEGRATION); + const FormSelectorOptions selector(optionCount, options); + selector.addFormSelector(F("Integration time"), F("pintegration"), P015_INTEGRATION); + addUnit(F("ms")); } addFormCheckBox(F("Send sensor to sleep:"), F("psleep"), @@ -115,14 +117,17 @@ boolean Plugin_015(uint8_t function, struct EventStruct *event, String& string) F("Auto Gain"), F("Extended Auto Gain"), }; + /* const int optionValues[] = { P015_NO_GAIN, P015_16X_GAIN, P015_AUTO_GAIN, P015_EXT_AUTO_GAIN, }; - constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Gain"), F("pgain"), optionCount, options, optionValues, P015_GAIN); + */ + constexpr size_t optionCount = NR_ELEMENTS(options); + const FormSelectorOptions selector(optionCount, options/*, optionValues*/); + selector.addFormSelector(F("Gain"), F("pgain"), P015_GAIN); } success = true; diff --git a/src/_P016_IR.ino b/src/_P016_IR.ino index df10524aa7..bda4899e81 100644 --- a/src/_P016_IR.ino +++ b/src/_P016_IR.ino @@ -427,8 +427,11 @@ boolean Plugin_016(uint8_t function, struct EventStruct *event, String& string) addHtmlInt(varNr + 1); // # html_TD(); { // Decode type - addSelector(getPluginCustomArgName(rowCnt + 0), protocolCount, &decodeTypes[0], &decodeTypeOptions[0], nullptr, - static_cast(line.CodeDecodeType), false, true, F("")); + FormSelectorOptions selector(protocolCount, &decodeTypes[0], &decodeTypeOptions[0]); + selector.clearClassName(); + selector.addSelector( + getPluginCustomArgName(rowCnt + 0), + static_cast(line.CodeDecodeType)); } html_TD(); addCheckBox(getPluginCustomArgName(rowCnt + 1), bitRead(line.CodeFlags, P16_FLAGS_REPEAT)); @@ -442,8 +445,12 @@ boolean Plugin_016(uint8_t function, struct EventStruct *event, String& string) html_TD(); { - addSelector(getPluginCustomArgName(rowCnt + 3), protocolCount, &decodeTypes[0], &decodeTypeOptions[0], nullptr, - static_cast(line.AlternativeCodeDecodeType), false, true, F("")); + FormSelectorOptions selector(protocolCount, &decodeTypes[0], &decodeTypeOptions[0]); + selector.clearClassName(); + + selector.addSelector( + getPluginCustomArgName(rowCnt + 3), + static_cast(line.AlternativeCodeDecodeType)); } html_TD(); addCheckBox(getPluginCustomArgName(rowCnt + 4), bitRead(line.AlternativeCodeFlags, P16_FLAGS_REPEAT)); diff --git a/src/_P019_PCF8574.ino b/src/_P019_PCF8574.ino index 46c204eda8..48ec2b2eb0 100644 --- a/src/_P019_PCF8574.ino +++ b/src/_P019_PCF8574.ino @@ -70,7 +70,8 @@ boolean Plugin_019(uint8_t function, struct EventStruct *event, String& string) portNames[x] += x; } addFormSelectorI2C(F("pi2c"), 16, i2cAddressValues, address); - addFormSelector(F("Port"), F("pport"), 8, portNames, portValues, port); + const FormSelectorOptions selector(8, portNames, portValues); + selector.addFormSelector(F("Port"), F("pport"), port); addFormNote(F("PCF8574 uses addresses 0x20..0x27, PCF8574A uses addresses 0x38..0x3F.")); } else { success = intArrayContains(16, i2cAddressValues, event->Par1); diff --git a/src/_P020_Ser2Net.ino b/src/_P020_Ser2Net.ino index 70d58e0465..fc38b4d4f4 100644 --- a/src/_P020_Ser2Net.ino +++ b/src/_P020_Ser2Net.ino @@ -192,16 +192,20 @@ boolean Plugin_020(uint8_t function, struct EventStruct *event, String& string) F("RFLink"), F("P1 WiFi Gateway") }; +/* const int optionValues[] = { static_cast(P020_Events::None), static_cast(P020_Events::Generic), static_cast(P020_Events::RFLink), static_cast(P020_Events::P1WiFiGateway), }; - constexpr int optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Event processing"), F("pevents"), - optionCount, options, optionValues, - P020_SERIAL_PROCESSING); +*/ + constexpr int optionCount = NR_ELEMENTS(options); + const FormSelectorOptions selector(optionCount, options /*, optionValues*/); + selector.addFormSelector( + F("Event processing"), + F("pevents"), + P020_SERIAL_PROCESSING); } addFormCheckBox(F("P1 #data event with message"), F("pp1event"), P020_GET_P1_EVENT_DATA); # ifndef LIMIT_BUILD_SIZE diff --git a/src/_P021_Level.ino b/src/_P021_Level.ino index 942bd4d829..8a9a45ec14 100644 --- a/src/_P021_Level.ino +++ b/src/_P021_Level.ino @@ -234,10 +234,13 @@ boolean Plugin_021(uint8_t function, struct EventStruct *event, String& string) // FormSelector with all operation mode options const __FlashStringHelper *options[] = { F("Classic"), F("Off"), F("Standby"), F("On"), F("Local"), F("Remote") }; + /* const int optionValues[] = { P021_OPMODE_CLASSIC, P021_OPMODE_OFF, P021_OPMODE_STANDBY, P021_OPMODE_ON, P021_OPMODE_TEMP, P021_OPMODE_REMOTE }; - constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Control mode"), F(P021_GUID_OPMODE), optionCount, options, optionValues, P021_OPMODE); + */ + constexpr size_t optionCount = NR_ELEMENTS(options); + const FormSelectorOptions selector(optionCount, options/*, optionValues*/); + selector.addFormSelector(F("Control mode"), F(P021_GUID_OPMODE), P021_OPMODE); // Add timer values depending on build size // - minimum build size: units are always in seconds; drop the units on the form diff --git a/src/_P022_PCA9685.ino b/src/_P022_PCA9685.ino index 14af526a3d..206e16e343 100644 --- a/src/_P022_PCA9685.ino +++ b/src/_P022_PCA9685.ino @@ -109,18 +109,16 @@ boolean Plugin_022(uint8_t function, struct EventStruct *event, String& string) // To prevent stack overflow issues, each selection has its own scope. { String m2Options[PCA9685_MODE2_VALUES]; - int m2Values[PCA9685_MODE2_VALUES]; + //int m2Values[PCA9685_MODE2_VALUES]; for (int i = 0; i < PCA9685_MODE2_VALUES; ++i) { - m2Values[i] = i; + //m2Values[i] = i; m2Options[i] = formatToHex_decimal(i); - - if (i == 0x10) { - m2Options[i] += F(" - (default)"); - } } - addFormSelector(F("MODE2"), F("pmode2"), PCA9685_MODE2_VALUES, m2Options, m2Values, mode2); + FormSelectorOptions selector(PCA9685_MODE2_VALUES, m2Options/*, m2Values*/); + selector.default_index = 0x10; + selector.addFormSelector(F("MODE2"), F("pmode2"), mode2); } addFormNumericBox( strformat(F("Frequency (%d-%d)"), PCA9685_MIN_FREQUENCY, PCA9685_MAX_FREQUENCY), diff --git a/src/_P023_OLED.ino b/src/_P023_OLED.ino index 5c192ca020..eae8fb7bee 100644 --- a/src/_P023_OLED.ino +++ b/src/_P023_OLED.ino @@ -106,7 +106,8 @@ boolean Plugin_023(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *options4[] = { F("Normal"), F("Optimized") }; const int optionValues4[] = { 1, 2 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues4); - addFormSelector(F("Font Width"), F("font_spacing"), optionCount, options4, optionValues4, PCONFIG(4)); + const FormSelectorOptions selector(optionCount, options4, optionValues4); + selector.addFormSelector(F("Font Width"), F("font_spacing"), PCONFIG(4)); } { String strings[P23_Nlines]; diff --git a/src/_P024_MLX90614.ino b/src/_P024_MLX90614.ino index 10fc1dfd09..efc29ed7f8 100644 --- a/src/_P024_MLX90614.ino +++ b/src/_P024_MLX90614.ino @@ -81,7 +81,8 @@ boolean Plugin_024(uint8_t function, struct EventStruct *event, String& string) (0x06) }; constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Option"), F("option"), optionCount, options, optionValues, PCONFIG(0)); + const FormSelectorOptions selector(optionCount, options, optionValues); + selector.addFormSelector(F("Option"), F("option"), PCONFIG(0)); success = true; break; diff --git a/src/_P027_INA219.ino b/src/_P027_INA219.ino index 1aca517611..2c56a4bd70 100644 --- a/src/_P027_INA219.ino +++ b/src/_P027_INA219.ino @@ -132,11 +132,13 @@ boolean Plugin_027(uint8_t function, struct EventStruct *event, String& string) { { const __FlashStringHelper *optionsMode[] = { F("32V, 2A"), F("32V, 1A"), F("16V, 0.4A"), F("26V, 8A") }; - addFormSelector(F("Measure range"), F("range"), 4, optionsMode, nullptr, PCONFIG(0)); + const FormSelectorOptions selector(NR_ELEMENTS(optionsMode), optionsMode); + selector.addFormSelector(F("Measure range"), F("range"), PCONFIG(0)); } { const __FlashStringHelper *options[] = { F("Voltage"), F("Current"), F("Power"), F("Voltage/Current/Power") }; - addFormSelector(F("Measurement Type"), F("measuretype"), 4, options, nullptr, PCONFIG(2)); + const FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.addFormSelector(F("Measurement Type"), F("measuretype"), PCONFIG(2)); } # if P027_FEATURE_POWERDOWN addFormCheckBox(F("Use Powerdown mode"), F("pwrdwn"), PCONFIG(3) == 1); diff --git a/src/_P028_BME280.ino b/src/_P028_BME280.ino index 61dabdab43..34532f21c4 100644 --- a/src/_P028_BME280.ino +++ b/src/_P028_BME280.ino @@ -190,7 +190,8 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string) static_cast(P028_data_struct::BMx_DetectMode::BME280), static_cast(P028_data_struct::BMx_DetectMode::BMP280), }; - addFormSelector(F("Output values mode"), F("det"), 2, detectOptionList, detectOptions, P028_DETECTION_MODE); + const FormSelectorOptions selector(NR_ELEMENTS(detectOptionList), detectOptionList, detectOptions); + selector.addFormSelector(F("Output values mode"), F("det"), P028_DETECTION_MODE); success = true; } @@ -253,11 +254,11 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string) # endif // ifndef LIMIT_BUILD_SIZE }; constexpr int P028_ERROR_STATE_COUNT = NR_ELEMENTS(resultsOptions); - addFormSelector(F("Temperature Error Value"), - F("err"), - P028_ERROR_STATE_COUNT, - resultsOptions, - resultsOptionValues, + const FormSelectorOptions selector( + P028_ERROR_STATE_COUNT, + resultsOptions, + resultsOptionValues); + selector.addFormSelector(F("Temperature Error Value"), F("err"), P028_ERROR_STATE_OUTPUT); break; diff --git a/src/_P036_FrameOLED.ino b/src/_P036_FrameOLED.ino index 16eafa20c9..6070a33377 100644 --- a/src/_P036_FrameOLED.ino +++ b/src/_P036_FrameOLED.ino @@ -348,7 +348,8 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string) # endif // if P036_ENABLE_TICKER }; constexpr int optionCnt = NR_ELEMENTS(optionValues); - addFormSelector(F("Scroll"), F("scroll"), optionCnt, options, optionValues, P036_SCROLL); + const FormSelectorOptions selector(optionCnt, options, optionValues); + selector.addFormSelector(F("Scroll"), F("scroll"), P036_SCROLL); } // FIXME TD-er: Why is this using pin3 and not pin1? And why isn't this using the normal pin selection functions? @@ -359,7 +360,8 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string) const int optionValues[] = { static_cast(eP036pinmode::ePPM_Input), static_cast(eP036pinmode::ePPM_InputPullUp) }; - addFormSelector(F("Pin mode"), F("pinmode"), 2, options, optionValues, + const FormSelectorOptions selector(NR_ELEMENTS(options), options, optionValues); + selector.addFormSelector(F("Pin mode"), F("pinmode"), bitRead(P036_FLAGS_0, P036_FLAG_INPUT_PULLUP)); // Bit 26 Input PullUp } @@ -388,7 +390,8 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string) F("Display, Contrast, Frame, Line & Linecount") }; const int optionValues[] = { 0, 1, 3 }; // Bitmap - addFormSelector(F("Generate events"), F("generateEvents"), 3, options, optionValues, choice); + const FormSelectorOptions selector(NR_ELEMENTS(options), options, optionValues); + selector.addFormSelector(F("Generate events"), F("generateEvents"), choice); # ifndef P036_LIMIT_BUILD_SIZE addFormNote(F("Events: <taskname> #display=1/0 (on/off), #contrast=0/1/2 (low/med/high),")); @@ -442,10 +445,15 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string) # endif // if P036_USERDEF_HEADERS }; constexpr int nrOptions9 = NR_ELEMENTS(options9); - addFormSelector(F("Header"), F("header"), nrOptions9, options9, optionValues9, - get8BitFromUL(P036_FLAGS_0, P036_FLAG_HEADER)); // HeaderContent - addFormSelector(F("Header (alternate)"), F("headerAlternate"), nrOptions9, options9, optionValues9, - get8BitFromUL(P036_FLAGS_0, P036_FLAG_HEADER_ALTERNATIVE)); // HeaderContentAlternative + const FormSelectorOptions selector(nrOptions9, options9, optionValues9); + // HeaderContent + selector.addFormSelector( + F("Header"), F("header"), + get8BitFromUL(P036_FLAGS_0, P036_FLAG_HEADER)); + // HeaderContentAlternative + selector.addFormSelector( + F("Header (alternate)"), F("headerAlternate"), + get8BitFromUL(P036_FLAGS_0, P036_FLAG_HEADER_ALTERNATIVE)); } # if P036_ENABLE_TIME_FORMAT { @@ -460,7 +468,8 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string) F("HH:MM:SS (am/pm)"), F("HH:MM (am/pm)"), }; - addFormSelector(F("Header Time format"), F("timeFmt"), NR_ELEMENTS(options), options, nullptr, + const FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.addFormSelector(F("Header Time format"), F("timeFmt"), get4BitFromUL(P036_FLAGS_1, P036_FLAG_TIME_FORMAT)); } # endif // if P036_ENABLE_TIME_FORMAT @@ -483,7 +492,8 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string) static_cast(eAlignment::eCenter), static_cast(eAlignment::eRight) }; - addFormSelector(F("Align content (global)"), F("LeftAlign"), 3, optionsAlignment, optionValuesAlignment, + const FormSelectorOptions selector( NR_ELEMENTS(optionValuesAlignment), optionsAlignment, optionValuesAlignment); + selector.addFormSelector(F("Align content (global)"), F("LeftAlign"), get2BitFromUL(P036_FLAGS_1, P036_FLAG_LEFT_ALIGNED)); } # endif // if P036_ENABLE_LEFT_ALIGN @@ -542,36 +552,36 @@ boolean Plugin_036(uint8_t function, struct EventStruct *event, String& string) addTextBox(getPluginCustomArgName(varNr), P036_lines.DisplayLinesV1[varNr].Content, P36_NcharsV1 - 1, - false, // readonly, - false, // required, - EMPTY_STRING, // pattern, F("xwide") // class name ); - html_TD(); // font - const uint8_t FontChoice = get3BitFromUL(P036_lines.DisplayLinesV1[varNr].ModifyLayout, P036_FLAG_ModifyLayout_Font); - addSelector(getPluginCustomArgName(varNr + 100), - 5, - optionsFont, - optionValuesFont, - nullptr, // attr[], - FontChoice, // selectedIndex, - false, // reloadonchange, - true, // enabled, - F("") // class name - ); - html_TD(); // alignment - const uint8_t AlignmentChoice = get3BitFromUL(P036_lines.DisplayLinesV1[varNr].ModifyLayout, - P036_FLAG_ModifyLayout_Alignment); - addSelector(getPluginCustomArgName(varNr + 200), - 4, - optionsAlignment, - optionValuesAlignment, - nullptr, // attr[], - AlignmentChoice, // selectedIndex, - false, // reloadonchange, - true, // enabled, - F("") // class name - ); + { + html_TD(); // font + + FormSelectorOptions selector( + 5, + optionsFont, + optionValuesFont); + selector.clearClassName(); + + const uint8_t FontChoice = get3BitFromUL(P036_lines.DisplayLinesV1[varNr].ModifyLayout, P036_FLAG_ModifyLayout_Font); + selector.addSelector( + getPluginCustomArgName(varNr + 100), + FontChoice); // selectedIndex, + } + { + html_TD(); // alignment + FormSelectorOptions selector( + 4, + optionsAlignment, + optionValuesAlignment); + selector.clearClassName(); + + const uint8_t AlignmentChoice = get3BitFromUL(P036_lines.DisplayLinesV1[varNr].ModifyLayout, + P036_FLAG_ModifyLayout_Alignment); + selector.addSelector( + getPluginCustomArgName(varNr + 200), + AlignmentChoice); // selectedIndex, + } } html_end_table(); } diff --git a/src/_P038_NeoPixel.ino b/src/_P038_NeoPixel.ino index d775f39bed..b4b9a7f65a 100644 --- a/src/_P038_NeoPixel.ino +++ b/src/_P038_NeoPixel.ino @@ -96,7 +96,8 @@ boolean Plugin_038(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *options[] = { F("GRB"), F("GRBW") }; int indices[] = { P038_STRIP_TYPE_RGB, P038_STRIP_TYPE_RGBW }; - addFormSelector(F("Strip Type"), F("pstrip"), 2, options, indices, P038_CONFIG_STRIPTYPE); + const FormSelectorOptions selector(NR_ELEMENTS(options), options, indices); + selector.addFormSelector(F("Strip Type"), F("pstrip"), P038_CONFIG_STRIPTYPE); } if (P038_CONFIG_BRIGHTNESS == 0) { P038_CONFIG_BRIGHTNESS = 255; } diff --git a/src/_P039_Thermosensors.ino b/src/_P039_Thermosensors.ino index a016f68d07..367e4a8668 100644 --- a/src/_P039_Thermosensors.ino +++ b/src/_P039_Thermosensors.ino @@ -434,7 +434,9 @@ boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *Foptions[] = { F("Thermocouple"), F("RTD") }; const int FoptionValues[] = { P039_TC, P039_RTD }; constexpr size_t optionCount = NR_ELEMENTS(FoptionValues); - addFormSelector(F("Sensor Family Type"), F("famtype"), optionCount, Foptions, FoptionValues, family, true); // auto reload activated + FormSelectorOptions selector( optionCount, Foptions, FoptionValues); + selector.reloadonchange = true; + selector.addFormSelector(F("Sensor Family Type"), F("famtype"), family); } const uint8_t choice = P039_MAX_TYPE; @@ -446,7 +448,9 @@ boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *options[] = { F("MAX 6675"), F("MAX 31855"), F("MAX 31856") }; const int optionValues[] = { P039_MAX6675, P039_MAX31855, P039_MAX31856 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Adapter IC"), F("maxtype"), optionCount, options, optionValues, choice, true); // auto reload activated + FormSelectorOptions selector( optionCount, options, optionValues); + selector.reloadonchange = true; + selector.addFormSelector(F("Adapter IC"), F("maxtype"), choice); } if (choice == P039_MAX31856) { @@ -472,13 +476,15 @@ boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) const int ToptionValues[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12 }; constexpr size_t optionCount = NR_ELEMENTS(ToptionValues); - addFormSelector(F("Thermocouple type"), F("tctype"), optionCount, Toptions, ToptionValues, P039_TC_TYPE); + const FormSelectorOptions selector( optionCount, Toptions, ToptionValues); + selector.addFormSelector(F("Thermocouple type"), F("tctype"), P039_TC_TYPE); } { const __FlashStringHelper *Coptions[] = { F("1"), F("2"), F("4"), F("8"), F("16") }; const int CoptionValues[] = { 0, 1, 2, 3, 4 }; constexpr size_t optionCount = NR_ELEMENTS(CoptionValues); - addFormSelector(F("Averaging"), F("contype"), optionCount, Coptions, CoptionValues, P039_CONFIG_4); + const FormSelectorOptions selector(optionCount, Coptions, CoptionValues); + selector.addFormSelector(F("Averaging"), F("contype"), P039_CONFIG_4); addUnit(F("sample(s)")); } P039_AddMainsFrequencyFilterSelection(event); @@ -489,7 +495,9 @@ boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *TPoptions[] = { F("MAX 31865"), F("LM7x") }; const int TPoptionValues[] = { P039_MAX31865, P039_LM7x }; constexpr size_t optionCount = NR_ELEMENTS(TPoptionValues); - addFormSelector(F("Adapter IC"), F("maxtype"), optionCount, TPoptions, TPoptionValues, choice, true); // auto reload activated + FormSelectorOptions selector(optionCount, TPoptions, TPoptionValues); + selector.reloadonchange = true; + selector.addFormSelector(F("Adapter IC"), F("maxtype"), choice); addFormNote(F("LM7x support is experimental.")); } @@ -503,12 +511,14 @@ boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *PToptions[] = { F("PT100"), F("PT1000") }; const int PToptionValues[] = { MAX31865_PT100, MAX31865_PT1000 }; constexpr size_t optionCount = NR_ELEMENTS(PToptionValues); - addFormSelector(F("Resistor Type"), F("rtdtype"), optionCount, PToptions, PToptionValues, P039_RTD_TYPE); + const FormSelectorOptions selector(optionCount, PToptions, PToptionValues); + selector.addFormSelector(F("Resistor Type"), F("rtdtype"), P039_RTD_TYPE); } { const __FlashStringHelper *Coptions[] = { F("2-/4"), F("3") }; constexpr size_t optionCount = NR_ELEMENTS(Coptions); - addFormSelector(F("Connection Type"), F("contype"), optionCount, Coptions, nullptr, P039_CONFIG_4); + const FormSelectorOptions selector( optionCount, Coptions); + selector.addFormSelector(F("Connection Type"), F("contype"), P039_CONFIG_4); addUnit(F("wire")); } @@ -539,7 +549,8 @@ boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) { F("LM70"), F("LM71"), F("LM74"), F("TMP121"), F("TMP122"), F("TMP123"), F("TMP124"), F("TMP125") }; const int PToptionValues[] = { LM7x_SD70, LM7x_SD71, LM7x_SD74, LM7x_SD121, LM7x_SD122, LM7x_SD123, LM7x_SD124, LM7x_SD125 }; constexpr size_t optionCount = NR_ELEMENTS(PToptionValues); - addFormSelector(F("LM7x device details"), F("rtd_lm_type"), optionCount, PToptions, PToptionValues, P039_RTD_LM_TYPE); + const FormSelectorOptions selector(optionCount, PToptions, PToptionValues); + selector.addFormSelector(F("LM7x device details"), F("rtd_lm_type"), P039_RTD_LM_TYPE); addFormNote(F("TMP122/124 Limited support -> fixed 12 Bit res, no advanced options")); } { @@ -808,10 +819,11 @@ boolean Plugin_039(uint8_t function, struct EventStruct *event, String& string) void P039_AddMainsFrequencyFilterSelection(struct EventStruct *event) { - const __FlashStringHelper *FToptions[2] = { F("60"), F("50") }; - const int FToptionValues[2] = { 0, 1 }; + const __FlashStringHelper *FToptions[] = { F("60"), F("50") }; + const int FToptionValues[] = { 0, 1 }; - addFormSelector(F("Supply Frequency Filter"), F("filttype"), 2, FToptions, FToptionValues, P039_RTD_FILT_TYPE); + const FormSelectorOptions selector(NR_ELEMENTS(FToptions), FToptions, FToptionValues); + selector.addFormSelector(F("Supply Frequency Filter"), F("filttype"), P039_RTD_FILT_TYPE); addUnit(F("Hz")); # ifndef LIMIT_BUILD_SIZE addFormNote(F("Filter power net frequency (50/60 Hz)")); diff --git a/src/_P042_Candle.ino b/src/_P042_Candle.ino index 6cc8c62086..ae44431078 100644 --- a/src/_P042_Candle.ino +++ b/src/_P042_Candle.ino @@ -139,7 +139,7 @@ boolean Plugin_042(uint8_t function, struct EventStruct *event, String& string) addFormNumericBox(F("Led Count"), P042_WEBVAR_PIXELCOUNT, P042_CONFIG_PIXELCOUNT, 1, P042_MAX_PIXELS); { - const __FlashStringHelper *options[P042_FLAME_OPTIONS] = { + const __FlashStringHelper *options[] = { F("Off"), F("Static Light"), F("Simple Candle"), @@ -155,7 +155,8 @@ boolean Plugin_042(uint8_t function, struct EventStruct *event, String& string) } // Candle Type Selection - addFormSelector(F("Flame Type"), P042_WEBVAR_CANDLETYPE, P042_FLAME_OPTIONS, options, nullptr, P042_CONFIG_CANDLETYPE); + const FormSelectorOptions selector(P042_FLAME_OPTIONS, options); + selector.addFormSelector(F("Flame Type"), P042_WEBVAR_CANDLETYPE, P042_CONFIG_CANDLETYPE); } // Advanced Color options diff --git a/src/_P043_ClkOutput.ino b/src/_P043_ClkOutput.ino index 695c9e1c48..589e575574 100644 --- a/src/_P043_ClkOutput.ino +++ b/src/_P043_ClkOutput.ino @@ -159,15 +159,20 @@ boolean Plugin_043(uint8_t function, struct EventStruct *event, String& string) int thisDay = weekDays.indexOf(timeStr.substring(0, 3)); if (thisDay > 0) { thisDay /= 3; } - addSelector(concat(F("day"), x), daysCount, days, nullptr, nullptr, thisDay, false, true, F("")); + FormSelectorOptions selector(daysCount, days); + selector.clearClassName(); + selector.addSelector( + concat(F("day"), x), + thisDay); addHtml(','); addTextBox(concat(F("clock"), x), - parseString(timeStr, 2), 32 - , false, false, EMPTY_STRING, F("") + parseString(timeStr, 2), 32, + false, false, EMPTY_STRING, + F(""), # if FEATURE_TOOLTIPS - , EMPTY_STRING + EMPTY_STRING, # endif // if FEATURE_TOOLTIPS - , F("timepatternlist")); + F("timepatternlist")); # else // ifndef LIMIT_BUILD_SIZE addFormTextBox(concat(F("Day,Time "), x + 1), concat(F("clock"), x), @@ -177,7 +182,10 @@ boolean Plugin_043(uint8_t function, struct EventStruct *event, String& string) if (validGpio(CONFIG_PIN1) || (P043_SIMPLE_VALUE == 1)) { addHtml(' '); const uint8_t choice = Cache.getTaskDevicePluginConfig(event->TaskIndex, x); - addSelector(concat(F("state"), x), optionsCount, options, nullptr, nullptr, choice); + const FormSelectorOptions selector(optionsCount, options); + selector.addSelector( + concat(F("state"), x), + choice); } else { addHtml(strformat(F("Value %d:"), x + 1)); diff --git a/src/_P045_MPU6050.ino b/src/_P045_MPU6050.ino index b6cad82981..9b116a9040 100644 --- a/src/_P045_MPU6050.ino +++ b/src/_P045_MPU6050.ino @@ -157,7 +157,7 @@ boolean Plugin_045(uint8_t function, struct EventStruct *event, String& string) { uint8_t choice = PCONFIG(1); { - const __FlashStringHelper *options[10] = { + const __FlashStringHelper *options[] = { F("Movement detection"), F("Range acceleration X"), F("Range acceleration Y"), @@ -169,7 +169,9 @@ boolean Plugin_045(uint8_t function, struct EventStruct *event, String& string) F("G-force Y"), F("G-force Z") }; - addFormSelector(F("Function"), F("pfunction"), 10, options, nullptr, choice); + + const FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.addFormSelector(F("Function"), F("pfunction"), choice); } if (choice == 0) { diff --git a/src/_P046_VentusW266.ino b/src/_P046_VentusW266.ino index 5143597d43..99d8034bc5 100644 --- a/src/_P046_VentusW266.ino +++ b/src/_P046_VentusW266.ino @@ -161,8 +161,7 @@ boolean Plugin_046(uint8_t function, struct EventStruct *event, String& string) { uint8_t choice = PCONFIG(0); { - const uint8_t nrchoices = 9; - const __FlashStringHelper * options[nrchoices] = { + const __FlashStringHelper * options[] = { F("Main + Temp/Hygro"), F("Wind"), F("Rain"), @@ -175,7 +174,9 @@ boolean Plugin_046(uint8_t function, struct EventStruct *event, String& string) F("Unknown 3, uint8_t 19"), }; - addFormSelector(F("Plugin function"), F("p046"), nrchoices, options, nullptr, choice, true); + FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.reloadonchange = true; + selector.addFormSelector(F("Plugin function"), F("p046"), choice); addFormNote(F("Changing the function will reload this page.")); } diff --git a/src/_P047_i2c-soil-moisture-sensor.ino b/src/_P047_i2c-soil-moisture-sensor.ino index 735f7d96b9..377c114f91 100644 --- a/src/_P047_i2c-soil-moisture-sensor.ino +++ b/src/_P047_i2c-soil-moisture-sensor.ino @@ -151,7 +151,10 @@ boolean Plugin_047(uint8_t function, struct EventStruct *event, String& string) # endif // if P047_FEATURE_ADAFRUIT }; constexpr size_t P047_MODEL_OPTIONS = NR_ELEMENTS(SensorModelIds); - addFormSelector(F("Sensor model"), F("model"), P047_MODEL_OPTIONS, SensorModels, SensorModelIds, P047_MODEL, true); + FormSelectorOptions selector( P047_MODEL_OPTIONS, SensorModels, SensorModelIds); + selector.default_index = static_cast(P047_MODEL_CATNIP); + selector.reloadonchange = true; + selector.addFormSelector(F("Sensor model"), F("model"), P047_MODEL); addFormNote(F("Changing the Sensor model will reload the page.")); } diff --git a/src/_P049_MHZ19.ino b/src/_P049_MHZ19.ino index a993ca59a1..4240a26c93 100644 --- a/src/_P049_MHZ19.ino +++ b/src/_P049_MHZ19.ino @@ -92,9 +92,10 @@ boolean Plugin_049(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { { - const __FlashStringHelper *options[2] = { F("Normal"), F("ABC disabled") }; - const int optionValues[2] = { P049_ABC_enabled, P049_ABC_disabled }; - addFormSelector(F("Auto Base Calibration"), F("abcdisable"), 2, options, optionValues, PCONFIG(0)); + const __FlashStringHelper *options[] = { F("Normal"), F("ABC disabled") }; + const int optionValues[] = { P049_ABC_enabled, P049_ABC_disabled }; + const FormSelectorOptions selector(NR_ELEMENTS(options), options, optionValues); + selector.addFormSelector(F("Auto Base Calibration"), F("abcdisable"), PCONFIG(0)); } { const __FlashStringHelper *filteroptions[5] = @@ -105,7 +106,8 @@ boolean Plugin_049(uint8_t function, struct EventStruct *event, String& string) PLUGIN_049_FILTER_FAST, PLUGIN_049_FILTER_MEDIUM, PLUGIN_049_FILTER_SLOW }; - addFormSelector(F("Filter"), F("filter"), 5, filteroptions, filteroptionValues, PCONFIG(1)); + const FormSelectorOptions selector(NR_ELEMENTS(filteroptions), filteroptions, filteroptionValues); + selector.addFormSelector(F("Filter"), F("filter"), PCONFIG(1)); } P049_html_show_stats(event); diff --git a/src/_P050_TCS34725.ino b/src/_P050_TCS34725.ino index d4f6a11393..2c8d776837 100644 --- a/src/_P050_TCS34725.ino +++ b/src/_P050_TCS34725.ino @@ -114,12 +114,12 @@ boolean Plugin_050(uint8_t function, struct EventStruct *event, String& string) { { const __FlashStringHelper *optionsMode[] = { - F("2.4 ms"), - F("24 ms"), - F("50 ms"), - F("101 ms"), - F("154 ms"), - F("700 ms"), + F("2.4"), + F("24"), + F("50"), + F("101"), + F("154"), + F("700"), }; const int optionValuesMode[] = { TCS34725_INTEGRATIONTIME_2_4MS, @@ -129,7 +129,9 @@ boolean Plugin_050(uint8_t function, struct EventStruct *event, String& string) TCS34725_INTEGRATIONTIME_154MS, TCS34725_INTEGRATIONTIME_700MS, }; - addFormSelector(F("Integration Time"), F("inttime"), 6, optionsMode, optionValuesMode, PCONFIG(0)); + const FormSelectorOptions selector(NR_ELEMENTS(optionsMode), optionsMode, optionValuesMode); + selector.addFormSelector(F("Integration Time"), F("inttime"), PCONFIG(0)); + addUnit(F("ms")); } { @@ -145,7 +147,8 @@ boolean Plugin_050(uint8_t function, struct EventStruct *event, String& string) TCS34725_GAIN_16X, TCS34725_GAIN_60X, }; - addFormSelector(F("Gain"), F("gain"), 4, optionsMode2, optionValuesMode2, PCONFIG(1)); + const FormSelectorOptions selector(NR_ELEMENTS(optionsMode2), optionsMode2, optionValuesMode2); + selector.addFormSelector(F("Gain"), F("gain"), PCONFIG(1)); } addFormSubHeader(F("Output settings")); @@ -163,7 +166,8 @@ boolean Plugin_050(uint8_t function, struct EventStruct *event, String& string) // const int optionValuesRGB[P050_RGB_OPTIONS] = { 0, 1, 2, 3, 4, 5 }; constexpr size_t valueCount = NR_ELEMENTS(optionsRGB); - addFormSelector(F("Output RGB Values"), F("outputrgb"), valueCount, optionsRGB, nullptr, PCONFIG(2)); + const FormSelectorOptions selector(valueCount, optionsRGB); + selector.addFormSelector(F("Output RGB Values"), F("outputrgb"), PCONFIG(2)); # ifndef LIMIT_BUILD_SIZE addFormNote(F("For 'normalized' or 'transformed' options, the Red/Green/Blue Decimals should best be increased.")); # endif // ifndef LIMIT_BUILD_SIZE @@ -190,7 +194,8 @@ boolean Plugin_050(uint8_t function, struct EventStruct *event, String& string) // const int optionValuesOutput[P050_VALUE4_OPTIONS] = { 0, 1, 2, 3 }; constexpr size_t valueCount = NR_ELEMENTS(optionsOutput); - addFormSelector(F("Output at Values #4"), F("output4"), valueCount, optionsOutput, nullptr, PCONFIG(3)); + const FormSelectorOptions selector(valueCount, optionsOutput); + selector.addFormSelector(F("Output at Values #4"), F("output4"), PCONFIG(3)); # ifndef LIMIT_BUILD_SIZE addFormNote(F("Optionally adjust Values #4 name accordingly.")); # endif // ifndef LIMIT_BUILD_SIZE diff --git a/src/_P052_SenseAir.ino b/src/_P052_SenseAir.ino index ba018e1409..dfd4682fb0 100644 --- a/src/_P052_SenseAir.ino +++ b/src/_P052_SenseAir.ino @@ -223,8 +223,9 @@ boolean Plugin_052(uint8_t function, struct EventStruct *event, String& string) if (P052_data->readHoldingRegister(P052_HR11_MEASUREMENT_MODE, value)) { // Disable selector for now, since single measurement not yet supported. - const __FlashStringHelper *options[2] = { F("Continuous"), F("Single Measurement") }; - addFormSelector(F("Measurement Mode"), F("mode"), 2, options, nullptr, value); + const __FlashStringHelper *options[] = { F("Continuous"), F("Single Measurement") }; + const FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.addFormSelector(F("Measurement Mode"), F("mode"), value); } */ @@ -246,10 +247,10 @@ boolean Plugin_052(uint8_t function, struct EventStruct *event, String& string) // ABC functionality disabled for now, due to a bug in the firmware. // See https://github.com/letscontrolit/ESPEasy/issues/759 uint8_t choiceABCperiod = PCONFIG(4); - const __FlashStringHelper * optionsABCperiod[9] = { F("disable"), F("1 h"), F("12 h"), F("1 + const __FlashStringHelper * optionsABCperiod[] = { F("disable"), F("1 h"), F("12 h"), F("1 day"), F("2 days"), F("4 days"), F("7 days"), F("14 days"), F("30 days") }; - addFormSelector(F("ABC period"), F("ABC_period"), 9, optionsABCperiod, - nullptr, choiceABCperiod); + const FormSelectorOptions selector(NR_ELEMENTS(optionsABCperiod), optionsABCperiod); + selector.addFormSelector(F("ABC period"), F("ABC_period"), choiceABCperiod); */ diff --git a/src/_P053_PMSx003.ino b/src/_P053_PMSx003.ino index dc7abfe18b..afc49bf32b 100644 --- a/src/_P053_PMSx003.ino +++ b/src/_P053_PMSx003.ino @@ -197,19 +197,16 @@ boolean Plugin_053(uint8_t function, struct EventStruct *event, String& string) # endif // ifdef USES_P175 }; addRowLabel(F("Sensor model")); - addSelector(F("model"), - NR_ELEMENTS(unitModelOptions), - unitModels, - unitModelOptions, - nullptr, - PLUGIN_053_SENSOR_MODEL_SELECTOR, - false, - # ifdef USES_P175 - !P053_for_P175 - # else // ifdef USES_P175 - true - # endif // ifdef USES_P175 - ); + + FormSelectorOptions selector( + NR_ELEMENTS(unitModelOptions), + unitModels, + unitModelOptions); +# ifdef USES_P175 + selector.enabled = !P053_for_P175; +# endif // ifdef USES_P175 + + selector.addSelector(F("model"), PLUGIN_053_SENSOR_MODEL_SELECTOR); } addFormSubHeader(F("Output")); @@ -224,14 +221,16 @@ boolean Plugin_053(uint8_t function, struct EventStruct *event, String& string) static_cast(PMSx003_output_selection::PM2_5_TempHum_Formaldehyde), static_cast(PMSx003_output_selection::ParticlesCount_100ml_cnt0_3__cnt_2_5), static_cast(PMSx003_output_selection::ParticlesCount_100ml_cnt1_0_cnt2_5_cnt10) }; - addFormSelector(F("Output values"), - F("output"), - NR_ELEMENTS(outputOptionValues), - outputOptions, - outputOptionValues, - PLUGIN_053_OUTPUT_SELECTOR, - true); - addFormNote(F("Changing this reloads the page and updates task value names + nr decimals.")); + + FormSelectorOptions selector( + NR_ELEMENTS(outputOptionValues), + outputOptions, + outputOptionValues); + selector.reloadonchange = true; + selector.addFormSelector( + F("Output values"), + F("output"), + PLUGIN_053_OUTPUT_SELECTOR); } { const __FlashStringHelper *eventOptions[] = { @@ -244,12 +243,14 @@ boolean Plugin_053(uint8_t function, struct EventStruct *event, String& string) static_cast(PMSx003_event_datatype::Event_PMxx_TempHum_Formaldehyde), static_cast(PMSx003_event_datatype::Event_All_count_bins), static_cast(PMSx003_event_datatype::Event_All) }; - addFormSelector(F("Events for non-output values"), - F("events"), - NR_ELEMENTS(eventOptionValues), - eventOptions, - eventOptionValues, - PLUGIN_053_EVENT_OUT_SELECTOR); + const FormSelectorOptions selector( + NR_ELEMENTS(eventOptionValues), + eventOptions, + eventOptionValues); + selector.addFormSelector( + F("Events for non-output values"), + F("events"), + PLUGIN_053_EVENT_OUT_SELECTOR); addFormNote(F("Only generates the 'missing' events, " "(taskname#temp/humi/hcho, " "taskname#pm1.0/pm2.5/pm10, " diff --git a/src/_P057_HT16K33_LED.ino b/src/_P057_HT16K33_LED.ino index 4500296195..2773e1e0b1 100644 --- a/src/_P057_HT16K33_LED.ino +++ b/src/_P057_HT16K33_LED.ino @@ -125,8 +125,9 @@ boolean Plugin_057(uint8_t function, struct EventStruct *event, String& string) addFormSubHeader(F("7-Seg. Clock")); { - const __FlashStringHelper *options[3] = { F("none"), F("7-Seg. HH:MM (24 hour)"), F("7-Seg. HH:MM (12 hour)") }; - addFormSelector(F("Clock Type"), F("clocktype"), 3, options, nullptr, PCONFIG(1)); + const __FlashStringHelper *options[] = { F("none"), F("7-Seg. HH:MM (24 hour)"), F("7-Seg. HH:MM (12 hour)") }; + const FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.addFormSelector(F("Clock Type"), F("clocktype"), PCONFIG(1)); } addFormNumericBox(F("Seg. for Xx:xx"), F("csh10"), PCONFIG(2), 0, 7); diff --git a/src/_P059_Encoder.ino b/src/_P059_Encoder.ino index f05ae91980..debb0c98e0 100644 --- a/src/_P059_Encoder.ino +++ b/src/_P059_Encoder.ino @@ -77,10 +77,10 @@ boolean Plugin_059(uint8_t function, struct EventStruct *event, String& string) } { - const __FlashStringHelper *options[] = { F("1"), F("2"), F("4") }; const int optionValues[] = { 1, 2, 4 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Mode"), F("mode"), optionCount, options, optionValues, PCONFIG(0)); + const FormSelectorOptions selector(optionCount, optionValues); + selector.addFormSelector(F("Mode"), F("mode"), PCONFIG(0)); addUnit(F("pulses per cycle")); } diff --git a/src/_P061_KeyPad.ino b/src/_P061_KeyPad.ino index 541366ba13..cc386777a0 100644 --- a/src/_P061_KeyPad.ino +++ b/src/_P061_KeyPad.ino @@ -154,7 +154,8 @@ boolean Plugin_061(uint8_t function, struct EventStruct *event, String& string) # endif // ifdef P061_ENABLE_PCF8575 }; constexpr int optionsCount = NR_ELEMENTS(options); - addFormSelector(F("Chip (Mode)"), F("chip"), optionsCount, options, nullptr, P061_CONFIG_KEYPAD_TYPE); + const FormSelectorOptions selector(optionsCount, options); + selector.addFormSelector(F("Chip (Mode)"), F("chip"), P061_CONFIG_KEYPAD_TYPE); success = true; break; diff --git a/src/_P062_MPR121_KeyPad.ino b/src/_P062_MPR121_KeyPad.ino index 8de0cffbb5..9339866356 100644 --- a/src/_P062_MPR121_KeyPad.ino +++ b/src/_P062_MPR121_KeyPad.ino @@ -124,7 +124,8 @@ boolean Plugin_062(uint8_t function, struct EventStruct *event, String& string) MPR212_EXTRA_SENSITIVITY }; constexpr size_t optionCount = NR_ELEMENTS(sensitivityValues); - addFormSelector(F("Panel sensitivity"), F("psens"), optionCount, sensitivityOptions, sensitivityValues, PCONFIG(4)); + const FormSelectorOptions selector(optionCount, sensitivityOptions, sensitivityValues); + selector.addFormSelector(F("Panel sensitivity"), F("psens"), PCONFIG(4)); } { bool canCalibrate = true; diff --git a/src/_P064_APDS9960.ino b/src/_P064_APDS9960.ino index 61d0fc33c5..6c5d92d2ab 100644 --- a/src/_P064_APDS9960.ino +++ b/src/_P064_APDS9960.ino @@ -129,7 +129,9 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string) F("R/G/B Colors") }; const int optionsPluginModeValues[] = { PLUGIN_MODE_GPL_064, PLUGIN_MODE_RGB_064 }; constexpr size_t optionCount = NR_ELEMENTS(optionsPluginModeValues); - addFormSelector(F("Plugin Mode"), F("mode"), optionCount, optionsPluginMode, optionsPluginModeValues, P064_MODE, true); + FormSelectorOptions selector(optionCount, optionsPluginMode, optionsPluginModeValues); + selector.reloadonchange = true; + selector.addFormSelector(F("Plugin Mode"), F("mode"), P064_MODE); # ifndef BUILD_NO_DEBUG addFormNote(F("After changing Plugin Mode you may want to change the Values names, below.")); # endif // ifndef BUILD_NO_DEBUG @@ -168,60 +170,76 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *optionsGain[] = { F("1x"), F("2x"), - F("4x (default)"), + F("4x"), F("8x") }; const int optionsGainValues[] = { PGAIN_1X, PGAIN_2X, PGAIN_4X, PGAIN_8X }; // Also used for optionsALSGain constexpr size_t optionsGainCount = NR_ELEMENTS(optionsGainValues); + constexpr int optionsGain_default_index = PGAIN_4X; // Led_Drive options, all Led_Drive optionsets in SparkFun_APDS9960.h have the same valueset, so only defined once here const __FlashStringHelper *optionsLedDrive[] = { - F("100 mA (default)"), - F("50 mA"), - F("25 mA"), - F("12.5 mA") }; + F("100"), + F("50"), + F("25"), + F("12.5") }; const int optionsLedDriveValues[] = { LED_DRIVE_100MA, LED_DRIVE_50MA, LED_DRIVE_25MA, LED_DRIVE_12_5MA }; constexpr size_t optionsLedDriveCount = NR_ELEMENTS(optionsLedDriveValues); - + constexpr int optionsLedDrive_default_index = LED_DRIVE_100MA; String lightSensorGainLabel; String lightSensorDriveLabel; if (P064_IS_GPL_SENSOR) { // Gesture/Proximity/ALS mode addFormSubHeader(F("Gesture parameters")); - - addFormSelector(F("Gesture Gain"), - F("ggain"), - optionsGainCount, - optionsGain, - optionsGainValues, - P064_GGAIN); - - addFormSelector(F("Gesture LED Drive"), - F("gldrive"), - optionsLedDriveCount, - optionsLedDrive, - optionsLedDriveValues, - P064_GLDRIVE); + { + FormSelectorOptions selector( + optionsGainCount, + optionsGain, + optionsGainValues); + selector.default_index = optionsGain_default_index; + selector.addFormSelector( + F("Gesture Gain"), + F("ggain"), + P064_GGAIN); + } + { + FormSelectorOptions selector( + optionsLedDriveCount, + optionsLedDrive, + optionsLedDriveValues); + selector.default_index = optionsLedDrive_default_index; + selector.addFormSelector( + F("Gesture LED Drive"), + F("gldrive"), + P064_GLDRIVE); + addUnit(F("mA")); + } { // Gesture Led-boost values const __FlashStringHelper *optionsLedBoost[] = { - F("100 %"), - F("150 %"), - F("200 %"), - F("300 % (default)") }; + F("100"), + F("150"), + F("200"), + F("300") }; const int optionsLedBoostValues[] = { LED_BOOST_100, LED_BOOST_150, LED_BOOST_200, LED_BOOST_300 }; constexpr size_t optionsLedBoostCount = NR_ELEMENTS(optionsLedBoostValues); - addFormSelector(F("Gesture LED Boost"), - F("lboost"), - optionsLedBoostCount, - optionsLedBoost, - optionsLedBoostValues, - P064_LED_BOOST); + FormSelectorOptions selector( + optionsLedBoostCount, + optionsLedBoost, + optionsLedBoostValues); + selector.default_index = LED_BOOST_300; + selector.addFormSelector( + F("Gesture LED Boost"), + F("lboost"), + P064_LED_BOOST); + addUnit('%'); } addFormSubHeader(F("Proximity & Ambient Light Sensor parameters")); - - addFormSelector(F("Proximity Gain"), F("pgain"), optionsGainCount, optionsGain, optionsGainValues, P064_PGAIN); + { + const FormSelectorOptions selector(optionsGainCount, optionsGain, optionsGainValues); + selector.addFormSelector(F("Proximity Gain"), F("pgain"), P064_PGAIN); + } lightSensorGainLabel = F("Ambient Light Sensor Gain"); lightSensorDriveLabel = F("Proximity & ALS LED Drive"); @@ -235,17 +253,24 @@ boolean Plugin_064(uint8_t function, struct EventStruct *event, String& string) // Ambient Light Sensor Gain options, values are equal to PGAIN values, so again avoid duplication const __FlashStringHelper *optionsALSGain[] = { F("1x"), - F("4x (default)"), + F("4x"), F("16x"), F("64x") }; - addFormSelector(lightSensorGainLabel, F("again"), optionsGainCount, optionsALSGain, optionsGainValues, P064_AGAIN); + FormSelectorOptions selector(optionsGainCount, optionsALSGain, optionsGainValues); + selector.default_index = 1; // 4x + selector.addFormSelector(lightSensorGainLabel, F("again"), P064_AGAIN); + } + { + const FormSelectorOptions selector( + optionsLedDriveCount, + optionsLedDrive, + optionsLedDriveValues); + selector.addFormSelector( + lightSensorDriveLabel, + F("ldrive"), + P064_LDRIVE); + addUnit(F("mA")); } - addFormSelector(lightSensorDriveLabel, - F("ldrive"), - optionsLedDriveCount, - optionsLedDrive, - optionsLedDriveValues, - P064_LDRIVE); } addFormSubHeader(F("Event generation")); diff --git a/src/_P066_VEML6040.ino b/src/_P066_VEML6040.ino index 082a73bf8f..339c81644b 100644 --- a/src/_P066_VEML6040.ino +++ b/src/_P066_VEML6040.ino @@ -93,7 +93,8 @@ boolean Plugin_066(uint8_t function, struct EventStruct *event, String& string) F("1280ms (515)"), }; constexpr size_t optionCount = NR_ELEMENTS(optionsMode); - addFormSelector(F("Integration Time (Max Lux)"), F("itime"), optionCount, optionsMode, nullptr, PCONFIG(1)); + const FormSelectorOptions selector(optionCount, optionsMode); + selector.addFormSelector(F("Integration Time (Max Lux)"), F("itime"), PCONFIG(1)); } { @@ -106,7 +107,8 @@ boolean Plugin_066(uint8_t function, struct EventStruct *event, String& string) F("Color Temperature [K], Ambient Light [Lux], Y, W"), }; constexpr size_t optionCount = NR_ELEMENTS(optionsVarMap); - addFormSelector(F("Value Mapping"), F("map"), optionCount, optionsVarMap, nullptr, PCONFIG(2)); + const FormSelectorOptions selector(optionCount, optionsVarMap); + selector.addFormSelector(F("Value Mapping"), F("map"), PCONFIG(2)); } success = true; diff --git a/src/_P067_HX711_Load_Cell.ino b/src/_P067_HX711_Load_Cell.ino index 1321ec4f44..64548e4b77 100644 --- a/src/_P067_HX711_Load_Cell.ino +++ b/src/_P067_HX711_Load_Cell.ino @@ -86,7 +86,8 @@ boolean Plugin_067(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *optionsModeChanA[] = { F("Off"), F("Gain 64"), F("Gain 128") }; - addFormSelector(F("Mode"), F("modeChA"), 3, optionsModeChanA, nullptr, P067_GET_CHANNEL_A_MODE); + const FormSelectorOptions selector(NR_ELEMENTS(optionsModeChanA), optionsModeChanA); + selector.addFormSelector(F("Mode"), F("modeChA"), P067_GET_CHANNEL_A_MODE); } P067_int2float(P067_OFFSET_CHANNEL_A_1, P067_OFFSET_CHANNEL_A_2, &valFloat); @@ -101,7 +102,8 @@ boolean Plugin_067(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *optionsModeChanB[] = { F("Off"), F("Gain 32") }; - addFormSelector(F("Mode"), F("modeChB"), 2, optionsModeChanB, nullptr, P067_GET_CHANNEL_B_MODE); + const FormSelectorOptions selector(NR_ELEMENTS(optionsModeChanB), optionsModeChanB); + selector.addFormSelector(F("Mode"), F("modeChB"), P067_GET_CHANNEL_B_MODE); } P067_int2float(P067_OFFSET_CHANNEL_B_1, P067_OFFSET_CHANNEL_B_2, &valFloat); diff --git a/src/_P073_7DGT.ino b/src/_P073_7DGT.ino index b96abca7c5..53c221cda1 100644 --- a/src/_P073_7DGT.ino +++ b/src/_P073_7DGT.ino @@ -119,7 +119,8 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) F("TM1637 - 6 digit"), F("MAX7219 - 8 digit") }; constexpr size_t optionCount = NR_ELEMENTS(displtype); - addFormSelector(F("Display Type"), F("displtype"), optionCount, displtype, nullptr, PCONFIG(0)); + const FormSelectorOptions selector(optionCount, displtype); + selector.addFormSelector(F("Display Type"), F("displtype"), PCONFIG(0)); } { const __FlashStringHelper *displout[] = { F("Manual"), @@ -129,7 +130,8 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) F("Clock 12h - No Blink"), F("Date") }; constexpr size_t optionCount = NR_ELEMENTS(displout); - addFormSelector(F("Display Output"), F("displout"), optionCount, displout, nullptr, PCONFIG(1)); + const FormSelectorOptions selector(optionCount, displout); + selector.addFormSelector(F("Display Output"), F("displout"), PCONFIG(1)); } addFormNumericBox(F("Brightness"), F("brightness"), PCONFIG(2), 0, 15); @@ -142,7 +144,8 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) F("Siekoo with uppercase 'CHNORUX'"), F("dSEG7") }; constexpr size_t optionCount = NR_ELEMENTS(fontset); - addFormSelector(F("Font set"), F("fontset"), optionCount, fontset, nullptr, PCONFIG(4)); + const FormSelectorOptions selector(optionCount, fontset); + selector.addFormSelector(F("Font set"), F("fontset"), PCONFIG(4)); addFormNote(F("Check documentation for examples of the font sets.")); } # endif // P073_EXTRA_FONTS diff --git a/src/_P074_TSL2591.ino b/src/_P074_TSL2591.ino index ef373e10c4..e03d669f9a 100644 --- a/src/_P074_TSL2591.ino +++ b/src/_P074_TSL2591.ino @@ -94,11 +94,11 @@ boolean Plugin_074(uint8_t function, struct EventStruct *event, String& string) // integration time (dim light) // } { - const __FlashStringHelper *optionsMode[6] = { F("100"), F("200"), F("300"), + const __FlashStringHelper *optionsMode[] = { F("100"), F("200"), F("300"), F("400"), F("500"), F("600") }; constexpr size_t optionCount = NR_ELEMENTS(optionsMode); - addFormSelector(F("Integration Time"), F("itime"), optionCount, optionsMode, - nullptr, PCONFIG(1)); + const FormSelectorOptions selector( optionCount, optionsMode); + selector.addFormSelector(F("Integration Time"), F("itime"), PCONFIG(1)); addUnit(F("ms")); } @@ -107,11 +107,11 @@ boolean Plugin_074(uint8_t function, struct EventStruct *event, String& string) // TSL2591_GAIN_HIGH = 0x20, // medium gain (428x) // TSL2591_GAIN_MAX = 0x30, // max gain (9876x) { - const __FlashStringHelper *optionsGain[4] = { F("low gain (1x)"), F("medium gain (25x)"), + const __FlashStringHelper *optionsGain[] = { F("low gain (1x)"), F("medium gain (25x)"), F("medium gain (428x)"), F("max gain (9876x)") }; constexpr size_t optionCount = NR_ELEMENTS(optionsGain); - addFormSelector(F("Value Mapping"), F("gain"), optionCount, optionsGain, nullptr, - PCONFIG(2)); + const FormSelectorOptions selector( optionCount, optionsGain); + selector.addFormSelector(F("Value Mapping"), F("gain"), PCONFIG(2)); } success = true; diff --git a/src/_P075_Nextion.ino b/src/_P075_Nextion.ino index f1e3789786..9e7d5b6b34 100644 --- a/src/_P075_Nextion.ino +++ b/src/_P075_Nextion.ino @@ -97,7 +97,8 @@ boolean Plugin_075(uint8_t function, struct EventStruct *event, String& string) }; constexpr size_t optionCount = NR_ELEMENTS(options); - addFormSelector(F("Baud Rate"), F("baud"), optionCount, options, nullptr, P075_BaudRate); + const FormSelectorOptions selector(optionCount, options); + selector.addFormSelector(F("Baud Rate"), F("baud"), P075_BaudRate); addUnit(F("baud")); break; } diff --git a/src/_P076_HLW8012.ino b/src/_P076_HLW8012.ino index 938e5a05c1..47e58d146e 100644 --- a/src/_P076_HLW8012.ino +++ b/src/_P076_HLW8012.ino @@ -333,38 +333,13 @@ boolean Plugin_076(uint8_t function, struct EventStruct *event, String &string) #endif // ifdef ESP32 }; constexpr int nrElements = NR_ELEMENTS(predefinedId); - addFormSelector(F("Device"), - F("preDefDevSel"), nrElements, - predefinedNames, predefinedId, devicePinSettings); + const FormSelectorOptions selector(nrElements, predefinedNames, predefinedId); + selector.addFormSelector(F("Device"), F("preDefDevSel"), devicePinSettings); addFormNote(F("Enable device and select device type first")); } { // Place this in a scope, to keep memory usage low. - const __FlashStringHelper *modeRaise[] = { - F("LOW"), - F("CHANGE"), - F("RISING"), - F("FALLING"), - }; - - const int modeValues[] = { - LOW, - CHANGE, - RISING, - FALLING, - }; - - const __FlashStringHelper *modeCurr[] = { - F("LOW"), - F("HIGH"), - }; - - const int modeCurrValues[] = { - LOW, - HIGH, - }; - uint8_t currentRead = P076_SEL_CUR_READ; if ((currentRead != LOW) && (currentRead != HIGH)) @@ -372,12 +347,39 @@ boolean Plugin_076(uint8_t function, struct EventStruct *event, String &string) currentRead = LOW; } addFormSubHeader(F("Custom Pin settings (choose Custom above)")); - addFormSelector(F("SEL Current (A) Reading"), F("curr_read"), 2, - modeCurr, modeCurrValues, currentRead); - addFormSelector(F("CF1 Interrupt Edge"), F("cf1_edge"), 4, - modeRaise, modeValues, P076_CF1_TRIGGER); - addFormSelector(F("CF Interrupt Edge"), F("cf_edge"), 4, - modeRaise, modeValues, P076_CF_TRIGGER); + { + const __FlashStringHelper *modeCurr[] = { + F("LOW"), + F("HIGH"), + }; + + const int modeCurrValues[] = { + LOW, + HIGH, + }; + + const FormSelectorOptions selector(NR_ELEMENTS(modeCurr), modeCurr, modeCurrValues); + selector.addFormSelector(F("SEL Current (A) Reading"), F("curr_read"), currentRead); + } + { + const __FlashStringHelper *modeRaise[] = { + F("LOW"), + F("CHANGE"), + F("RISING"), + F("FALLING"), + }; + + const int modeValues[] = { + LOW, + CHANGE, + RISING, + FALLING, + }; + + const FormSelectorOptions selector(NR_ELEMENTS(modeRaise), modeRaise, modeValues); + selector.addFormSelector(F("CF1 Interrupt Edge"), F("cf1_edge"), P076_CF1_TRIGGER); + selector.addFormSelector(F("CF Interrupt Edge"), F("cf_edge"), P076_CF_TRIGGER); + } } ESPEASY_RULES_FLOAT_TYPE current, voltage, power; diff --git a/src/_P078_Eastron.ino b/src/_P078_Eastron.ino index 4784d825dc..d3f53fa7da 100644 --- a/src/_P078_Eastron.ino +++ b/src/_P078_Eastron.ino @@ -120,7 +120,8 @@ boolean Plugin_078(uint8_t function, struct EventStruct *event, String& string) options_baudrate[i] = p078_storageValueToBaudrate(i); } constexpr size_t optionCount = NR_ELEMENTS(options_baudrate); - addFormSelector(F("Baud Rate"), P078_BAUDRATE_LABEL, optionCount, options_baudrate, nullptr, P078_BAUDRATE); + const FormSelectorOptions selector(optionCount, options_baudrate); + selector.addFormSelector(F("Baud Rate"), P078_BAUDRATE_LABEL, P078_BAUDRATE); addUnit(F("baud")); } @@ -173,7 +174,8 @@ boolean Plugin_078(uint8_t function, struct EventStruct *event, String& string) F("SDM320C") }; constexpr size_t nrOptions = NR_ELEMENTS(options_model); - addFormSelector(F("Model Type"), P078_MODEL_LABEL, nrOptions, options_model, nullptr, P078_MODEL); + const FormSelectorOptions selector(nrOptions, options_model); + selector.addFormSelector(F("Model Type"), P078_MODEL_LABEL, P078_MODEL); addFormNote(F("Submit after changing the modell to update Output Configuration.")); } success = true; diff --git a/src/_P079_Wemos_Motorshield.ino b/src/_P079_Wemos_Motorshield.ino index f79e967c9e..db6c4f66d7 100644 --- a/src/_P079_Wemos_Motorshield.ino +++ b/src/_P079_Wemos_Motorshield.ino @@ -125,7 +125,8 @@ boolean Plugin_079(uint8_t function, struct EventStruct *event, String& string) static_cast(P079_BoardType::LolinMotorshield) }; constexpr size_t optionCount = NR_ELEMENTS(indices); - addFormSelector(F("Motor Shield Type"), F("shield_type"), optionCount, options, indices, SHIELD_VER_PCFG_P079); + const FormSelectorOptions selector(optionCount, options, indices); + selector.addFormSelector(F("Motor Shield Type"), F("shield_type"), SHIELD_VER_PCFG_P079); } if (Plugin_079_MotorShield_type == P079_BoardType::WemosMotorshield) { diff --git a/src/_P082_GPS.ino b/src/_P082_GPS.ino index 41aa8e2863..d5bf404bba 100644 --- a/src/_P082_GPS.ino +++ b/src/_P082_GPS.ino @@ -191,7 +191,8 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string) static_cast(P082_PowerMode::Eco) }; constexpr size_t optionCount = NR_ELEMENTS(indices); - addFormSelector(F("Power Mode"), F("pwrmode"), optionCount, options, indices, P082_POWER_MODE); + const FormSelectorOptions selector(optionCount, options, indices); + selector.addFormSelector(F("Power Mode"), F("pwrmode"), P082_POWER_MODE); } { @@ -220,7 +221,8 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string) static_cast(P082_DynamicModel::Bike) }; constexpr size_t optionCount = NR_ELEMENTS(indices); - addFormSelector(F("Dynamic Platform Model"), F("dynmodel"), optionCount, options, indices, P082_DYNAMIC_MODEL); + const FormSelectorOptions selector(optionCount, options, indices); + selector.addFormSelector(F("Dynamic Platform Model"), F("dynmodel"), P082_DYNAMIC_MODEL); } # endif // P082_USE_U_BLOX_SPECIFIC diff --git a/src/_P084_VEML6070.ino b/src/_P084_VEML6070.ino index 02334ad44f..aa9c718605 100644 --- a/src/_P084_VEML6070.ino +++ b/src/_P084_VEML6070.ino @@ -88,7 +88,8 @@ boolean Plugin_084(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *optionsMode[] = { F("1/2T"), F("1T"), F("2T"), F("4T (Default)") }; constexpr size_t optionCount = NR_ELEMENTS(optionsMode); - addFormSelector(F("Refresh Time Determination"), F("itime"), optionCount, optionsMode, nullptr, PCONFIG(0)); + const FormSelectorOptions selector(optionCount, optionsMode); + selector.addFormSelector(F("Refresh Time Determination"), F("itime"), PCONFIG(0)); success = true; break; diff --git a/src/_P085_AcuDC243.ino b/src/_P085_AcuDC243.ino index e542bfc9c3..28dc7e900c 100644 --- a/src/_P085_AcuDC243.ino +++ b/src/_P085_AcuDC243.ino @@ -97,7 +97,8 @@ boolean Plugin_085(uint8_t function, struct EventStruct *event, String& string) for (int i = 0; i < 6; ++i) { options_baudrate[i] = String(p085_storageValueToBaudrate(i)); } - addFormSelector(F("Baud Rate"), P085_BAUDRATE_LABEL, 6, options_baudrate, nullptr, P085_BAUDRATE); + const FormSelectorOptions selector(6, options_baudrate); + selector.addFormSelector(F("Baud Rate"), P085_BAUDRATE_LABEL, P085_BAUDRATE); addUnit(F("baud")); addFormNumericBox(F("Modbus Address"), P085_DEV_ID_LABEL, P085_DEV_ID, 1, 247); break; diff --git a/src/_P086_Homie.ino b/src/_P086_Homie.ino index 5fbef766f2..9748910796 100644 --- a/src/_P086_Homie.ino +++ b/src/_P086_Homie.ino @@ -98,8 +98,9 @@ boolean Plugin_086(uint8_t function, struct EventStruct *event, String& string) addFormTextBox(F("Event Name"), getPluginCustomArgName((i * 10) + 0), Cache.getTaskDeviceValueName(event->TaskIndex, i), NAME_FORMULA_LENGTH_MAX); - addFormSelector(F("Parameter Type"), getPluginCustomArgName((i * 10) + 1), - PLUGIN_086_VALUE_TYPES, options, optionValues, PCONFIG(i)); + + const FormSelectorOptions selector(PLUGIN_086_VALUE_TYPES, options, optionValues); + selector.addFormSelector(F("Parameter Type"), getPluginCustomArgName((i * 10) + 1), PCONFIG(i)); addFormNumericBox(F("Min"), getPluginCustomArgName((i * 10) + 2), Cache.getTaskDevicePluginConfig(event->TaskIndex, i)); diff --git a/src/_P087_SerialProxy.ino b/src/_P087_SerialProxy.ino index 01aca2edd0..5780c5b167 100644 --- a/src/_P087_SerialProxy.ino +++ b/src/_P087_SerialProxy.ino @@ -348,13 +348,14 @@ void P087_html_show_matchForms(struct EventStruct *event) { optionValues[i] = matchType; } P087_Match_Type choice = P087_data->getMatchType(); - addFormSelector(F("Match Type"), - getPluginCustomArgName(P087_MATCH_TYPE_POS), - P087_Match_Type_NR_ELEMENTS, - options, - optionValues, - choice, - false); + const FormSelectorOptions selector( + P087_Match_Type_NR_ELEMENTS, + options, + optionValues); + selector.addFormSelector( + F("Match Type"), + getPluginCustomArgName(P087_MATCH_TYPE_POS), + choice); addFormNote(F("Capture filter can only be used on Global Match")); } @@ -386,13 +387,15 @@ void P087_html_show_matchForms(struct EventStruct *event) { options[P087_Filter_Comp::Equal] = F("=="); options[P087_Filter_Comp::NotEqual] = F("!="); const int optionValues[] = { P087_Filter_Comp::Equal, P087_Filter_Comp::NotEqual }; - addSelector(id, 2, options, optionValues, nullptr, static_cast(comparator), false, true, F("")); + FormSelectorOptions selector(2, options, optionValues); + selector.clearClassName(); + selector.addSelector(id, static_cast(comparator)); break; } case 2: { // Compare with - addTextBox(id, filter, 32, false, false, EMPTY_STRING, F("")); + addTextBox(id, filter, 32, F("")); break; } } diff --git a/src/_P090_CCS811.ino b/src/_P090_CCS811.ino index b234f51586..80a69562df 100644 --- a/src/_P090_CCS811.ino +++ b/src/_P090_CCS811.ino @@ -111,7 +111,8 @@ boolean Plugin_090(uint8_t function, struct EventStruct *event, String& string) if (function == PLUGIN_WEBFORM_SHOW_I2C_PARAMS) { const __FlashStringHelper *options[] = { F("0x5A (ADDR pin is LOW)"), F("0x5B (ADDR pin is HIGH)") }; constexpr size_t optionCount = NR_ELEMENTS(options); - addFormSelector(F("I2C Address"), F("i2c_addr"), optionCount, options, i2cAddressValues, P090_I2C_ADDR); + const FormSelectorOptions selector(optionCount, options, i2cAddressValues); + selector.addFormSelector(F("I2C Address"), F("i2c_addr"), P090_I2C_ADDR); } else { success = intArrayContains(2, i2cAddressValues, event->Par1); } @@ -135,7 +136,8 @@ boolean Plugin_090(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *frequencyOptions[] = { F("1 second"), F("10 seconds"), F("60 seconds") }; const int frequencyValues[] = { 1, 2, 3 }; constexpr size_t optionCount = NR_ELEMENTS(frequencyValues); - addFormSelector(F("Take reading every"), F("temp_freq"), optionCount, frequencyOptions, frequencyValues, frequencyChoice); + const FormSelectorOptions selector(optionCount, frequencyOptions, frequencyValues); + selector.addFormSelector(F("Take reading every"), F("temp_freq"), frequencyChoice); } addFormSeparator(2); diff --git a/src/_P091_SerSwitch.ino b/src/_P091_SerSwitch.ino index 6f0cccdca9..7cd07b1132 100644 --- a/src/_P091_SerSwitch.ino +++ b/src/_P091_SerSwitch.ino @@ -125,7 +125,8 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) }; const int optionValues[] = { SER_SWITCH_YEWE, SER_SWITCH_SONOFFDUAL, SER_SWITCH_LCTECH, SER_SWITCH_WIFIDIMMER }; constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Switch Type"), F("type"), optionCount, options, optionValues, PCONFIG(0)); + const FormSelectorOptions selector(optionCount, options, optionValues); + selector.addFormSelector(F("Switch Type"), F("type"), PCONFIG(0)); } if (PCONFIG(0) == SER_SWITCH_YEWE) @@ -138,7 +139,8 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) }; const int buttonoptionValues[] = { 1, 2, 3, 4 }; constexpr size_t optionCount = NR_ELEMENTS(buttonoptionValues); - addFormSelector(F("Number of relays"), F("button"), optionCount, buttonOptions, buttonoptionValues, PCONFIG(1)); + const FormSelectorOptions selector(optionCount, buttonOptions, buttonoptionValues); + selector.addFormSelector(F("Number of relays"), F("button"), PCONFIG(1)); } if (PCONFIG(0) == SER_SWITCH_SONOFFDUAL) @@ -149,21 +151,17 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) F("Simultaneous mode"), }; constexpr size_t optionCount = NR_ELEMENTS(modeoptions); - addFormSelector(F("Relay working mode"), F("mode"), optionCount, modeoptions, nullptr, PCONFIG(1)); + const FormSelectorOptions selector(optionCount, modeoptions); + selector.addFormSelector(F("Relay working mode"), F("mode"), PCONFIG(1)); } if (PCONFIG(0) == SER_SWITCH_LCTECH) { { - const __FlashStringHelper *buttonOptions[] = { - F("1"), - F("2"), - F("3"), - F("4"), - }; const int buttonoptionValues[] = { 1, 2, 3, 4 }; constexpr size_t optionCount = NR_ELEMENTS(buttonoptionValues); - addFormSelector(F("Number of relays"), F("button"), optionCount, buttonOptions, buttonoptionValues, PCONFIG(1)); + const FormSelectorOptions selector(optionCount, buttonoptionValues); + selector.addFormSelector(F("Number of relays"), F("button"), PCONFIG(1)); } { @@ -178,7 +176,9 @@ boolean Plugin_091(uint8_t function, struct EventStruct *event, String& string) F("57600"), }; constexpr size_t optionCount = NR_ELEMENTS(speedOptions); - addFormSelector(F("Serial speed"), F("speed"), optionCount, speedOptions, nullptr, PCONFIG(2)); + const FormSelectorOptions selector(optionCount, speedOptions); + selector.addFormSelector(F("Serial speed"), F("speed"), PCONFIG(2)); + addUnit(F("baud")); } addFormCheckBox(F("Use command doubling"), F("dbl"), PCONFIG(3)); diff --git a/src/_P092_DLbus.ino b/src/_P092_DLbus.ino index aa911f85a1..4a8a0e06e7 100644 --- a/src/_P092_DLbus.ino +++ b/src/_P092_DLbus.ino @@ -138,7 +138,8 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) static_cast(eP092pinmode::ePPM_Input), static_cast(eP092pinmode::ePPM_InputPullUp) }; - addFormSelector(F("Pin mode"), F("ppinmode"), 2, options, optionValues, choice); + const FormSelectorOptions selector(NR_ELEMENTS(options), options, optionValues); + selector.addFormSelector(F("Pin mode"), F("ppinmode"), choice); } { const __FlashStringHelper *Devices[] = { @@ -151,7 +152,9 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) const int DevTypes[] = { 21, 31, 42, 1611, 6132, 6133 }; constexpr size_t optionCount = NR_ELEMENTS(Devices); - addFormSelector(F("DL-Bus Type"), F("pdlbtype"), optionCount, Devices, DevTypes, nullptr, PCONFIG(0), true); + FormSelectorOptions selector(optionCount, Devices, DevTypes); + selector.reloadonchange = true; + selector.addFormSelector(F("DL-Bus Type"), F("pdlbtype"), PCONFIG(0)); } { int P092_ValueType, P092_ValueIdx; @@ -236,14 +239,9 @@ boolean Plugin_092(uint8_t function, struct EventStruct *event, String& string) P092_ValueType = PCONFIG(1) >> 8; P092_ValueIdx = PCONFIG(1) & 0x00FF; - addFormSelector(plugin_092_DefValueName, - F("pValue"), - optionCount, - Options, - P092_OptionTypes, - nullptr, - P092_ValueType, - true); + FormSelectorOptions selector(optionCount, Options, P092_OptionTypes); + selector.reloadonchange = true; + selector.addFormSelector(plugin_092_DefValueName, F("pValue"), P092_ValueType); if (P092_MaxIdx[P092_ValueType] > 1) { int CurIdx = P092_ValueIdx; diff --git a/src/_P095_ILI9341.ino b/src/_P095_ILI9341.ino index bb0a7e148b..4babc42fd7 100644 --- a/src/_P095_ILI9341.ino +++ b/src/_P095_ILI9341.ino @@ -261,12 +261,13 @@ boolean Plugin_095(uint8_t function, struct EventStruct *event, String& string) # endif // if P095_ENABLE_ILI948X }; constexpr size_t optionCount = NR_ELEMENTS(hardwareOptions); - addFormSelector(F("TFT display model"), - F("dsptype"), - optionCount, + const FormSelectorOptions selector(optionCount, hardwareTypes, - hardwareOptions, - P095_CONFIG_FLAG_GET_TYPE); + hardwareOptions); + selector.addFormSelector( + F("TFT display model"), + F("dsptype"), + P095_CONFIG_FLAG_GET_TYPE); } addFormCheckBox(F("Invert display"), F("invert"), P095_CONFIG_FLAG_GET_INVERTDISPLAY); @@ -311,12 +312,10 @@ boolean Plugin_095(uint8_t function, struct EventStruct *event, String& string) # endif // if P095_ENABLE_ILI948X }; constexpr size_t optionCount = NR_ELEMENTS(commandTriggerOptions); - addFormSelector(F("Write Command trigger"), - F("commandtrigger"), - optionCount, - commandTriggers, - commandTriggerOptions, - P095_CONFIG_FLAG_GET_CMD_TRIGGER); + const FormSelectorOptions selector(optionCount, commandTriggers, commandTriggerOptions); + selector.addFormSelector( + F("Write Command trigger"), + F("commandtrigger"), P095_CONFIG_FLAG_GET_CMD_TRIGGER); # ifndef LIMIT_BUILD_SIZE addFormNote(F("Select the command that is used to handle commands for this display.")); # endif // ifndef LIMIT_BUILD_SIZE diff --git a/src/_P096_eInk.ino b/src/_P096_eInk.ino index 534268c7e2..c698c2793a 100644 --- a/src/_P096_eInk.ino +++ b/src/_P096_eInk.ino @@ -273,11 +273,12 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) # endif // if P096_USE_WAVESHARE_2IN7 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues4); - addFormSelector(F("eInk display model"), + const FormSelectorOptions selector( + optionCount, + options4, + optionValues4); + selector.addFormSelector(F("eInk display model"), F("_type"), - optionCount, - options4, - optionValues4, P096_CONFIG_FLAG_GET_DISPLAYTYPE); } @@ -291,7 +292,8 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *options2[] = { F("Normal"), F("+90°"), F("+180°"), F("+270°") }; int optionValues2[] = { 0, 1, 2, 3 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues2); - addFormSelector(F("Rotation"), F("_rotate"), optionCount, options2, optionValues2, P096_CONFIG_ROTATION); + const FormSelectorOptions selector( optionCount, options2, optionValues2); + selector.addFormSelector(F("Rotation"), F("_rotate"), P096_CONFIG_ROTATION); } # endif // ifdef P096_USE_ADA_GRAPHICS @@ -338,12 +340,9 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) P096_CONFIG_FLAGS = lSettings; } constexpr size_t optionCount = NR_ELEMENTS(colorDepthOptions); - addFormSelector(F("Greyscale levels"), - F("_colorDepth"), - optionCount, - colorDepths, - colorDepthOptions, - P096_CONFIG_FLAG_GET_COLORDEPTH); + const FormSelectorOptions selector(optionCount, colorDepths, colorDepthOptions); + selector.addFormSelector(F("Greyscale levels"),F("_colorDepth"), + P096_CONFIG_FLAG_GET_COLORDEPTH); } AdaGFXFormTextPrintMode(F("_mode"), P096_CONFIG_FLAG_GET_MODE); @@ -378,11 +377,8 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) # endif // if P096_USE_WAVESHARE_2IN7 }; constexpr size_t optionCount = NR_ELEMENTS(commandTriggerOptions); - addFormSelector(F("Write Command trigger"), - F("_commandtrigger"), - optionCount, - commandTriggers, - commandTriggerOptions, + const FormSelectorOptions selector(optionCount, commandTriggers, commandTriggerOptions); + selector.addFormSelector(F("Write Command trigger"), F("_commandtrigger"), P096_CONFIG_FLAG_GET_CMD_TRIGGER); addFormNote(F("Select the command that is used to handle commands for this display.")); } diff --git a/src/_P098_PWM_motor.ino b/src/_P098_PWM_motor.ino index 4fb4a54fa8..e35190a046 100644 --- a/src/_P098_PWM_motor.ino +++ b/src/_P098_PWM_motor.ino @@ -181,7 +181,8 @@ boolean Plugin_098(uint8_t function, struct EventStruct *event, String& string) options[i] = P098_config_struct::toString(static_cast(i)); optionValues[i] = i; } - addFormSelector(F("Motor Control"), F("motor_contr"), P098_PWM_MODE_TYPES, options, optionValues, P098_MOTOR_CONTROL); + const FormSelectorOptions selector(P098_PWM_MODE_TYPES, options, optionValues); + selector.addFormSelector(F("Motor Control"), F("motor_contr"), P098_MOTOR_CONTROL); } addFormNumericBox(F("PWM Frequency"), F("pwm_freq"), P098_PWM_FREQ, 50, 100000); addUnit(F("Hz")); diff --git a/src/_P099_XPT2046Touch.ino b/src/_P099_XPT2046Touch.ino index cfe6f688de..ed543b5003 100644 --- a/src/_P099_XPT2046Touch.ino +++ b/src/_P099_XPT2046Touch.ino @@ -128,7 +128,8 @@ boolean Plugin_099(uint8_t function, struct EventStruct *event, String& string) const int optionValues2[] = { 0, 1, 2, 3 }; // Rotation similar to the // TFT ILI9341 rotation constexpr size_t optionCount = NR_ELEMENTS(optionValues2); - addFormSelector(F("Rotation"), F("protate"), optionCount, options2, optionValues2, choice2); + const FormSelectorOptions selector(optionCount, options2, optionValues2); + selector.addFormSelector(F("Rotation"), F("protate"), choice2); } const bool bRotationFlipped = bitRead(P099_CONFIG_FLAGS, P099_FLAGS_ROTATION_FLIPPED); @@ -153,7 +154,8 @@ boolean Plugin_099(uint8_t function, struct EventStruct *event, String& string) F("Objectnames, X, Y and Z") }; const int optionValues3[] = { 0, 1, 3, 4, 5, 7 }; // Already used as a bitmap! constexpr size_t optionCount = NR_ELEMENTS(optionValues3); - addFormSelector(F("Events"), F("pevents"), optionCount, options3, optionValues3, choice3); + const FormSelectorOptions selector(optionCount, options3, optionValues3); + selector.addFormSelector(F("Events"), F("pevents"), choice3); } if (!Settings.UseRules) { @@ -215,7 +217,9 @@ boolean Plugin_099(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *options5[] = { F("None"), F("8"), F("16"), F("24"), F("32"), F("40") }; const int optionValues5[] = { -1, 8, 16, 24, 32, 40 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues5); - addFormSelector(F("# of objects"), F("pobjectcount"), optionCount, options5, optionValues5, choice5, true); + FormSelectorOptions selector(optionCount, options5, optionValues5); + selector.reloadonchange = true; + selector.addFormSelector(F("# of objects"), F("pobjectcount"), choice5); } } @@ -239,7 +243,7 @@ boolean Plugin_099(uint8_t function, struct EventStruct *event, String& string) addTextBox(getPluginCustomArgName(objectNr), String(P099_data->StoredSettings.TouchObjects[objectNr].objectname), P099_MaxObjectNameLength - 1, - false, false, EMPTY_STRING, F("")); + F("")); html_TD(); addNumericBox(getPluginCustomArgName(objectNr + 100), P099_data->StoredSettings.TouchObjects[objectNr].top_left.x, 0, 65535); html_TD(); diff --git a/src/_P100_DS2423_counter.ino b/src/_P100_DS2423_counter.ino index 5ab8fa770e..946520ff54 100644 --- a/src/_P100_DS2423_counter.ino +++ b/src/_P100_DS2423_counter.ino @@ -64,7 +64,8 @@ boolean Plugin_100(uint8_t function, struct EventStruct *event, String& string) // Counter select const __FlashStringHelper *resultsOptions[] = { F("A"), F("B") }; constexpr size_t optionCount = NR_ELEMENTS(resultsOptions); - addFormSelector(F("Counter"), F("counter"), optionCount, resultsOptions, nullptr, PCONFIG(0)); + const FormSelectorOptions selector(optionCount, resultsOptions); + selector.addFormSelector(F("Counter"), F("counter"), PCONFIG(0)); addFormNote(F("Counter value is incremental")); } success = true; diff --git a/src/_P102_PZEM004Tv3.ino b/src/_P102_PZEM004Tv3.ino index bff9c8a47f..0ef7aa71e8 100644 --- a/src/_P102_PZEM004Tv3.ino +++ b/src/_P102_PZEM004Tv3.ino @@ -150,7 +150,8 @@ boolean Plugin_102(uint8_t function, struct EventStruct *even { const __FlashStringHelper *options_model[] = { F("Read_value"), F("Reset_Energy"), F("Program_adress") }; constexpr size_t optionCount = NR_ELEMENTS(options_model); - addFormSelector(F("PZEM Mode"), F("PZEM_mode"), optionCount, options_model, nullptr, P102_PZEM_mode); + const FormSelectorOptions selector(optionCount, options_model); + selector.addFormSelector(F("PZEM Mode"), F("PZEM_mode"), P102_PZEM_mode); } if (P102_PZEM_mode == 2) @@ -160,8 +161,8 @@ boolean Plugin_102(uint8_t function, struct EventStruct *even { const __FlashStringHelper *options_confirm[] = { F("NO"), F("YES") }; constexpr size_t optionCount = NR_ELEMENTS(options_confirm); - addFormSelector(F("Confirm address programming ?"), F("PZEM_addr_set"), optionCount, options_confirm, nullptr, - P102_PZEM_ADDR_SET); + const FormSelectorOptions selector(optionCount, options_confirm); + selector.addFormSelector(F("Confirm address programming ?"), F("PZEM_addr_set"), P102_PZEM_ADDR_SET); } addFormNumericBox(F("Address of PZEM"), F("PZEM_addr"), (P102_PZEM_ADDR < 1) ? 1 : P102_PZEM_ADDR, 1, 247); addHtml(F("Select the address to set PZEM. Programming address 0 is forbidden.")); @@ -184,7 +185,8 @@ boolean Plugin_102(uint8_t function, struct EventStruct *even { const __FlashStringHelper *options_model[] = { F("Read_value"), F("Reset_Energy") }; constexpr size_t optionCount = NR_ELEMENTS(options_model); - addFormSelector(F("PZEM Mode"), F("PZEM_mode"), optionCount, options_model, nullptr, P102_PZEM_mode); + const FormSelectorOptions selector(optionCount, options_model); + selector.addFormSelector(F("PZEM Mode"), F("PZEM_mode"), P102_PZEM_mode); } addHtml(F(" Tx/Rx Pins config disabled: Configuration is available in the first PZEM plugin.
")); addFormNumericBox(F("Address of PZEM"), F("PZEM_addr"), P102_PZEM_ADDR, 1, 247); diff --git a/src/_P105_AHT.ino b/src/_P105_AHT.ino index a229613c0f..1930233f0f 100644 --- a/src/_P105_AHT.ino +++ b/src/_P105_AHT.ino @@ -152,7 +152,9 @@ boolean Plugin_105(uint8_t function, struct EventStruct *event, String& string) static_cast(AHTx_device_type::AHT20_DEVICE), static_cast(AHTx_device_type::AHT21_DEVICE) }; constexpr size_t optionCount = NR_ELEMENTS(indices); - addFormSelector(F("Sensor model"), F("ahttype"), optionCount, options, indices, P105_AHT_TYPE, true); + FormSelectorOptions selector(optionCount, options, indices); + selector.reloadonchange = true; + selector.addFormSelector(F("Sensor model"), F("ahttype"), P105_AHT_TYPE); addFormNote(F("Changing Sensor model will reload the page.")); if (static_cast(AHTx_device_type::AHT10_DEVICE) == P105_AHT_TYPE) { diff --git a/src/_P108_DDS238.ino b/src/_P108_DDS238.ino index d914f225c5..a57c26337c 100644 --- a/src/_P108_DDS238.ino +++ b/src/_P108_DDS238.ino @@ -106,7 +106,8 @@ boolean Plugin_108(uint8_t function, struct EventStruct *event, String& string) for (int i = 0; i < 4; ++i) { options_baudrate[i] = String(p108_storageValueToBaudrate(i)); } - addFormSelector(F("Baud Rate"), P108_BAUDRATE_LABEL, 4, options_baudrate, nullptr, P108_BAUDRATE); + const FormSelectorOptions selector(4, options_baudrate); + selector.addFormSelector(F("Baud Rate"), P108_BAUDRATE_LABEL, P108_BAUDRATE); addUnit(F("baud")); addFormNumericBox(F("Modbus Address"), P108_DEV_ID_LABEL, P108_DEV_ID, 1, 247); break; diff --git a/src/_P109_ThermOLED.ino b/src/_P109_ThermOLED.ino index b07946ceb7..08b5a70d32 100644 --- a/src/_P109_ThermOLED.ino +++ b/src/_P109_ThermOLED.ino @@ -181,7 +181,8 @@ boolean Plugin_109(uint8_t function, struct EventStruct *event, String& string) const __FlashStringHelper *options4[] = { F("0.2"), F("0.5"), F("1") }; const int optionValues4[] = { 2, 5, 10 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues4); - addFormSelector(F("Hysteresis"), F("hyst"), optionCount, options4, optionValues4, static_cast(P109_CONFIG_HYSTERESIS * 10.0f)); + const FormSelectorOptions selector(optionCount, options4, optionValues4); + selector.addFormSelector(F("Hysteresis"), F("hyst"), static_cast(P109_CONFIG_HYSTERESIS * 10.0f)); } { diff --git a/src/_P110_VL53L0X.ino b/src/_P110_VL53L0X.ino index 72320e7a14..ad7b520861 100644 --- a/src/_P110_VL53L0X.ino +++ b/src/_P110_VL53L0X.ino @@ -100,7 +100,8 @@ boolean Plugin_110(uint8_t function, struct EventStruct *event, String& string) F("Accurate") }; const int optionValuesMode2[] = { 80, 20, 320 }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); - addFormSelector(F("Timing"), F("ptiming"), optionCount, optionsMode2, optionValuesMode2, P110_TIMING); + const FormSelectorOptions selector(optionCount, optionsMode2, optionValuesMode2); + selector.addFormSelector(F("Timing"), F("ptiming"), P110_TIMING); } { @@ -108,7 +109,8 @@ boolean Plugin_110(uint8_t function, struct EventStruct *event, String& string) F("Normal"), F("Long") }; constexpr size_t optionCount = NR_ELEMENTS(optionsMode3); - addFormSelector(F("Range"), F("prange"), optionCount, optionsMode3, nullptr, P110_RANGE); + const FormSelectorOptions selector(optionCount, optionsMode3); + selector.addFormSelector(F("Range"), F("prange"), P110_RANGE); } addFormCheckBox(F("Send event when value unchanged"), F("notchanged"), P110_SEND_ALWAYS == 1); addFormNote(F("When checked, 'Trigger delta' setting is ignored!")); diff --git a/src/_P111_RC522_RFID.ino b/src/_P111_RC522_RFID.ino index a865e1d106..403482c91c 100644 --- a/src/_P111_RC522_RFID.ino +++ b/src/_P111_RC522_RFID.ino @@ -87,7 +87,8 @@ boolean Plugin_111(uint8_t function, struct EventStruct *event, String& string) # endif // P111_USE_REMOVAL }; constexpr size_t P111_removaltypes = NR_ELEMENTS(removalopts); - addFormSelector(F("Tag removal mode"), F("autotagremoval"), P111_removaltypes, removaltype, removalopts, P111_TAG_AUTOREMOVAL); + const FormSelectorOptions selector(P111_removaltypes, removaltype, removalopts); + selector.addFormSelector(F("Tag removal mode"), F("autotagremoval"), P111_TAG_AUTOREMOVAL); } addFormNumericBox(F("Tag removal Time-out"), F("removaltimeout"), P111_REMOVALTIMEOUT, 0, 60000); // 0 to 60 seconds diff --git a/src/_P112_AS7265x.ino b/src/_P112_AS7265x.ino index b515e4c7c5..16afcb216b 100644 --- a/src/_P112_AS7265x.ino +++ b/src/_P112_AS7265x.ino @@ -106,7 +106,7 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) // sensor.setGain(AS7265X_GAIN_64X); const __FlashStringHelper *optionsMode[] = { F("1x"), - F("3.7x (default)"), + F("3.7x"), F("16x"), F("64x"), }; @@ -117,19 +117,21 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) AS7265X_GAIN_64X, }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode); - addFormSelector(F("Gain"), F("Gain"), optionCount, optionsMode, optionValuesMode, PCONFIG_LONG(0)); + FormSelectorOptions selector(optionCount, optionsMode, optionValuesMode); + selector.default_index = AS7265X_GAIN_37X; + selector.addFormSelector(F("Gain"), F("Gain"), PCONFIG_LONG(0)); } { // Integration cycles from 0 (2.78ms) to 255 (711ms) // sensor.setIntegrationCycles(49); //Default: 50*2.8ms = 140ms per reading // sensor.setIntegrationCycles(1); //2*2.8ms = 5.6ms per reading const __FlashStringHelper *optionsMode2[] = { - F("2.8 ms"), - F("28 ms"), - F("56 ms"), - F("140 ms"), - F("280 ms"), - F("711 ms (default)"), + F("2.8"), + F("28"), + F("56"), + F("140"), + F("280"), + F("711"), }; const int optionValuesMode2[] = { 0, @@ -140,7 +142,10 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) 254, }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); - addFormSelector(F("Integration Time"), F("IntegrationTime"), optionCount, optionsMode2, optionValuesMode2, PCONFIG_LONG(1)); + FormSelectorOptions selector(optionCount, optionsMode2, optionValuesMode2); + selector.default_index = 254; // "711" + selector.addFormSelector(F("Integration Time"), F("IntegrationTime"), PCONFIG_LONG(1)); + addUnit(F("ms")); } # ifndef BUILD_NO_DEBUG addFormNote(F("Raw Readings shall not reach the upper limit of 65535 (Sensor Saturation).")); @@ -155,10 +160,10 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) // sensor.setIndicatorCurrent(AS7265X_INDICATOR_CURRENT_LIMIT_4MA); // sensor.setIndicatorCurrent(AS7265X_INDICATOR_CURRENT_LIMIT_8MA); //Default const __FlashStringHelper *optionsMode3[] = { - F("1 mA"), - F("2 mA"), - F("4 mA"), - F("8 mA (default)"), + F("1"), + F("2"), + F("4"), + F("8"), }; const int optionValuesMode3[] = { AS7265X_INDICATOR_CURRENT_LIMIT_1MA, @@ -167,7 +172,10 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) AS7265X_INDICATOR_CURRENT_LIMIT_8MA, }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode3); - addFormSelector(EMPTY_STRING, PCONFIG_LABEL(1), optionCount, optionsMode3, optionValuesMode3, PCONFIG(1)); + FormSelectorOptions selector(optionCount, optionsMode3, optionValuesMode3); + selector.default_index = AS7265X_INDICATOR_CURRENT_LIMIT_8MA; + selector.addFormSelector(EMPTY_STRING, PCONFIG_LABEL(1), PCONFIG(1)); + addUnit(F("mA")); } addHtml(F(" Current Limit")); # ifndef BUILD_NO_DEBUG @@ -181,10 +189,10 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) // sensor.setBulbCurrent(AS7265X_LED_CURRENT_LIMIT_50MA, AS7265x_LED_WHITE); //Allowed // sensor.setBulbCurrent(AS7265X_LED_CURRENT_LIMIT_100MA, AS7265x_LED_WHITE); //Allowed const __FlashStringHelper *optionsMode4[] = { - F("12.5 mA (default)"), - F("25 mA"), - F("50 mA"), - F("100 mA"), + F("12.5"), + F("25"), + F("50"), + F("100"), }; const int optionValuesMode4[] = { AS7265X_LED_CURRENT_LIMIT_12_5MA, @@ -193,7 +201,10 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) AS7265X_LED_CURRENT_LIMIT_100MA, }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode4); - addFormSelector(F("White"), PCONFIG_LABEL(2), optionCount, optionsMode4, optionValuesMode4, PCONFIG(2)); + FormSelectorOptions selector(optionCount, optionsMode4, optionValuesMode4); + selector.default_index = AS7265X_LED_CURRENT_LIMIT_12_5MA; + selector.addFormSelector(F("White"), PCONFIG_LABEL(2), PCONFIG(2)); + addUnit(F("mA")); } addHtml(F(" Current Limit")); @@ -204,9 +215,9 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) // sensor.setBulbCurrent(AS7265X_LED_CURRENT_LIMIT_50MA, AS7265x_LED_IR); //Allowed // sensor.setBulbCurrent(AS7265X_LED_CURRENT_LIMIT_100MA, AS7265x_LED_IR-bad); //Not allowed const __FlashStringHelper *optionsMode5[] = { - F("12.5 mA (default)"), - F("25 mA"), - F("50 mA"), + F("12.5"), + F("25"), + F("50"), }; const int optionValuesMode5[] = { AS7265X_LED_CURRENT_LIMIT_12_5MA, @@ -214,7 +225,10 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) AS7265X_LED_CURRENT_LIMIT_50MA, }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode5); - addFormSelector(F("IR"), PCONFIG_LABEL(3), optionCount, optionsMode5, optionValuesMode5, PCONFIG(3)); + FormSelectorOptions selector(optionCount, optionsMode5, optionValuesMode5); + selector.default_index = AS7265X_LED_CURRENT_LIMIT_12_5MA; + selector.addFormSelector(F("IR"), PCONFIG_LABEL(3), PCONFIG(3)); + addUnit(F("mA")); } { @@ -223,10 +237,13 @@ boolean Plugin_112(uint8_t function, struct EventStruct *event, String& string) // sensor.setBulbCurrent(AS7265X_LED_CURRENT_LIMIT_25MA, AS7265x_LED_UV-bad); //Not allowed // sensor.setBulbCurrent(AS7265X_LED_CURRENT_LIMIT_50MA, AS7265x_LED_UV-bad); //Not allowed // sensor.setBulbCurrent(AS7265X_LED_CURRENT_LIMIT_100MA, AS7265x_LED_UV-bad); //Not allowed - const __FlashStringHelper *optionsMode6[] = { F("12.5 mA (default)") }; + const __FlashStringHelper *optionsMode6[] = { F("12.5") }; const int optionValuesMode6[] = { AS7265X_LED_CURRENT_LIMIT_12_5MA }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode6); - addFormSelector(F("UV"), PCONFIG_LABEL(4), optionCount, optionsMode6, optionValuesMode6, PCONFIG(4)); + FormSelectorOptions selector(optionCount, optionsMode6, optionValuesMode6); + selector.default_index = AS7265X_LED_CURRENT_LIMIT_12_5MA; + selector.addFormSelector(F("UV"), PCONFIG_LABEL(4), PCONFIG(4)); + addUnit(F("mA")); } addFormNote(F("Control Gain and Integration Time after any change to avoid Sensor Saturation!")); diff --git a/src/_P113_VL53L1X.ino b/src/_P113_VL53L1X.ino index f431101556..ffdae3b74f 100644 --- a/src/_P113_VL53L1X.ino +++ b/src/_P113_VL53L1X.ino @@ -102,16 +102,18 @@ boolean Plugin_113(uint8_t function, struct EventStruct *event, String& string) { { const __FlashStringHelper *optionsMode2[] = { - F("100ms (Normal)"), - F("20ms (Fastest)"), - F("33ms (Fast)"), - F("50ms"), - F("200ms (Accurate)"), - F("500ms"), + F("100 (Normal)"), + F("20 (Fastest)"), + F("33 (Fast)"), + F("50"), + F("200 (Accurate)"), + F("500"), }; const int optionValuesMode2[] = { 100, 20, 33, 50, 200, 500 }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); - addFormSelector(F("Timing"), F("timing"), optionCount, optionsMode2, optionValuesMode2, P113_TIMING); + const FormSelectorOptions selector(optionCount, optionsMode2, optionValuesMode2); + selector.addFormSelector(F("Timing"), F("timing"), P113_TIMING); + addUnit(F("ms")); } { @@ -121,7 +123,8 @@ boolean Plugin_113(uint8_t function, struct EventStruct *event, String& string) }; const int optionValuesMode3[2] = { 0, 1 }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode3); - addFormSelector(F("Range"), F("range"), optionCount, optionsMode3, optionValuesMode3, P113_RANGE); + const FormSelectorOptions selector(optionCount, optionsMode3, optionValuesMode3); + selector.addFormSelector(F("Range"), F("range"), P113_RANGE); } addFormCheckBox(F("Send event when value unchanged"), F("notchanged"), P113_SEND_ALWAYS == 1); addFormNote(F("When checked, 'Trigger delta' setting is ignored!")); diff --git a/src/_P114_VEML6075.ino b/src/_P114_VEML6075.ino index 740bf75832..efa38d4870 100644 --- a/src/_P114_VEML6075.ino +++ b/src/_P114_VEML6075.ino @@ -80,11 +80,11 @@ boolean Plugin_114(uint8_t function, struct EventStruct *event, String& string) { { const __FlashStringHelper *optionsMode2[] = { - F("50 ms"), - F("100 ms"), - F("200 ms"), - F("400 ms"), - F("800 ms"), + F("50"), + F("100"), + F("200"), + F("400"), + F("800"), }; const int optionValuesMode2[] = { P114_IT_50, @@ -94,7 +94,9 @@ boolean Plugin_114(uint8_t function, struct EventStruct *event, String& string) P114_IT_800, }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); - addFormSelector(F("Integration Time"), F("it"), optionCount, optionsMode2, optionValuesMode2, PCONFIG(1)); + const FormSelectorOptions selector(optionCount, optionsMode2, optionValuesMode2); + selector.addFormSelector(F("Integration Time"), F("it"), PCONFIG(1)); + addUnit(F("ms")); } { @@ -103,7 +105,8 @@ boolean Plugin_114(uint8_t function, struct EventStruct *event, String& string) F("High Dynamic") } ; constexpr size_t optionCount = NR_ELEMENTS(optionsMode3); - addFormSelector(F("Dynamic Setting"), F("hd"), optionCount, optionsMode3, nullptr, PCONFIG(2)); + const FormSelectorOptions selector(optionCount, optionsMode3); + selector.addFormSelector(F("Dynamic Setting"), F("hd"), PCONFIG(2)); } success = true; diff --git a/src/_P115_MAX1704x_v2.ino b/src/_P115_MAX1704x_v2.ino index 0623f7cc76..ab1f08274d 100644 --- a/src/_P115_MAX1704x_v2.ino +++ b/src/_P115_MAX1704x_v2.ino @@ -107,7 +107,8 @@ boolean Plugin_115(uint8_t function, struct EventStruct *event, String& string) MAX1704X_MAX17048, MAX1704X_MAX17049 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Device"), F("device"), optionCount, options, optionValues, choice); + const FormSelectorOptions selector(optionCount, options, optionValues); + selector.addFormSelector(F("Device"), F("device"), choice); } addFormNumericBox(F("Alert threshold"), F("threshold"), P115_THRESHOLD, 1, 32); diff --git a/src/_P116_ST77xx.ino b/src/_P116_ST77xx.ino index 8e1e34ec0a..f7a618d16d 100644 --- a/src/_P116_ST77xx.ino +++ b/src/_P116_ST77xx.ino @@ -180,11 +180,9 @@ boolean Plugin_116(uint8_t function, struct EventStruct *event, String& string) static_cast(ST77xx_type_e::ST7796s_320x480) }; constexpr int optCount4 = NR_ELEMENTS(optionValues4); - addFormSelector(F("TFT display model"), + const FormSelectorOptions selector(optCount4, options4, optionValues4); + selector.addFormSelector(F("TFT display model"), F("type"), - optCount4, - options4, - optionValues4, P116_CONFIG_FLAG_GET_TYPE); } @@ -218,12 +216,11 @@ boolean Plugin_116(uint8_t function, struct EventStruct *event, String& string) static_cast(P116_CommandTrigger::st7796) }; constexpr int cmdCount = NR_ELEMENTS(commandTriggerOptions); - addFormSelector(F("Write Command trigger"), - F("commandtrigger"), - cmdCount, - commandTriggers, - commandTriggerOptions, - P116_CONFIG_FLAG_GET_CMD_TRIGGER); + const FormSelectorOptions selector(cmdCount, commandTriggers, commandTriggerOptions); + selector.addFormSelector( + F("Write Command trigger"), + F("commandtrigger"), + P116_CONFIG_FLAG_GET_CMD_TRIGGER); # ifndef LIMIT_BUILD_SIZE addFormNote(F("Select the command that is used to handle commands for this display.")); # endif // ifndef LIMIT_BUILD_SIZE diff --git a/src/_P119_ITG3205_Gyro.ino b/src/_P119_ITG3205_Gyro.ino index 1aa867205b..2c67cfdd21 100644 --- a/src/_P119_ITG3205_Gyro.ino +++ b/src/_P119_ITG3205_Gyro.ino @@ -124,7 +124,8 @@ boolean Plugin_119(uint8_t function, struct EventStruct *event, String& string) F("50") }; const int frequencyValues[] = { P119_FREQUENCY_10, P119_FREQUENCY_50 }; constexpr size_t optionCount = NR_ELEMENTS(frequencyValues); - addFormSelector(F("Measuring frequency"), F("frequency"), optionCount, frequencyOptions, frequencyValues, P119_FREQUENCY); + const FormSelectorOptions selector(optionCount, frequencyOptions, frequencyValues); + selector.addFormSelector(F("Measuring frequency"), F("frequency"), P119_FREQUENCY); addUnit(F("Hz")); success = true; diff --git a/src/_P122_SHT2x.ino b/src/_P122_SHT2x.ino index 96402421cd..e842e20fe4 100644 --- a/src/_P122_SHT2x.ino +++ b/src/_P122_SHT2x.ino @@ -138,7 +138,8 @@ boolean Plugin_122(uint8_t function, struct EventStruct *event, String& string) P122_RESOLUTION_11T_11RH, }; constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Resolution"), P122_RESOLUTION_LABEL, optionCount, options, optionValues, P122_RESOLUTION); + const FormSelectorOptions selector(optionCount, options, optionValues); + selector.addFormSelector(F("Resolution"), P122_RESOLUTION_LABEL, P122_RESOLUTION); # ifndef LIMIT_BUILD_SIZE P122_data_struct *P122_data = static_cast(getPluginTaskData(event->TaskIndex)); diff --git a/src/_P123_I2CTouch.ino b/src/_P123_I2CTouch.ino index e97b65e21c..5b5a06db90 100644 --- a/src/_P123_I2CTouch.ino +++ b/src/_P123_I2CTouch.ino @@ -201,12 +201,9 @@ boolean Plugin_123(uint8_t function, struct EventStruct *event, String& string) static_cast(P123_TouchType_e::Automatic), }; constexpr size_t optionCount = NR_ELEMENTS(touchTypeOptions); - addFormSelector(F("Touchscreen type (address)"), - F("ttype"), - optionCount, - touchTypes, - touchTypeOptions, - P123_GET_TOUCH_TYPE); + const FormSelectorOptions selector(optionCount, touchTypes, touchTypeOptions); + selector.addFormSelector( + F("Touchscreen type (address)"), F("ttype"), P123_GET_TOUCH_TYPE); if (nullptr != P123_data) { addUnit(concat(F("Detected: "), toString(P123_data->getTouchType()))); diff --git a/src/_P124_MultiRelay.ino b/src/_P124_MultiRelay.ino index 8220b8ff55..fda3486984 100644 --- a/src/_P124_MultiRelay.ino +++ b/src/_P124_MultiRelay.ino @@ -105,13 +105,17 @@ boolean Plugin_124(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { + /* const __FlashStringHelper *optionsMode2[] = { F("2"), F("4"), F("8") }; + */ const int optionValuesMode2[] { 2, 4, 8 }; constexpr size_t optionCount = NR_ELEMENTS(optionValuesMode2); - addFormSelector(F("Number of relays"), F("relays"), optionCount, optionsMode2, optionValuesMode2, P124_CONFIG_RELAY_COUNT, true); + FormSelectorOptions selector(optionCount, /*optionsMode2,*/ optionValuesMode2); + selector.reloadonchange = true; + selector.addFormSelector(F("Number of relays"), F("relays"), P124_CONFIG_RELAY_COUNT); addFormSelector_YesNo(F("Initialize relays on startup"), getPluginCustomArgName(P124_FLAGS_INIT_RELAYS), diff --git a/src/_P126_74HC595.ino b/src/_P126_74HC595.ino index 81bd15365b..a7ff7c4e12 100644 --- a/src/_P126_74HC595.ino +++ b/src/_P126_74HC595.ino @@ -167,7 +167,8 @@ boolean Plugin_126(uint8_t function, struct EventStruct *event, String& string) F("Hex/bin only") }; const int outputValues[] = { P126_OUTPUT_BOTH, P126_OUTPUT_DEC_ONLY, P126_OUTPUT_HEXBIN }; constexpr size_t optionCount = NR_ELEMENTS(outputValues); - addFormSelector(F("Output selection"), F("output"), optionCount, outputOptions, outputValues, P126_CONFIG_FLAGS_GET_OUTPUT_SELECTION); + const FormSelectorOptions selector(optionCount, outputOptions, outputValues); + selector.addFormSelector(F("Output selection"), F("output"), P126_CONFIG_FLAGS_GET_OUTPUT_SELECTION); addFormCheckBox(F("Restore Values on warm boot"), F("valrestore"), P126_CONFIG_FLAGS_GET_VALUES_RESTORE); diff --git a/src/_P129_74HC165.ino b/src/_P129_74HC165.ino index 60a7bf5589..32d36b7e84 100644 --- a/src/_P129_74HC165.ino +++ b/src/_P129_74HC165.ino @@ -155,20 +155,17 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string) addFormSubHeader(F("Device configuration")); { - String chipCount[P129_MAX_CHIP_COUNT]; + //String chipCount[P129_MAX_CHIP_COUNT]; int chipOption[P129_MAX_CHIP_COUNT]; for (uint8_t i = 0; i < P129_MAX_CHIP_COUNT; ++i) { - chipCount[i] = i + 1; + //chipCount[i] = i + 1; chipOption[i] = i + 1; } - addFormSelector(F("Number of chips (Q7 → DS)"), - F("chipcnt"), - P129_MAX_CHIP_COUNT, - chipCount, - chipOption, - P129_CONFIG_CHIP_COUNT, - true); + FormSelectorOptions selector(P129_MAX_CHIP_COUNT, /*chipCount,*/ chipOption); + selector.reloadonchange = true; + selector.addFormSelector( + F("Number of chips (Q7 → DS)"), F("chipcnt"), P129_CONFIG_CHIP_COUNT); addUnit(concat(F("Daisychained 1.."), P129_MAX_CHIP_COUNT)); # ifndef LIMIT_BUILD_SIZE addFormNote(F("Changing the number of chips will reload the page and update the Event configuration.")); @@ -180,12 +177,9 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string) F("50/sec (20 msec)") }; const int frequencyValues[] = { P129_FREQUENCY_10, P129_FREQUENCY_50 }; constexpr size_t optionCount = NR_ELEMENTS(frequencyValues); - addFormSelector(F("Sample frequency"), - F("frequency"), - optionCount, - frequencyOptions, - frequencyValues, - P129_CONFIG_FLAGS_GET_READ_FREQUENCY); + const FormSelectorOptions selector(optionCount, frequencyOptions, frequencyValues); + selector.addFormSelector( + F("Sample frequency"), F("frequency"), P129_CONFIG_FLAGS_GET_READ_FREQUENCY); addFormSubHeader(F("Display and output")); @@ -199,8 +193,8 @@ boolean Plugin_129(uint8_t function, struct EventStruct *event, String& string) F("Hex/bin only") }; const int outputValues[] = { P129_OUTPUT_BOTH, P129_OUTPUT_DEC_ONLY, P129_OUTPUT_HEXBIN }; constexpr size_t outputCount = NR_ELEMENTS(outputValues); - addFormSelector(F("Output selection"), F("outputsel"), outputCount, outputOptions, outputValues, - P129_CONFIG_FLAGS_GET_OUTPUT_SELECTION); + const FormSelectorOptions selector_output(outputCount, outputOptions, outputValues); + selector_output.addFormSelector(F("Output selection"), F("outputsel"), P129_CONFIG_FLAGS_GET_OUTPUT_SELECTION); addFormCheckBox(F("Separate events per pin"), F("separate_events"), P129_CONFIG_FLAGS_GET_SEPARATE_EVENTS == 1); diff --git a/src/_P131_NeoPixelMatrix.ino b/src/_P131_NeoPixelMatrix.ino index 24371d69d0..4104f44915 100644 --- a/src/_P131_NeoPixelMatrix.ino +++ b/src/_P131_NeoPixelMatrix.ino @@ -92,7 +92,8 @@ boolean Plugin_131(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *stripOptions[] = { F("GRB"), F("GRBW") }; // Selection copied from P038 - addFormSelector(F("Strip Type"), F("striptype"), 2, stripOptions, optionValuesZeroOne, P131_CONFIG_FLAGS_GET_STRIP_TYPE); + const FormSelectorOptions selector(2, stripOptions, optionValuesZeroOne); + selector.addFormSelector(F("Strip Type"), F("striptype"), P131_CONFIG_FLAGS_GET_STRIP_TYPE); } { @@ -118,14 +119,18 @@ boolean Plugin_131(uint8_t function, struct EventStruct *event, String& string) addFormNumericBox(F("Matrix height"), F("mxheight"), P131_CONFIG_MATRIX_HEIGHT, 1, 100); - addFormSelector(F("Matrix start-pixel"), F("mxstart"), 4, optionsTop, optionValuesTop, - get2BitFromUL(P131_CONFIG_FLAGS, P131_FLAGS_MATRIX_TYPE_TOP)); + const FormSelectorOptions selTop(4, optionsTop, optionValuesTop); + const FormSelectorOptions selRowCol(2, optionsRowCol, optionValuesZeroOne); + const FormSelectorOptions selProZig(2, optionsProZig, optionValuesZeroOne); - addFormSelector(F("Matrix Rows/Columns mode"), F("mxrowcol"), 2, optionsRowCol, optionValuesZeroOne, - bitRead(P131_CONFIG_FLAGS, P131_FLAGS_MATRIX_TYPE_RC)); + selTop.addFormSelector(F("Matrix start-pixel"), F("mxstart"), + get2BitFromUL(P131_CONFIG_FLAGS, P131_FLAGS_MATRIX_TYPE_TOP)); - addFormSelector(F("Matrix flow direction"), F("mxprozig"), 2, optionsProZig, optionValuesZeroOne, - bitRead(P131_CONFIG_FLAGS, P131_FLAGS_MATRIX_TYPE_PZ)); + selRowCol.addFormSelector(F("Matrix Rows/Columns mode"), F("mxrowcol"), + bitRead(P131_CONFIG_FLAGS, P131_FLAGS_MATRIX_TYPE_RC)); + + selProZig.addFormSelector(F("Matrix flow direction"), F("mxprozig"), + bitRead(P131_CONFIG_FLAGS, P131_FLAGS_MATRIX_TYPE_PZ)); addFormSubHeader(F("Multiple matrices: Tiles")); @@ -134,14 +139,14 @@ boolean Plugin_131(uint8_t function, struct EventStruct *event, String& string) addFormNumericBox(F("Tile matrix height"), F("tlheight"), P131_CONFIG_TILE_HEIGHT, 1, P131_Nlines); - addFormSelector(F("Tile start-matrix"), F("tlstart"), 4, optionsTop, optionValuesTop, - get2BitFromUL(P131_CONFIG_FLAGS, P131_FLAGS_TILE_TYPE_TOP)); + selTop.addFormSelector(F("Tile start-matrix"), F("tlstart"), + get2BitFromUL(P131_CONFIG_FLAGS, P131_FLAGS_TILE_TYPE_TOP)); - addFormSelector(F("Tile Rows/Columns mode"), F("tlrowcol"), 2, optionsRowCol, optionValuesZeroOne, - bitRead(P131_CONFIG_FLAGS, P131_FLAGS_TILE_TYPE_RC)); + selRowCol.addFormSelector(F("Tile Rows/Columns mode"), F("tlrowcol"), + bitRead(P131_CONFIG_FLAGS, P131_FLAGS_TILE_TYPE_RC)); - addFormSelector(F("Tile flow direction"), F("tlprozig"), 2, optionsProZig, optionValuesZeroOne, - bitRead(P131_CONFIG_FLAGS, P131_FLAGS_TILE_TYPE_PZ)); + selProZig.addFormSelector(F("Tile flow direction"), F("tlprozig"), + bitRead(P131_CONFIG_FLAGS, P131_FLAGS_TILE_TYPE_PZ)); } addFormSubHeader(F("Display")); @@ -174,13 +179,10 @@ boolean Plugin_131(uint8_t function, struct EventStruct *event, String& string) static_cast(P131_CommandTrigger::neomatrix), static_cast(P131_CommandTrigger::neo) }; - constexpr int cmdCount = sizeof(commandTriggerOptions) / sizeof(commandTriggerOptions[0]); - addFormSelector(F("Write Command trigger"), - F("cmdtrigger"), - cmdCount, - commandTriggers, - commandTriggerOptions, - P131_CONFIG_FLAG_GET_CMD_TRIGGER); + constexpr int cmdCount = NR_ELEMENTS(commandTriggerOptions); + const FormSelectorOptions selector(cmdCount, commandTriggers, commandTriggerOptions); + selector.addFormSelector( + F("Write Command trigger"), F("cmdtrigger"), P131_CONFIG_FLAG_GET_CMD_TRIGGER); # ifndef LIMIT_BUILD_SIZE addFormNote(F("Select the command that is used to handle commands for this display.")); # endif // ifndef LIMIT_BUILD_SIZE @@ -220,9 +222,6 @@ boolean Plugin_131(uint8_t function, struct EventStruct *event, String& string) addTextBox(getPluginCustomArgName(varNr), parseStringKeepCaseNoTrim(strings[varNr], 1), P131_Nchars, - false, - false, - EMPTY_STRING, F("")); String opts = parseString(strings[varNr], 2); diff --git a/src/_P132_INA3221.ino b/src/_P132_INA3221.ino index 314970893a..81934354ee 100644 --- a/src/_P132_INA3221.ino +++ b/src/_P132_INA3221.ino @@ -111,9 +111,13 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) }; constexpr size_t optionCount = NR_ELEMENTS(varOptions); + const FormSelectorOptions selector(optionCount, varOptions); + for (uint8_t r = 0; r < VARS_PER_TASK; ++r) { - addFormSelector(concat(F("Power value "), r + 1), - getPluginCustomArgName(r), optionCount, varOptions, NULL, PCONFIG(P132_CONFIG_BASE + r)); + selector.addFormSelector( + concat(F("Power value "), r + 1), + getPluginCustomArgName(r), + PCONFIG(P132_CONFIG_BASE + r)); } } @@ -122,13 +126,15 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *varshuntptions[] = { - F("0.1 ohm"), - F("0.01 ohm"), - F("0.005 ohm"), + F("0.1"), + F("0.01"), + F("0.005"), }; const int shuntvalue[] = { 1, 10, 20 }; constexpr size_t optionCount = NR_ELEMENTS(shuntvalue); - addFormSelector(F("Shunt resistor"), F("shunt"), optionCount, varshuntptions, shuntvalue, P132_SHUNT); + const FormSelectorOptions selector(optionCount, varshuntptions, shuntvalue); + selector.addFormSelector(F("Shunt resistor"), F("shunt"), P132_SHUNT); + addUnit(F("Ohm")); addFormNote(F("Select as is installed on the board.")); } @@ -136,7 +142,7 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *averagingSamples[] = { - F("1 (default)"), + F("1"), F("4"), F("16"), F("64"), @@ -147,12 +153,9 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) }; const int averageValue[] = { 0b000, 0b001, 0b010, 0b011, 0b100, 0b101, 0b110, 0b111 }; constexpr size_t optionCount = NR_ELEMENTS(averageValue); - addFormSelector(F("Averaging samples"), - F("average"), - optionCount, - averagingSamples, - averageValue, - P132_GET_AVERAGE); + FormSelectorOptions selector(optionCount, averagingSamples, averageValue); + selector.default_index = 0b000; + selector.addFormSelector(F("Averaging samples"),F("average"),P132_GET_AVERAGE); addFormNote(F("Samples > 16 then min. Interval: 64= 4, 128= 7, 256= 14, 512= 26, 1024= 52 seconds!")); } @@ -162,7 +165,7 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) F("204 µsec"), F("332 µsec"), F("588 µsec"), - F("1.1 msec (default)"), + F("1.1 msec"), F("2.116 msec"), F("4.156 msec"), F("8.244 msec"), @@ -171,19 +174,10 @@ boolean Plugin_132(uint8_t function, struct EventStruct *event, String& string) // 140us 204us 332us 588us 1.1ms 2.1ms 4.1ms 8.2ms const int conversionValues[] = { 0b000, 0b001, 0b010, 0b011, 0b100, 0b101, 0b110, 0b111 }; constexpr size_t optionCount = NR_ELEMENTS(conversionValues); - addFormSelector(F("Conversion rate Voltage"), - F("conv_v"), - optionCount, - conversionRates, - conversionValues, - P132_GET_CONVERSION_B); - - addFormSelector(F("Conversion rate Current"), - F("conv_c"), - optionCount, - conversionRates, - conversionValues, - P132_GET_CONVERSION_S); + FormSelectorOptions selector(optionCount, conversionRates, conversionValues); + selector.default_index = 0b100; // 1.1ms + selector.addFormSelector(F("Conversion rate Voltage"), F("conv_v"), P132_GET_CONVERSION_B); + selector.addFormSelector(F("Conversion rate Current"), F("conv_c"), P132_GET_CONVERSION_S); } success = true; diff --git a/src/_P133_LTR390.ino b/src/_P133_LTR390.ino index 39390ec521..f22a1e73a8 100644 --- a/src/_P133_LTR390.ino +++ b/src/_P133_LTR390.ino @@ -97,7 +97,9 @@ boolean Plugin_133(uint8_t function, struct EventStruct *event, String& string) static_cast(P133_selectMode_e::ALSMode) }; constexpr size_t optionCount = NR_ELEMENTS(selectModeValues); - addFormSelector(F("Read mode"), F("mode"), optionCount, selectModeOptions, selectModeValues, P133_SELECT_MODE, true); + FormSelectorOptions selector(optionCount, selectModeOptions, selectModeValues); + selector.reloadonchange = true; + selector.addFormSelector(F("Read mode"), F("mode"), P133_SELECT_MODE); } const __FlashStringHelper *gainOptions[] = { F("1x"), F("3x"), F("6x"), F("9x"), F("18x") }; @@ -127,15 +129,17 @@ boolean Plugin_133(uint8_t function, struct EventStruct *event, String& string) LTR390_RESOLUTION_13BIT, }; constexpr size_t resolutionCount = NR_ELEMENTS(resolutionValues); + const FormSelectorOptions selGain(gainCount, gainOptions, gainValues); + const FormSelectorOptions selRes(resolutionCount, resolutionOptions, resolutionValues); if (static_cast(P133_SELECT_MODE) != P133_selectMode_e::ALSMode) { - addFormSelector(F("UV Gain"), F("uvgain"), gainCount, gainOptions, gainValues, P133_UVGAIN); - addFormSelector(F("UV Resolution"), F("uvres"), resolutionCount, resolutionOptions, resolutionValues, P133_UVRESOLUTION); + selGain.addFormSelector(F("UV Gain"), F("uvgain"), P133_UVGAIN); + selRes.addFormSelector(F("UV Resolution"), F("uvres"), P133_UVRESOLUTION); } if (static_cast(P133_SELECT_MODE) != P133_selectMode_e::UVMode) { - addFormSelector(F("Ambient Gain"), F("alsgain"), gainCount, gainOptions, gainValues, P133_ALSGAIN); - addFormSelector(F("Ambient Resolution"), F("alsres"), resolutionCount, resolutionOptions, resolutionValues, P133_ALSRESOLUTION); + selGain.addFormSelector(F("Ambient Gain"), F("alsgain"), P133_ALSGAIN); + selRes.addFormSelector(F("Ambient Resolution"), F("alsres"), P133_ALSRESOLUTION); } addFormCheckBox(F("Reset sensor on init"), F("initreset"), P133_INITRESET == 1); diff --git a/src/_P135_SCD4x.ino b/src/_P135_SCD4x.ino index 4f5f2d51e8..354d8f9b8d 100644 --- a/src/_P135_SCD4x.ino +++ b/src/_P135_SCD4x.ino @@ -105,7 +105,9 @@ boolean Plugin_135(uint8_t function, struct EventStruct *event, String& string) static_cast(scd4x_sensor_type_e::SCD4x_SENSOR_SCD41), }; constexpr size_t optionCount = NR_ELEMENTS(sensorTypeOptions); - addFormSelector(F("Sensor model"), F("ptype"), optionCount, sensorTypes, sensorTypeOptions, P135_SENSOR_TYPE, true); + FormSelectorOptions selector(optionCount, sensorTypes, sensorTypeOptions); + selector.reloadonchange = true; + selector.addFormSelector(F("Sensor model"), F("ptype"), P135_SENSOR_TYPE); # ifndef LIMIT_BUILD_SIZE addFormNote(F("Page will reload on change.")); # endif // ifndef LIMIT_BUILD_SIZE diff --git a/src/_P137_AXP192.ino b/src/_P137_AXP192.ino index 02b214217a..32eb4cb2d4 100644 --- a/src/_P137_AXP192.ino +++ b/src/_P137_AXP192.ino @@ -190,9 +190,9 @@ boolean Plugin_137(uint8_t function, struct EventStruct *event, String& string) static_cast(P137_PredefinedDevices_e::LilyGO_TBeam), static_cast(P137_PredefinedDevices_e::UserDefined) }; // keep last and at 99 !! constexpr size_t optionCount = NR_ELEMENTS(predefinedValues); - addFormSelector(F("Predefined device configuration"), F("predef"), - optionCount, - predefinedNames, predefinedValues, 0, !Settings.isPowerManagerTask(event->TaskIndex)); + FormSelectorOptions selector(optionCount, predefinedNames, predefinedValues); + selector.reloadonchange = !Settings.isPowerManagerTask(event->TaskIndex); + selector.addFormSelector(F("Predefined device configuration"), F("predef"), 0); if (!Settings.isPowerManagerTask(event->TaskIndex)) { addFormNote(F("Page will reload when selection is changed.")); @@ -271,14 +271,11 @@ boolean Plugin_137(uint8_t function, struct EventStruct *event, String& string) for (int i = 0; i < 5; ++i) { // GPIO0..4 const String id = concat(F("pgpio"), i); addRowLabel(concat(F("Initial state GPIO"), i)); - addSelector(id, optionCount, - bootStates, bootStateValues, bootStateAttributes, - get3BitFromUL(P137_CONFIG_FLAGS, i * 3), - false, !bitRead(P137_CONFIG_DISABLEBITS, i + 3), F("") - # if FEATURE_TOOLTIPS - , EMPTY_STRING - # endif // if FEATURE_TOOLTIPS - ); + FormSelectorOptions selector( + optionCount, bootStates, bootStateValues, bootStateAttributes); + selector.enabled = !bitRead(P137_CONFIG_DISABLEBITS, i + 3); + selector.clearClassName(); + selector.addSelector(id, get3BitFromUL(P137_CONFIG_FLAGS, i * 3)); if (bitRead(P137_CONFIG_DISABLEBITS, i + 3)) { addUnit(notConnected); diff --git a/src/_P139_AXP2101.ino b/src/_P139_AXP2101.ino new file mode 100644 index 0000000000..b817e7c09a --- /dev/null +++ b/src/_P139_AXP2101.ino @@ -0,0 +1,337 @@ +#include "_Plugin_Helper.h" +#ifdef USES_P139 + +# ifdef ESP32 + +// ####################################################################################################### +// ################################### Plugin 139: AXP2101 Powermanagement ############################### +// ####################################################################################################### + +/** + * Changelog: + * 2025-01-18 tonhuisman: Enable writing values to chip. + * 2024-02-25 tonhuisman: Add I2C-enabled check on plugin startup, implement FsP macro + * 2024-02-21 tonhuisman: Add support for ChipID and ChargingDetail data supplied by AXP2101 + * 2024-02-18 tonhuisman: Add setting for Generate events, support for chargestate and isBatteryDetected, fix some issues + * 2024-02-17 tonhuisman: Add setting for Charge led and battery charge level, fix saving adjusted port settings, + * set to 0 decimals as we're using mV values + * 2024-02-15 tonhuisman: First plugin version, in ReadOnly mode only, no data is written to the AXP2101, only the register to read + * 2024-02-04 tonhuisman: Initial plugin development, only available for ESP32 + **/ + +/** + * Supported commands: (using same command as P137 AXP192 as no hardware overlap is possible) + * axp,readchip : Read current settings from AXP2101 chip and list values and state to the log at INFO level + * axp,voltage,, : Set port to given voltage and on, or turn off if below minimum value + * axp,on, : Turn On port + * axp,off, : Turn Off port + * axp,percentage,, : Set port to percentage of Low to High range (min/max or set range per port) + * axp,range,,, : Define low/high range for port. Low and High must be withing technical range of port + * axp,range : List current range configuration (or when providing an out of range low/high argument) + * axp,chargeled, : Set charge-led state, 0 : off, 1 : flash 1Hz, 2 : flash 4Hz, 3 : on + * TODO: Add more commands? + **/ +/** + * Get Config options: + * [#dcdc1] : Returns the voltage from the named port. + * [#dcdc2] : Can also read the status by using [#dcdc1.status] (text: On/Off/Default/Disabled/Protected) + * [#dcdc3] : Can also read the numeric status by using [#dcdc1.state] (0/1/2/3/7) + * [#dcdc4] : + * [#dcdc5] : + * [#aldo1] : + * [#aldo2] : + * [#aldo3] : + * [#aldo4] : + * [#bldo1] : + * [#bldo2] : + * [#dldo1] : + * [#dldo2] : + * [#cpuldos] : + * [#chargeled] : + * [#batcharge] : (Doesn't support the .status and .state variants of the variable) + * [#chargingstate] : Charging state, -1 = discharging, 0 = standby, 1 = charging + * [#batpresent] : (Doesn't support the .status and .state variants of the variable) + * [#chipid] : (Doesn't support the .state variant of the variable) + * [#chargingdet] : (Doesn't support the .state variant of the variable) + * TODO: Define additional values? + **/ +/** + * Events: + * #ChargingState=, : On change of the charging-state, new/old values: -1 = discharging, 0 = standby, 1 = charging + * TODO: Define events? + */ + + +# define PLUGIN_139 +# define PLUGIN_ID_139 139 +# define PLUGIN_NAME_139 "Power mgt - AXP2101 Power management" + +# include "./src/PluginStructs/P139_data_struct.h" + +boolean Plugin_139(uint8_t function, struct EventStruct *event, String& string) +{ + boolean success = false; + + switch (function) + { + case PLUGIN_DEVICE_ADD: + { + auto& dev = Device[++deviceCount]; + dev.Number = PLUGIN_ID_139; + dev.Type = DEVICE_TYPE_I2C; + dev.VType = Sensor_VType::SENSOR_TYPE_QUAD; + dev.OutputDataType = Output_Data_type_t::Simple; + dev.PowerManager = true; // So it can be started before SPI is initialized + dev.FormulaOption = true; + dev.ValueCount = 4; + dev.SendDataOption = true; + dev.TimerOption = true; + dev.TimerOptional = true; + dev.PluginStats = true; + break; + } + + case PLUGIN_PRIORITY_INIT: + { + const bool isPowerManagerTask = Settings.isPowerManagerTask(event->TaskIndex); + # ifndef BUILD_NO_DEBUG + addLogMove(LOG_LEVEL_DEBUG, F("P139: PLUGIN_PRIORITY_INIT")); + # endif // ifndef BUILD_NO_DEBUG + success = isPowerManagerTask; // Are we the PowerManager task? + break; + } + + case PLUGIN_GET_DEVICENAME: + { + string = F(PLUGIN_NAME_139); + break; + } + + case PLUGIN_GET_DEVICEVALUENAMES: + { + for (uint8_t i = 0; i < VARS_PER_TASK; ++i) { + if (i < P139_NR_OUTPUT_VALUES) { + const uint8_t choice = PCONFIG(P139_CONFIG_BASE + i); + ExtraTaskSettings.setTaskDeviceValueName(i, toString(static_cast(choice), false)); + + if ((choice != (static_cast(AXP2101_registers_e::battemp))) && + (choice != (static_cast(AXP2101_registers_e::chiptemp)))) { + ExtraTaskSettings.TaskDeviceValueDecimals[i] = 0; + } + } else { + ExtraTaskSettings.clearTaskDeviceValueName(i); + ExtraTaskSettings.TaskDeviceValueDecimals[i] = 0; + } + } + break; + } + + case PLUGIN_GET_DEVICEVALUECOUNT: + { + event->Par1 = P139_NR_OUTPUT_VALUES; + success = true; + break; + } + + case PLUGIN_GET_DEVICEVTYPE: + { + event->sensorType = static_cast(PCONFIG(P139_SENSOR_TYPE_INDEX)); + event->idx = P139_SENSOR_TYPE_INDEX; + success = true; + break; + } + + case PLUGIN_I2C_HAS_ADDRESS: + { + success = event->Par1 == AXP2101_ADDR; + break; + } + + # if FEATURE_I2C_GET_ADDRESS + case PLUGIN_I2C_GET_ADDRESS: + { + event->Par1 = AXP2101_ADDR; + success = true; + break; + } + # endif // if FEATURE_I2C_GET_ADDRESS + + case PLUGIN_SET_DEFAULTS: + { + PCONFIG(0) = static_cast(AXP2101_registers_e::dcdc1); + PCONFIG(1) = static_cast(AXP2101_registers_e::dcdc3); + PCONFIG(2) = static_cast(AXP2101_registers_e::aldo1); + PCONFIG(3) = static_cast(AXP2101_registers_e::dldo1); + PCONFIG(P139_SENSOR_TYPE_INDEX) = static_cast(Sensor_VType::SENSOR_TYPE_QUAD); + P139_CONFIG_DECIMALS = 2; // 2 decimals for all get config values + AXP2101_device_model_e device = AXP2101_device_model_e::M5Stack_Core2_v1_1; + P139_CURRENT_PREDEFINED = static_cast(device); // M5Stack Core2 v1.1 + P139_SET_GENERATE_EVENTS(true); + + P139_data_struct *P139_data = new (std::nothrow) P139_data_struct(); + + if (nullptr != P139_data) { + P139_data->applyDeviceModelTemplate(device); + P139_data->saveSettings(event); + delete P139_data; + } + + break; + } + + case PLUGIN_WEBFORM_LOAD: + { + bool created_new = false; + P139_data_struct *P139_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P139_data) { + P139_data = new (std::nothrow) P139_data_struct(); + P139_data->loadSettings(event); + created_new = true; + } + + if (nullptr != P139_data) { + P139_data->webform_load(event); + + if (created_new) { + delete P139_data; + } + + success = true; + } + + break; + } + + case PLUGIN_WEBFORM_LOAD_OUTPUT_SELECTOR: + { + const __FlashStringHelper *valOptions[AXP2101_register_count + 1]; + int valValues[AXP2101_register_count + 1]; + + valOptions[0] = F("None"); + valValues[0] = 0; + + for (int r = 0; r < AXP2101_register_count; ++r) { + AXP2101_registers_e reg = AXP2101_intToRegister(r); + valOptions[r + 1] = toString(reg); + valValues[r + 1] = static_cast(reg); + } + constexpr uint8_t valueCount = NR_ELEMENTS(valValues); + + for (uint8_t i = 0; i < P139_NR_OUTPUT_VALUES; ++i) { + sensorTypeHelper_loadOutputSelector(event, + P139_CONFIG_BASE + i, + i, + valueCount, + valOptions, + valValues); + } + + success = true; + break; + } + + case PLUGIN_WEBFORM_SAVE: + { + bool created_new = false; + P139_data_struct *P139_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr == P139_data) { + P139_data = new (std::nothrow) P139_data_struct(); + P139_data->loadSettings(event); + created_new = true; + } + + if (nullptr != P139_data) { + P139_data->webform_save(event); + + if (created_new) { + delete P139_data; + } + + success = true; + } + + break; + } + + case PLUGIN_INIT: + { + if (Settings.isI2CEnabled()) { + P139_data_struct *P139_init = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P139_init) { + # ifndef BUILD_NO_DEBUG + addLogMove(LOG_LEVEL_INFO, F("P139: Already initialized, skipped.")); + # endif // ifndef BUILD_NO_DEBUG + // has been initialized so nothing to do here + success = true; // Still was successful (to keep plugin enabled!) + } else { + # ifndef BUILD_NO_DEBUG + addLogMove(LOG_LEVEL_DEBUG, F("P139: PLUGIN_INIT")); + # endif // ifndef BUILD_NO_DEBUG + success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P139_data_struct(event)); + } + } else { + addLog(LOG_LEVEL_ERROR, F("AXP2101: I2C not enabled, initialization failed!")); + } + + break; + } + + case PLUGIN_READ: + { + P139_data_struct *P139_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P139_data) { + success = P139_data->plugin_read(event); + } + break; + } + + // case PLUGIN_TEN_PER_SECOND: + // { + // P139_data_struct *P139_data = static_cast(getPluginTaskData(event->TaskIndex)); + + // if (nullptr != P139_data) { + // success = P139_data->plugin_ten_per_second(event); + // } + // break; + // } + + case PLUGIN_FIFTY_PER_SECOND: + { + P139_data_struct *P139_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P139_data) { + success = P139_data->plugin_fifty_per_second(event); + } + break; + } + + case PLUGIN_WRITE: + { + P139_data_struct *P139_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P139_data) { + success = P139_data->plugin_write(event, string); + } + break; + } + + case PLUGIN_GET_CONFIG_VALUE: + { + P139_data_struct *P139_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P139_data) { + success = P139_data->plugin_get_config_value(event, string); // GetConfig operation, handle variables + } + break; + } + } + + return success; +} + +# endif // ifdef ESP32 +#endif // USES_P139 diff --git a/src/_P141_PCD8544_Nokia5110.ino b/src/_P141_PCD8544_Nokia5110.ino index c56f909411..7c79d281ad 100644 --- a/src/_P141_PCD8544_Nokia5110.ino +++ b/src/_P141_PCD8544_Nokia5110.ino @@ -148,12 +148,9 @@ boolean Plugin_141(uint8_t function, struct EventStruct *event, String& string) static_cast(P141_CommandTrigger::lcd), }; constexpr size_t optionCount = NR_ELEMENTS(commandTriggerOptions); - addFormSelector(F("Write Command trigger"), - F("pcmdtrigger"), - optionCount, - commandTriggers, - commandTriggerOptions, - P141_CONFIG_FLAG_GET_CMD_TRIGGER); + const FormSelectorOptions selector(optionCount, commandTriggers, commandTriggerOptions); + selector.addFormSelector( + F("Write Command trigger"), F("pcmdtrigger"), P141_CONFIG_FLAG_GET_CMD_TRIGGER); # ifndef LIMIT_BUILD_SIZE addFormNote(F("Select the command that is used to handle commands for this display.")); # endif // ifndef LIMIT_BUILD_SIZE diff --git a/src/_P142_AS5600.ino b/src/_P142_AS5600.ino index 260d8b27cb..d4e07480b5 100644 --- a/src/_P142_AS5600.ino +++ b/src/_P142_AS5600.ino @@ -173,12 +173,8 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_MODE_RADIANS, }; constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); - addFormSelector(F("Output range"), - F("range"), - optionCount, - configurations, - configurationOptions, - P142_GET_OUTPUT_MODE); + const FormSelectorOptions selector(optionCount, configurations, configurationOptions); + selector.addFormSelector(F("Output range"), F("range"), P142_GET_OUTPUT_MODE); } addFormCheckBox(F("Generate Events only when changed"), F("diff"), P142_GET_UPDATE_DIFF_ONLY); addFormCheckBox(F("Generate Events only when magnet detected"), F("cmag"), P142_GET_CHECK_MAGNET); @@ -212,12 +208,8 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_POWERMODE_LOW3, }; constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); - addFormSelector(F("Power mode"), - F("pow"), - optionCount, - configurations, - configurationOptions, - P142_GET_POWER_MODE); + const FormSelectorOptions selector(optionCount, configurations, configurationOptions); + selector.addFormSelector(F("Power mode"), F("pow"), P142_GET_POWER_MODE); } addFormCheckBox(F("Power watchdog"), F("wdog"), P142_GET_WATCHDOG); addFormNote(F("Switches to 'Low power mode 3' after 1 minute of less than 4 LSBs change")); @@ -237,12 +229,8 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_HYST_LSB3, }; constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); - addFormSelector(F("Hysteresis"), - F("hyst"), - optionCount, - configurations, - configurationOptions, - P142_GET_HYSTERESIS); + const FormSelectorOptions selector(optionCount, configurations, configurationOptions); + selector.addFormSelector(F("Hysteresis"), F("hyst"), P142_GET_HYSTERESIS); } { const __FlashStringHelper *configurations[] = { @@ -258,12 +246,8 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_SLOW_FILT_2X, }; constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); - addFormSelector(F("Slow filter"), - F("sflt"), - optionCount, - configurations, - configurationOptions, - P142_GET_SLOW_FILTER); + const FormSelectorOptions selector(optionCount, configurations, configurationOptions); + selector.addFormSelector(F("Slow filter"), F("sflt"), P142_GET_SLOW_FILTER); } { const __FlashStringHelper *configurations[] = { @@ -287,12 +271,8 @@ boolean Plugin_142(uint8_t function, struct EventStruct *event, String& string) AS5600_FAST_FILT_LSB10, }; constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); - addFormSelector(F("Fast filter"), - F("fflt"), - optionCount, - configurations, - configurationOptions, - P142_GET_FAST_FILTER); + const FormSelectorOptions selector(optionCount, configurations, configurationOptions); + selector.addFormSelector(F("Fast filter"), F("fflt"), P142_GET_FAST_FILTER); } success = true; break; diff --git a/src/_P143_I2C_Rotary.ino b/src/_P143_I2C_Rotary.ino index cfe4748341..6220281ccd 100644 --- a/src/_P143_I2C_Rotary.ino +++ b/src/_P143_I2C_Rotary.ino @@ -172,13 +172,9 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) # endif // if P143_FEATURE_INCLUDE_DFROBOT }; constexpr size_t optionCount = NR_ELEMENTS(selectModeValues); - addFormSelector(F("Encoder type"), - F("pdevice"), - optionCount, - selectModeOptions, - selectModeValues, - P143_ENCODER_TYPE, - true); + FormSelectorOptions selector(optionCount, selectModeOptions, selectModeValues); + selector.reloadonchange = true; + selector.addFormSelector(F("Encoder type"), F("pdevice"), P143_ENCODER_TYPE); addFormNote(F("Changing the Encoder type will reload the page and reset Encoder specific settings to default!")); } @@ -241,12 +237,8 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) static_cast(P143_M5StackLed_e::Led2Only), }; constexpr size_t optionCount = NR_ELEMENTS(selectLedModeValues); - addFormSelector(F("Color map Leds"), - F("pledsel"), - optionCount, - selectLedModeOptions, - selectLedModeValues, - P143_M5STACK_SELECTION); + const FormSelectorOptions selector(optionCount, selectLedModeOptions, selectLedModeValues); + selector.addFormSelector(F("Color map Leds"), F("pledsel"), P143_M5STACK_SELECTION); } # endif // if P143_FEATURE_INCLUDE_M5STACK break; @@ -287,12 +279,8 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) static_cast(P143_ButtonAction_e::ToggleSwitch), }; constexpr size_t optionCount = NR_ELEMENTS(selectButtonValues); - addFormSelector(F("Button action"), - F("pbutton"), - optionCount, - selectButtonOptions, - selectButtonValues, - P143_PLUGIN_BUTTON_ACTION); + const FormSelectorOptions selector(optionCount, selectButtonOptions, selectButtonValues); + selector.addFormSelector(F("Button action"), F("pbutton"), P143_PLUGIN_BUTTON_ACTION); # if P143_FEATURE_INCLUDE_DFROBOT @@ -330,12 +318,8 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) static_cast(P143_CounterMapping_e::ColorGradient), }; constexpr size_t optionCount = NR_ELEMENTS(selectCounterValues); - addFormSelector(F("Counter color mapping"), - F("pmap"), - optionCount, - selectCounterOptions, - selectCounterValues, - P143_PLUGIN_COUNTER_MAPPING); + const FormSelectorOptions selector(optionCount, selectCounterOptions, selectCounterValues); + selector.addFormSelector(F("Counter color mapping"), F("pmap"), P143_PLUGIN_COUNTER_MAPPING); } { String strings[P143_STRINGS]; @@ -351,7 +335,7 @@ boolean Plugin_143(uint8_t function, struct EventStruct *event, String& string) addHtml('#'); addHtmlInt(varNr + 1); html_TD(); - addTextBox(getPluginCustomArgName(varNr), strings[varNr], P143_STRING_LEN, false, false, EMPTY_STRING, F("xwide")); + addTextBox(getPluginCustomArgName(varNr), strings[varNr], P143_STRING_LEN, F("xwide")); } html_end_table(); } diff --git a/src/_P145_MQxxx.ino b/src/_P145_MQxxx.ino index 5e5e895797..41855fb61b 100644 --- a/src/_P145_MQxxx.ino +++ b/src/_P145_MQxxx.ino @@ -191,7 +191,8 @@ boolean Plugin_145(byte function, struct EventStruct *event, String& string) { options[i] = concat(concat(P145_data_struct::getTypeName(i), F(" - ")), P145_data_struct::getGasName(i)); } - addFormSelector(F("Sensor type"), F(P145_GUID_TYPE), x, options, nullptr, P145_PCONFIG_SENSORT); + const FormSelectorOptions selector(x, options); + selector.addFormSelector(F("Sensor type"), F(P145_GUID_TYPE), P145_PCONFIG_SENSORT); # ifdef ESP32 diff --git a/src/_P146_CacheControllerReader.ino b/src/_P146_CacheControllerReader.ino index 83edccd923..816f6a8cc4 100644 --- a/src/_P146_CacheControllerReader.ino +++ b/src/_P146_CacheControllerReader.ino @@ -221,7 +221,8 @@ boolean Plugin_146(uint8_t function, struct EventStruct *event, String& string) ';' }; constexpr size_t optionCount = NR_ELEMENTS(separatorOptions); - addFormSelector(F("Separator"), F("separator"), optionCount, separatorLabels, separatorOptions, P146_SEPARATOR_CHARACTER); + const FormSelectorOptions selector(optionCount, separatorLabels, separatorOptions); + selector.addFormSelector(F("Separator"), F("separator"), P146_SEPARATOR_CHARACTER); } addFormCheckBox(F("Join Samples with same Timestamp"), F("jointimestamp"), P146_GET_JOIN_TIMESTAMP); addFormCheckBox(F("Export only enabled tasks"), F("onlysettasks"), P146_GET_ONLY_SET_TASKS); diff --git a/src/_P147_SGP4x.ino b/src/_P147_SGP4x.ino index 98b859b677..9e084fedb0 100644 --- a/src/_P147_SGP4x.ino +++ b/src/_P147_SGP4x.ino @@ -119,7 +119,9 @@ boolean Plugin_147(uint8_t function, struct EventStruct *event, String& string) static_cast(P147_sensor_e::SGP41), }; constexpr size_t optionCount = NR_ELEMENTS(sensorTypeOptions); - addFormSelector(F("Sensor model"), F("ptype"), optionCount, sensorTypes, sensorTypeOptions, P147_SENSOR_TYPE, true); + FormSelectorOptions selector(optionCount, sensorTypes, sensorTypeOptions); + selector.reloadonchange = true; + selector.addFormSelector(F("Sensor model"), F("ptype"), P147_SENSOR_TYPE); # ifndef BUILD_NO_DEBUG addFormNote(F("Page will reload on change.")); # endif // ifndef BUILD_NO_DEBUG diff --git a/src/_P148_POWRxxD_THR3xxD.ino b/src/_P148_POWRxxD_THR3xxD.ino index 235e631356..f9948c6ad3 100644 --- a/src/_P148_POWRxxD_THR3xxD.ino +++ b/src/_P148_POWRxxD_THR3xxD.ino @@ -121,8 +121,8 @@ boolean Plugin_148(uint8_t function, struct EventStruct *event, String& string) static_cast(P148_data_struct::Tm1621Device::THR3xxD) }; constexpr size_t nrElements = NR_ELEMENTS(optionValues); - - addFormSelector(F("Device Template"), F("devtmpl"), nrElements, options, optionValues, P148_DEVICE_SELECTOR); + const FormSelectorOptions selector(nrElements, options, optionValues); + selector.addFormSelector(F("Device Template"), F("devtmpl"), P148_DEVICE_SELECTOR); addFormNote(F("GPIO settings will be ignored when selecting other than 'Custom'")); } diff --git a/src/_P150_TMP117.ino b/src/_P150_TMP117.ino index a0bb743723..2a21280e14 100644 --- a/src/_P150_TMP117.ino +++ b/src/_P150_TMP117.ino @@ -135,7 +135,8 @@ boolean Plugin_150(uint8_t function, struct EventStruct *event, String& string) P150_AVERAGING_64_SAMPLES, }; constexpr size_t optionCount = NR_ELEMENTS(averagingOptions); - addFormSelector(F("Averaging"), F("avg"), optionCount, averagingCaptions, averagingOptions, P150_GET_CONF_AVERAGING); + const FormSelectorOptions selector(optionCount, averagingCaptions, averagingOptions); + selector.addFormSelector(F("Averaging"), F("avg"), P150_GET_CONF_AVERAGING); } { @@ -148,13 +149,9 @@ boolean Plugin_150(uint8_t function, struct EventStruct *event, String& string) P150_CONVERSION_ONE_SHOT, }; constexpr size_t optionCount = NR_ELEMENTS(conversionOptions); - addFormSelector(F("Conversion mode"), - F("conv"), - optionCount, - conversionCaptions, - conversionOptions, - P150_GET_CONF_CONVERSION_MODE, - true); + FormSelectorOptions selector(optionCount, conversionCaptions, conversionOptions); + selector.reloadonchange = true; + selector.addFormSelector(F("Conversion mode"), F("conv"), P150_GET_CONF_CONVERSION_MODE); # ifndef BUILD_NO_DEBUG addFormNote(F("Changing this setting will save and reload this page.")); # endif // ifndef BUILD_NO_DEBUG @@ -182,8 +179,8 @@ boolean Plugin_150(uint8_t function, struct EventStruct *event, String& string) P150_CYCLE_16_SEC, }; constexpr size_t optionCount = NR_ELEMENTS(cycleOptions); - addFormSelector(F("Continuous conversion cycle time"), F("cycle"), optionCount, cycleCaptions, cycleOptions, - P150_GET_CONF_CYCLE_BITS); + const FormSelectorOptions selector(optionCount, cycleCaptions, cycleOptions); + selector.addFormSelector(F("Continuous conversion cycle time"), F("cycle"), P150_GET_CONF_CYCLE_BITS); } addFormSubHeader(F("Output")); diff --git a/src/_P153_SHT4x.ino b/src/_P153_SHT4x.ino index 22e2c55626..7d7b92eb8d 100644 --- a/src/_P153_SHT4x.ino +++ b/src/_P153_SHT4x.ino @@ -147,23 +147,19 @@ boolean Plugin_153(uint8_t function, struct EventStruct *event, String& string) static_cast(P153_configuration_e::HighResolution20mW100msec), }; constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); - addFormSelector(F("Startup Configuration"), - F("startup"), - optionCount, - configurations, - configurationOptions, - P153_STARTUP_CONFIGURATION); + const FormSelectorOptions selector(optionCount, configurations, configurationOptions); + selector.addFormSelector(F("Startup Configuration"), F("startup"), P153_STARTUP_CONFIGURATION); addFormNote(F("Heater should not exceed 10% dutycycle, so 1 sec. heater must have Interval > 10 sec.!")); addFormNumericBox(F("Use Normal Configuration after"), F("loops"), P153_INTERVAL_LOOPS, 0, 10); addUnit(F("Interval runs (0..10)")); - addFormSelector(F("Normal Configuration"), - F("normal"), - 3, // Only non-heater options - configurations, - configurationOptions, - P153_NORMAL_CONFIGURATION); + const FormSelectorOptions selector_normal( + 3, // Only non-heater options + configurations, configurationOptions); + + selector_normal.addFormSelector( + F("Normal Configuration"), F("normal"), P153_NORMAL_CONFIGURATION); } success = true; diff --git a/src/_P166_GP8403.ino b/src/_P166_GP8403.ino index 81c2557e72..e00eae4cd6 100644 --- a/src/_P166_GP8403.ino +++ b/src/_P166_GP8403.ino @@ -127,12 +127,8 @@ boolean Plugin_166(uint8_t function, struct EventStruct *event, String& string) static_cast(DFRobot_GP8403::eOutPutRange_t::eOutputRange10V), }; constexpr size_t optionCount = NR_ELEMENTS(configurationOptions); - addFormSelector(F("Output range"), - F("range"), - optionCount, - configurations, - configurationOptions, - P166_MAX_VOLTAGE); + const FormSelectorOptions selector(optionCount, configurations, configurationOptions); + selector.addFormSelector(F("Output range"), F("range"), P166_MAX_VOLTAGE); } addFormCheckBox(F("Restore output on warm boot"), F("prstr"), P166_RESTORE_VALUES == 1); diff --git a/src/_P167_Vindstyrka.ino b/src/_P167_Vindstyrka.ino index c31dfcbd92..2f03248567 100644 --- a/src/_P167_Vindstyrka.ino +++ b/src/_P167_Vindstyrka.ino @@ -176,9 +176,9 @@ boolean Plugin_167(uint8_t function, struct EventStruct *event, String& string) P167_MODEL_SEN55, }; constexpr uint8_t optCount = NR_ELEMENTS(options_model_value); - - addFormSelector(F("Model Type"), P167_MODEL_LABEL, optCount, - options_model, options_model_value, P167_MODEL, true); + FormSelectorOptions selector(optCount, options_model, options_model_value); + selector.reloadonchange = true; + selector.addFormSelector(F("Model Type"), P167_MODEL_LABEL, P167_MODEL); addFormNote(F("Changing the Model Type will reload the page.")); if (P167_MODEL == P167_MODEL_VINDSTYRKA) { diff --git a/src/_P168_VEML6030_7700.ino b/src/_P168_VEML6030_7700.ino index c5f7e23648..1a9aa30bcc 100644 --- a/src/_P168_VEML6030_7700.ino +++ b/src/_P168_VEML6030_7700.ino @@ -114,12 +114,8 @@ boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string) VEML_LUX_CORRECTED_NOWAIT, }; constexpr size_t optionCount = NR_ELEMENTS(readMethodOptions); - addFormSelector(F("Lux Read-method"), - F("rmth"), - optionCount, - readMethod, - readMethodOptions, - P168_READLUX_MODE); + const FormSelectorOptions selector(optionCount, readMethod, readMethodOptions); + selector.addFormSelector(F("Lux Read-method"), F("rmth"), P168_READLUX_MODE); addFormNote(F("For 'Auto' Read-method, the Gain factor and Integration time settings are ignored.")); } { @@ -136,21 +132,17 @@ boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string) 0b11, }; constexpr size_t optionCount = NR_ELEMENTS(alsGainOptions); - addFormSelector(F("Gain factor"), - F("gain"), - optionCount, - alsGain, - alsGainOptions, - P168_ALS_GAIN); + const FormSelectorOptions selector(optionCount, alsGain, alsGainOptions); + selector.addFormSelector(F("Gain factor"), F("gain"), P168_ALS_GAIN); } { const __FlashStringHelper *alsIntegration[] = { - F("25 ms"), - F("50 ms"), - F("100 ms"), - F("200 ms"), - F("400 ms"), - F("800 ms"), + F("25"), + F("50"), + F("100"), + F("200"), + F("400"), + F("800"), }; const int alsIntegrationOptions[] = { 0b1100, @@ -161,12 +153,9 @@ boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string) 0b0011, }; constexpr size_t optionCount = NR_ELEMENTS(alsIntegrationOptions); - addFormSelector(F("Integration time"), - F("int"), - optionCount, - alsIntegration, - alsIntegrationOptions, - P168_ALS_INTEGRATION); + const FormSelectorOptions selector(optionCount, alsIntegration, alsIntegrationOptions); + selector.addFormSelector(F("Integration time"), F("int"), P168_ALS_INTEGRATION); + addUnit(F("ms")); } addFormSeparator(2); { @@ -185,12 +174,8 @@ boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string) static_cast(P168_power_save_mode_e::Mode4), }; constexpr size_t optionCount = NR_ELEMENTS(psmModeOptions); - addFormSelector(F("Power Save Mode"), - F("psm"), - optionCount, - psmMode, - psmModeOptions, - P168_PSM_MODE); + const FormSelectorOptions selector(optionCount, psmMode, psmModeOptions); + selector.addFormSelector(F("Power Save Mode"), F("psm"), P168_PSM_MODE); } success = true; diff --git a/src/_P169_AS3935_LightningDetector.ino b/src/_P169_AS3935_LightningDetector.ino index 7655a70fec..1b15e9ee40 100644 --- a/src/_P169_AS3935_LightningDetector.ino +++ b/src/_P169_AS3935_LightningDetector.ino @@ -127,12 +127,11 @@ boolean Plugin_169(uint8_t function, struct EventStruct *event, String& string) AS3935MI::AS3935_MNL_9, AS3935MI::AS3935_MNL_16 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("Lightning Threshold"), - P169_LIGHTNING_THRESHOLD_LABEL, - optionCount, - options, - optionValues, - P169_LIGHTNING_THRESHOLD); + const FormSelectorOptions selector(optionCount, options, optionValues); + selector.addFormSelector( + F("Lightning Threshold"), + P169_LIGHTNING_THRESHOLD_LABEL, + P169_LIGHTNING_THRESHOLD); addFormNote(F("Minimum number of lightning strikes in the last 15 minutes")); } { @@ -159,8 +158,9 @@ boolean Plugin_169(uint8_t function, struct EventStruct *event, String& string) 18 }; constexpr size_t optionCount = NR_ELEMENTS(optionValues); - addFormSelector(F("AFE Gain Min"), P169_AFE_GAIN_LOW_LABEL, optionCount, options, optionValues, P169_AFE_GAIN_LOW); - addFormSelector(F("AFE Gain Max"), P169_AFE_GAIN_HIGH_LABEL, optionCount, options, optionValues, P169_AFE_GAIN_HIGH); + const FormSelectorOptions selector(optionCount, options, optionValues); + selector.addFormSelector(F("AFE Gain Min"), P169_AFE_GAIN_LOW_LABEL, P169_AFE_GAIN_LOW); + selector.addFormSelector(F("AFE Gain Max"), P169_AFE_GAIN_HIGH_LABEL, P169_AFE_GAIN_HIGH); addFormNote(F("Lower and upper limit for the Analog Frond-End auto gain to use.")); } diff --git a/src/include/ESPEasy_config.h b/src/include/ESPEasy_config.h index 7aecb45a54..8ccfe1643c 100644 --- a/src/include/ESPEasy_config.h +++ b/src/include/ESPEasy_config.h @@ -142,7 +142,6 @@ constexpr unsigned CEIL_LOG2(unsigned x) # endif // ifdef ESP8266 -// Start: Copied from PR #4977 (P139) # ifdef ESP8266 // (ESP8266) FsP: FlashstringHelper to String-Pointer @@ -161,7 +160,6 @@ constexpr unsigned CEIL_LOG2(unsigned x) # define FsP # endif // if defined(ESP32_CLASSIC) || defined(ESP32S2) || defined(ESP32S3) # endif // ifdef ESP32 -// End: Copied from PR #4977 (P139) // User configuration // Include Custom.h before ESPEasyDefaults.h. diff --git a/src/src/Controller_config/C018_config.cpp b/src/src/Controller_config/C018_config.cpp index c4fac1b5de..77369d0849 100644 --- a/src/src/Controller_config/C018_config.cpp +++ b/src/src/Controller_config/C018_config.cpp @@ -73,38 +73,40 @@ void C018_ConfigStruct::webform_load(C018_data_struct *C018_data) { addFormTextBox(F("App Session Key"), F("appskey"), AppSessionKey, C018_APP_SESSION_KEY_LEN - 1); { - const __FlashStringHelper *options[2] = { F("OTAA"), F("ABP") }; - const int values[2] = { C018_USE_OTAA, C018_USE_ABP }; - addFormSelector_script(F("Activation Method"), F("joinmethod"), 2, - options, values, nullptr, joinmethod, - F("joinChanged(this)")); // Script to toggle OTAA/ABP fields visibility when changing selection. + const __FlashStringHelper *options[] = { F("OTAA"), F("ABP") }; + //const int values[] = { C018_USE_OTAA, C018_USE_ABP }; + FormSelectorOptions selector(NR_ELEMENTS(options), options); + // Script to toggle OTAA/ABP fields visibility when changing selection. + selector.onChangeCall = F("joinChanged(this)"); + selector.addFormSelector(F("Activation Method"), F("joinmethod"), joinmethod); + } html_add_script(F("document.getElementById('joinmethod').onchange();"), false); addTableSeparator(F("Connection Configuration"), 2, 3); { - const __FlashStringHelper *options[4] = { F("SINGLE_CHANNEL_EU"), F("TTN_EU"), F("TTN_US"), F("DEFAULT_EU") }; - int values[4] = + const __FlashStringHelper *options[] = { F("SINGLE_CHANNEL_EU"), F("TTN_EU"), F("TTN_US"), F("DEFAULT_EU") }; + int values[] = { RN2xx3_datatypes::Freq_plan::SINGLE_CHANNEL_EU, RN2xx3_datatypes::Freq_plan::TTN_EU, RN2xx3_datatypes::Freq_plan::TTN_US, RN2xx3_datatypes::Freq_plan::DEFAULT_EU }; - - addFormSelector(F("Frequency Plan"), F("frequencyplan"), 4, options, values, nullptr, frequencyplan, false); + const FormSelectorOptions selector( NR_ELEMENTS(options), options, values); + selector.addFormSelector(F("Frequency Plan"), F("frequencyplan"), frequencyplan); addFormNumericBox(F("RX2 Frequency"), F("rx2freq"), rx2_freq, 0); addUnit(F("Hz")); addFormNote(F("0 = default, or else override default")); } { - const __FlashStringHelper *options[2] = { F("TTN v2"), F("TTN v3") }; - int values[2] = { + const __FlashStringHelper *options[] = { F("TTN v2"), F("TTN v3") }; + constexpr int values[] { RN2xx3_datatypes::TTN_stack_version::TTN_v2, RN2xx3_datatypes::TTN_stack_version::TTN_v3 }; - - addFormSelector(F("TTN Stack"), F("ttnstack"), 2, options, values, nullptr, stackVersion, false); + const FormSelectorOptions selector(NR_ELEMENTS(options), options, values); + selector.addFormSelector(F("TTN Stack"), F("ttnstack"), stackVersion); } addFormNumericBox(F("Spread Factor"), F("sf"), sf, 7, 12); diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index 4aebbee070..0f695283d5 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -1535,13 +1535,21 @@ To create/register a plugin, you have to : #if !defined(USES_P095) && defined(ESP32) && !defined(PLUGIN_BUILD_IR_EXTENDED) #define USES_P095 // TFT ILI9xxx #endif - #if !defined(USES_P137) && defined(ESP32) - #define USES_P137 // AXP192 + #if !defined(PLUGIN_BUILD_NORMAL_IRext) + // IRext builds do need quite a lot of build space + // Also it is quite unlikely those are running from a battery powered unit + // which are the boards that need these power management ICs ("PMIC") + #if !defined(USES_P137) && defined(ESP32) + #define USES_P137 // AXP192 + #endif + #if !defined(USES_P138) && defined(ESP32) + #define USES_P138 // IP5306 + #endif + #if !defined(USES_P139) && defined(ESP32) + #define USES_P139 // AXP2101 + #endif #endif - #if !defined(USES_P138) && defined(ESP32) - #define USES_P138 // IP5306 - #endif -#endif // ifdef PLUGIN_SET_COLLECTION +#endif #ifdef PLUGIN_SET_COLLECTION_A @@ -1746,6 +1754,9 @@ To create/register a plugin, you have to : #endif #if !defined(USES_P138) && defined(ESP32) #define USES_P138 // IP5306 + #endif + #if !defined(USES_P139) && defined(ESP32) + #define USES_P139 // AXP2101 #endif #if !defined(USES_P148) && defined(ESP32) #define USES_P148 // Sonoff POWR3xxD and THR3xxD display @@ -1847,6 +1858,9 @@ To create/register a plugin, you have to : #if !defined(USES_P138) && defined(ESP32) #define USES_P138 // IP5306 #endif + #if !defined(USES_P139) && defined(ESP32) + #define USES_P139 // AXP2101 + #endif #ifndef USES_P141 #define USES_P141 // PCD8544 Nokia 5110 #endif @@ -2067,6 +2081,9 @@ To create/register a plugin, you have to : #if !defined(USES_P137) && defined(ESP32) #define USES_P137 // AXP192 #endif + #if !defined(USES_P139) && defined(ESP32) + #define USES_P139 // AXP2101 + #endif #if FEATURE_PLUGIN_STATS && defined(ESP8266) // Does not fit in build #undef FEATURE_PLUGIN_STATS @@ -2414,7 +2431,7 @@ To create/register a plugin, you have to : #define USES_P138 // IP5306 #endif #ifndef USES_P139 -// #define USES_P139 // + #define USES_P139 // AXP2101 #endif #ifndef USES_P140 // #define USES_P140 // @@ -3397,7 +3414,7 @@ To create/register a plugin, you have to : #endif // ifndef USES_ESPEASY_CONSOLE_FALLBACK_PORT -#if !FEATURE_PLUGIN_PRIORITY && (defined(USES_P137) /*|| defined(USES_Pxxx)*/) +#if !FEATURE_PLUGIN_PRIORITY && (defined(USES_P137) || defined(USES_P139)) #undef FEATURE_PLUGIN_PRIORITY #define FEATURE_PLUGIN_PRIORITY 1 #endif diff --git a/src/src/DataTypes/FormSelectorOptions.cpp b/src/src/DataTypes/FormSelectorOptions.cpp new file mode 100644 index 0000000000..8b157d1f15 --- /dev/null +++ b/src/src/DataTypes/FormSelectorOptions.cpp @@ -0,0 +1,177 @@ +#include "../DataTypes/FormSelectorOptions.h" + +#include "../WebServer/Markup.h" +#include "../WebServer/Markup_Forms.h" +#include "../WebServer/HTML_wrappers.h" + +FormSelectorOptions::FormSelectorOptions() + : classname(F("wide")), _onlySelectorHead(true) +{} + + +FormSelectorOptions::FormSelectorOptions(int optionCount) + : classname(F("wide")), _optionCount(optionCount) +{} + +FormSelectorOptions::FormSelectorOptions( + int optionCount, + const int indices[], + const String attr[]) : + classname(F("wide")), + _optionCount(optionCount), + _indices(indices), + _attr_str(attr) +{} + +FormSelectorOptions::FormSelectorOptions( + int optionCount, + const String options[], + const int indices[], + const String attr[]) : + classname(F("wide")), + _optionCount(optionCount), + _names_str(options), + _indices(indices), + _attr_str(attr) +{} + +FormSelectorOptions::FormSelectorOptions( + int optionCount, + const __FlashStringHelper *options[], + const int indices[], + const String attr[]) : + classname(F("wide")), + _optionCount(optionCount), + _names_f(options), + _indices(indices), + _attr_str(attr) +{} + +FormSelectorOptions::~FormSelectorOptions() {} + +String FormSelectorOptions::getOptionString(int index) const +{ + if (index >= _optionCount) { + return EMPTY_STRING; + } + + if (_names_f != nullptr) { + return String(_names_f[index]); + } + + if (_names_str != nullptr) { + return String(_names_str[index]); + } + + if (_indices != nullptr) { + return String(_indices[index]); + } + return String(index); +} + +int FormSelectorOptions::getIndexValue(int index) const +{ + if (index >= _optionCount) { + return -1; + } + + if (_indices != nullptr) { + return _indices[index]; + } + return index; +} + +bool FormSelectorOptions::isDone(int index) const +{ + return index >= _optionCount; +} + +void FormSelectorOptions::clearClassName() +{ + classname = F(""); +} + +void FormSelectorOptions::addFormSelector( + const __FlashStringHelper *label, + const __FlashStringHelper *id, + int selectedIndex) const +{ + addFormSelector(String(label), String(id), selectedIndex); +} + +void FormSelectorOptions::addFormSelector( + const String & label, + const __FlashStringHelper *id, + int selectedIndex) const +{ + addFormSelector(label, String(id), selectedIndex); +} + +void FormSelectorOptions::addFormSelector( + const __FlashStringHelper *label, + const String & id, + int selectedIndex) const +{ + addFormSelector(String(label), id, selectedIndex); +} + +void FormSelectorOptions::addFormSelector( + const String& label, + const String& id, + int selectedIndex) const +{ + addRowLabel_tr_id(label, id); + addSelector(id, selectedIndex); +} + +void FormSelectorOptions::addSelector(const __FlashStringHelper *id, + int selectedIndex) const +{ + addSelector(String(id), selectedIndex); +} + +void FormSelectorOptions::addSelector(const String& id, + int selectedIndex) const +{ + // FIXME TD-er Change bool 'enabled' to disabled + if (reloadonchange) + { + addSelector_Head_reloadOnChange(id, classname, !enabled + #if FEATURE_TOOLTIPS + , tooltip + #endif // if FEATURE_TOOLTIPS + ); + } else { + do_addSelector_Head(id, classname, onChangeCall, !enabled + #if FEATURE_TOOLTIPS + , tooltip + #endif // if FEATURE_TOOLTIPS + ); + } + + if (_onlySelectorHead) { return; } + + for (int i = 0; !isDone(i); ++i) + { + const int index = getIndexValue(i); + String optionString = getOptionString(i); + if (index == default_index) { + optionString += F(" (default)"); + } + addSelector_Item( + optionString, + index, + selectedIndex == index, + false, + _attr_str ? _attr_str[i] : EMPTY_STRING); + + if ((i & 0x07) == 0) { delay(0); } + } + + addSelectorFoot(); +} + +void FormSelectorOptions::addSelectorFoot() const +{ + addSelector_Foot(reloadonchange); +} diff --git a/src/src/DataTypes/FormSelectorOptions.h b/src/src/DataTypes/FormSelectorOptions.h new file mode 100644 index 0000000000..c09791fe45 --- /dev/null +++ b/src/src/DataTypes/FormSelectorOptions.h @@ -0,0 +1,87 @@ +#ifndef DATATYPES_FORMSELECTOROPTIONS_H +#define DATATYPES_FORMSELECTOROPTIONS_H + +#include "../../ESPEasy_common.h" + +class FormSelectorOptions { +public: + + FormSelectorOptions(); + + FormSelectorOptions(int optionCount); + + FormSelectorOptions(int optionCount, + const int indices[], + const String attr[] = nullptr); + + FormSelectorOptions(int optionCount, + const String options[], + const int indices[] = nullptr, + const String attr[] = nullptr); + FormSelectorOptions(int optionCount, + const __FlashStringHelper *options[], + const int indices[] = nullptr, + const String attr[] = nullptr); + + + virtual ~FormSelectorOptions(); + + // Return either a string representation of the current index, + // or the override implementation in a class inheriting of this class + virtual String getOptionString(int index) const; + + virtual int getIndexValue(int index) const; + + virtual bool isDone(int index) const; + + void clearClassName(); + + void addFormSelector(const __FlashStringHelper *label, + const __FlashStringHelper *id, + int selectedIndex) const; + + void addFormSelector(const String & label, + const __FlashStringHelper *id, + int selectedIndex) const; + + void addFormSelector(const __FlashStringHelper *label, + const String & id, + int selectedIndex) const; + + void addFormSelector(const String& label, + const String& id, + int selectedIndex) const; + + + void addSelector(const __FlashStringHelper *id, + int selectedIndex) const; + + void addSelector(const String& id, + int selectedIndex) const; + + + void addSelectorFoot() const; + + bool reloadonchange = false; + bool enabled = true; + const __FlashStringHelper *classname; +#if FEATURE_TOOLTIPS + String tooltip; +#endif // if FEATURE_TOOLTIPS + String onChangeCall; + + // Allow to add "(default)" to some option. + int default_index = -1; + +protected: + + const int _optionCount{}; + const __FlashStringHelper **_names_f{ nullptr }; + const String *_names_str{ nullptr }; + const int *_indices{ nullptr }; + const String *_attr_str{ nullptr }; + bool _onlySelectorHead = false; +}; + + +#endif // ifndef DATATYPES_FORMSELECTOROPTIONS_H diff --git a/src/src/Helpers/AdafruitGFX_helper.cpp b/src/src/Helpers/AdafruitGFX_helper.cpp index fb9171c026..7503ca6eaf 100644 --- a/src/src/Helpers/AdafruitGFX_helper.cpp +++ b/src/src/Helpers/AdafruitGFX_helper.cpp @@ -210,14 +210,17 @@ void AdaGFXFormTextPrintMode(const __FlashStringHelper *id, toString(AdaGFXTextPrintMode::ClearThenTruncate), toString(AdaGFXTextPrintMode::TruncateExceedingCentered), }; + /* const int textModeOptions[] = { static_cast(AdaGFXTextPrintMode::ContinueToNextLine), static_cast(AdaGFXTextPrintMode::TruncateExceedingMessage), static_cast(AdaGFXTextPrintMode::ClearThenTruncate), static_cast(AdaGFXTextPrintMode::TruncateExceedingCentered), }; + */ - addFormSelector(F("Text print Mode"), id, sizeof(textModeOptions) / sizeof(int), textModes, textModeOptions, selectedIndex); + const FormSelectorOptions selector(NR_ELEMENTS(textModes), textModes); + selector.addFormSelector(F("Text print Mode"), id, selectedIndex); } void AdaGFXFormColorDepth(const __FlashStringHelper *id, @@ -266,7 +269,9 @@ void AdaGFXFormColorDepth(const __FlashStringHelper *id, }; addRowLabel_tr_id(F("Display Color-depth"), id); - addSelector(id, colorDepthCount, colorDepths, colorDepthOptions, NULL, selectedIndex, false, enabled); + FormSelectorOptions selector(colorDepthCount, colorDepths, colorDepthOptions); + selector.enabled = enabled; + selector.addSelector(id, selectedIndex); } /***************************************************************************************** @@ -275,9 +280,9 @@ void AdaGFXFormColorDepth(const __FlashStringHelper *id, void AdaGFXFormRotation(const __FlashStringHelper *id, uint8_t selectedIndex) { const __FlashStringHelper *rotationOptions[] = { F("Normal"), F("+90°"), F("+180°"), F("+270°") }; - const int rotationOptionValues[] = { 0, 1, 2, 3 }; - - addFormSelector(F("Rotation"), id, 4, rotationOptions, rotationOptionValues, selectedIndex); +// const int rotationOptionValues[] = { 0, 1, 2, 3 }; + const FormSelectorOptions selector(NR_ELEMENTS(rotationOptions), rotationOptions); + selector.addFormSelector(F("Rotation"), id, selectedIndex); } /***************************************************************************************** @@ -399,7 +404,7 @@ void AdaGFXFormFontScaling(const __FlashStringHelper *fontScalingId, void AdaGFXFormLineSpacing(const __FlashStringHelper *id, uint8_t selectedIndex) { String lineSpacings[16]; - int lineSpacingOptions[16]; +// int lineSpacingOptions[16]; for (uint8_t i = 0; i < 16; ++i) { if (15 == i) { @@ -411,9 +416,10 @@ void AdaGFXFormLineSpacing(const __FlashStringHelper *id, } else { lineSpacings[i] = i; } - lineSpacingOptions[i] = i; +// lineSpacingOptions[i] = i; } - addFormSelector(F("Linespacing"), id, 16, lineSpacings, lineSpacingOptions, selectedIndex); + const FormSelectorOptions selector(16, lineSpacings); + selector.addFormSelector(F("Linespacing"), id, selectedIndex); addUnit(F("px")); } diff --git a/src/src/Helpers/ESPEasy_TouchHandler.cpp b/src/src/Helpers/ESPEasy_TouchHandler.cpp index b78e5adb87..fdc98a2fea 100644 --- a/src/src/Helpers/ESPEasy_TouchHandler.cpp +++ b/src/src/Helpers/ESPEasy_TouchHandler.cpp @@ -889,7 +889,8 @@ bool ESPEasy_TouchHandler::plugin_webform_load(struct EventStruct *event) { # endif // if TOUCH_FEATURE_EXTENDED_TOUCH }; const int optionValues3[] = { 0, 1, 3, 4, 5, 7 }; // Already used as a bitmap! - addFormSelector(F("Events"), F("events"), NR_ELEMENTS(optionValues3), options3, optionValues3, choice3); + const FormSelectorOptions selector(NR_ELEMENTS(optionValues3), options3, optionValues3); + selector.addFormSelector(F("Events"), F("events"), choice3); addFormCheckBox(F("Draw buttons when started"), F("initobj"), bitRead(Touch_Settings.flags, TOUCH_FLAGS_INIT_OBJECTEVENT)); # ifndef LIMIT_BUILD_SIZE @@ -915,17 +916,10 @@ bool ESPEasy_TouchHandler::plugin_webform_load(struct EventStruct *event) { addFormSubHeader(F("Calibration")); - { - const __FlashStringHelper *noYesOptions[2] = { F("No"), F("Yes") }; - const int noYesOptionValues[2] = { 0, 1 }; - addFormSelector(F("Calibrate to screen resolution"), - F("usecalib"), - 2, - noYesOptions, - noYesOptionValues, - Touch_Settings.calibrationEnabled ? 1 : 0, - true); - } + addFormSelector_YesNo(F("Calibrate to screen resolution"), + F("usecalib"), + Touch_Settings.calibrationEnabled ? 1 : 0, + true); // reloadonchange if (Touch_Settings.calibrationEnabled) { addRowLabel(F("Calibration")); @@ -1220,7 +1214,7 @@ bool ESPEasy_TouchHandler::plugin_webform_load(struct EventStruct *event) { addTextBox(getPluginCustomArgName(objectNr + 100), TouchObjects[objectNr].objectName, TOUCH_MaxObjectNameLength, - false, false, EMPTY_STRING, F("wide")); + F("wide")); html_TD(); // top-x addNumericBox(getPluginCustomArgName(objectNr + 200), TouchObjects[objectNr].top_left.x, 0, 65535 @@ -1237,27 +1231,39 @@ bool ESPEasy_TouchHandler::plugin_webform_load(struct EventStruct *event) { ); html_TD(); // (on/off) button (type) # if TOUCH_FEATURE_EXTENDED_TOUCH - addSelector(getPluginCustomArgName(objectNr + 800), - sizeof(buttonTypeValues) / sizeof(int), - buttonTypeOptions, - buttonTypeValues, - nullptr, - get4BitFromUL(TouchObjects[objectNr].flags, TOUCH_OBJECT_FLAG_BUTTONTYPE), false, true, F("widenumber") - # if TOUCH_FEATURE_TOOLTIPS - , F("Button") - # endif // if TOUCH_FEATURE_TOOLTIPS - ); - html_TD(); // button alignment - addSelector(getPluginCustomArgName(objectNr + 900), - sizeof(buttonLayoutValues) / sizeof(int), - buttonLayoutOptions, - buttonLayoutValues, - nullptr, - get4BitFromUL(TouchObjects[objectNr].flags, TOUCH_OBJECT_FLAG_BUTTONALIGN) << 4, false, true, F("widenumber") - # if TOUCH_FEATURE_TOOLTIPS - , F("Layout") - # endif // if TOUCH_FEATURE_TOOLTIPS - ); + { + FormSelectorOptions selector( + NR_ELEMENTS(buttonTypeValues), + buttonTypeOptions, + buttonTypeValues); + selector.classname = F("widenumber"); +# if TOUCH_FEATURE_TOOLTIPS + selector.tooltip = F("Button"); +# endif // if TOUCH_FEATURE_TOOLTIPS + + selector.addSelector( + getPluginCustomArgName(objectNr + 800), + get4BitFromUL( + TouchObjects[objectNr].flags, + TOUCH_OBJECT_FLAG_BUTTONTYPE)); + } + { + html_TD(); // button alignment + FormSelectorOptions selector( + NR_ELEMENTS(buttonLayoutOptions), + buttonLayoutOptions, + buttonLayoutValues); + selector.classname = F("widenumber"); +# if TOUCH_FEATURE_TOOLTIPS + selector.tooltip = F("Layout"); +# endif // if TOUCH_FEATURE_TOOLTIPS + + selector.addSelector( + getPluginCustomArgName(objectNr + 900), + get4BitFromUL( + TouchObjects[objectNr].flags, + TOUCH_OBJECT_FLAG_BUTTONALIGN) << 4); + } # else // if TOUCH_FEATURE_EXTENDED_TOUCH addCheckBox(getPluginCustomArgName(objectNr + 600), bitRead(TouchObjects[objectNr].flags, TOUCH_OBJECT_FLAG_BUTTON), false @@ -1308,20 +1314,23 @@ bool ESPEasy_TouchHandler::plugin_webform_load(struct EventStruct *event) { # endif // if TOUCH_FEATURE_TOOLTIPS , F("adagfx65kcolors") ); - html_TD(); // button action - addSelector(getPluginCustomArgName(objectNr + 2000), - sizeof(touchActionValues) / sizeof(int), - touchActionOptions, - touchActionValues, - nullptr, - get4BitFromUL(TouchObjects[objectNr].groupFlags, TOUCH_OBJECT_GROUP_ACTION), - false, - true, - F("widenumber") - # if TOUCH_FEATURE_TOOLTIPS - , F("Touch action") - # endif // if TOUCH_FEATURE_TOOLTIPS - ); + { + html_TD(); // button action + FormSelectorOptions selector( + NR_ELEMENTS(touchActionOptions), + touchActionOptions, + touchActionValues); + selector.classname = F("widenumber"); +# if TOUCH_FEATURE_TOOLTIPS + selector.tooltip = F("Touch action"); +# endif // if TOUCH_FEATURE_TOOLTIPS + + selector.addSelector( + getPluginCustomArgName(objectNr + 2000), + get4BitFromUL( + TouchObjects[objectNr].groupFlags, + TOUCH_OBJECT_GROUP_ACTION)); + } # endif // if TOUCH_FEATURE_EXTENDED_TOUCH html_TR_TD(); // Start new row diff --git a/src/src/Helpers/OLed_helper.cpp b/src/src/Helpers/OLed_helper.cpp index 9e0d379d0d..b7ffe4dc34 100644 --- a/src/src/Helpers/OLed_helper.cpp +++ b/src/src/Helpers/OLed_helper.cpp @@ -6,15 +6,16 @@ void OLedFormController(const __FlashStringHelper *id, const int *values, uint8_t selectedIndex) { - const __FlashStringHelper *controllerOptions[2] = { + const __FlashStringHelper *controllerOptions[] = { F("SSD1306 (128x64 dot controller)"), F("SH1106 (132x64 dot controller)") }; - const int controllerValues[2] = { - 1, - 2 }; - - addFormSelector(F("Controller"), id, 2, controllerOptions, values == nullptr ? controllerValues : values, selectedIndex); + const int controllerValues[] = { 1, 2 }; + const FormSelectorOptions selector( + NR_ELEMENTS(controllerOptions), + controllerOptions, + values == nullptr ? controllerValues : values); + selector.addFormSelector(F("Controller"), id, selectedIndex); } /************************************************************************** @@ -28,8 +29,10 @@ void OLedFormRotation(const __FlashStringHelper *id, const int rotationValues[] = { 1, 2 }; - - addFormSelector(F("Rotation"), id, 2, rotationOptions, rotationValues, selectedIndex); + const FormSelectorOptions selector( + NR_ELEMENTS(rotationOptions), + rotationOptions, rotationValues); + selector.addFormSelector(F("Rotation"), id, selectedIndex); } /************************************************************************** @@ -45,8 +48,14 @@ void OLedFormContrast(const __FlashStringHelper *id, OLED_CONTRAST_LOW, OLED_CONTRAST_MED, OLED_CONTRAST_HIGH }; + const FormSelectorOptions selector( + NR_ELEMENTS(contrastOptions), + contrastOptions, contrastValues); - addFormSelector(F("Contrast"), id, 3, contrastOptions, contrastValues, selectedIndex == 0 ? OLED_CONTRAST_HIGH : selectedIndex); + selector.addFormSelector( + F("Contrast"), + id, + selectedIndex == 0 ? OLED_CONTRAST_HIGH : selectedIndex); } /************************************************************************** @@ -56,12 +65,16 @@ void OLedFormSizes(const __FlashStringHelper *id, const int *values, uint8_t selectedIndex, bool reloadOnChange) { - const __FlashStringHelper *options3[3] = { + const __FlashStringHelper *options3[] = { F("128x64"), F("128x32"), F("64x48") }; - - addFormSelector(F("Display Size"), id, 3, options3, values, selectedIndex, reloadOnChange); + FormSelectorOptions selector(NR_ELEMENTS(options3), options3, values); + selector.reloadonchange = reloadOnChange; + selector.addFormSelector( + F("Display Size"), + id, + selectedIndex); } /************************************************************************** diff --git a/src/src/Helpers/_CPlugin_Helper_webform.cpp b/src/src/Helpers/_CPlugin_Helper_webform.cpp index 02342f16ee..f9a193ddd7 100644 --- a/src/src/Helpers/_CPlugin_Helper_webform.cpp +++ b/src/src/Helpers/_CPlugin_Helper_webform.cpp @@ -169,11 +169,13 @@ void addControllerParameterForm(const ControllerSettingsStruct & ControllerSett switch (varType) { case ControllerSettingsStruct::CONTROLLER_USE_DNS: { - const __FlashStringHelper *options[2] = { + const __FlashStringHelper *options[] = { F("Use IP address"), F("Use Hostname") }; - addFormSelector(displayName, internalName, 2, options, nullptr, nullptr, ControllerSettings.UseDNS, true); + FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.reloadonchange = true; + selector.addFormSelector(displayName, internalName, ControllerSettings.UseDNS); break; } case ControllerSettingsStruct::CONTROLLER_HOSTNAME: @@ -195,7 +197,7 @@ void addControllerParameterForm(const ControllerSettingsStruct & ControllerSett case ControllerSettingsStruct::CONTROLLER_MQTT_TLS_TYPE: { const int choice = static_cast(ControllerSettings.TLStype()); - const __FlashStringHelper *options[] = { + const __FlashStringHelper *options[]{ toString(TLS_types::NoTLS), // toString(TLS_types::TLS_PSK), @@ -207,7 +209,7 @@ void addControllerParameterForm(const ControllerSettingsStruct & ControllerSett */ toString(TLS_types::TLS_insecure) }; - const int indices[] = { + constexpr int indices[] = { static_cast(TLS_types::NoTLS), // static_cast(TLS_types::TLS_PSK), @@ -220,7 +222,9 @@ void addControllerParameterForm(const ControllerSettingsStruct & ControllerSett static_cast(TLS_types::TLS_insecure) }; constexpr int nrOptions = NR_ELEMENTS(indices); - addFormSelector(displayName, internalName, nrOptions, options, indices, choice, true); + FormSelectorOptions selector(nrOptions, options, indices); + selector.reloadonchange = true; + selector.addFormSelector(displayName, internalName, choice); addCertificateFileNote(ControllerSettings, F("Certificate or FingerPrint must be stored on the filesystem in"), ControllerSettings.TLStype()); @@ -300,11 +304,12 @@ void addControllerParameterForm(const ControllerSettingsStruct & ControllerSett } case ControllerSettingsStruct::CONTROLLER_FULL_QUEUE_ACTION: { - const __FlashStringHelper *options[2] { + const __FlashStringHelper *options[] { F("Ignore New"), F("Delete Oldest") }; - addFormSelector(displayName, internalName, 2, options, nullptr, nullptr, ControllerSettings.DeleteOldest, false); + const FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.addFormSelector(displayName, internalName, ControllerSettings.DeleteOldest); break; } case ControllerSettingsStruct::CONTROLLER_ALLOW_EXPIRE: @@ -318,11 +323,12 @@ void addControllerParameterForm(const ControllerSettingsStruct & ControllerSett break; case ControllerSettingsStruct::CONTROLLER_CHECK_REPLY: { - const __FlashStringHelper *options[2] = { + const __FlashStringHelper *options[] = { F("Ignore Acknowledgement"), F("Check Acknowledgement") }; - addFormSelector(displayName, internalName, 2, options, nullptr, nullptr, ControllerSettings.MustCheckReply, false); + const FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.addFormSelector(displayName, internalName, ControllerSettings.MustCheckReply); break; } case ControllerSettingsStruct::CONTROLLER_CLIENT_ID: @@ -424,18 +430,14 @@ void saveControllerParameterForm(ControllerSettingsStruct & ControllerSet #if FEATURE_MQTT_TLS case ControllerSettingsStruct::CONTROLLER_MQTT_TLS_TYPE: { - # if FEATURE_MQTT_TLS const int current = static_cast(ControllerSettings.TLStype()); const TLS_types tls_type = static_cast(getFormItemInt(internalName, current)); ControllerSettings.TLStype(tls_type); - # endif // if FEATURE_MQTT_TLS break; } case ControllerSettingsStruct::CONTROLLER_MQTT_TLS_STORE_FINGERPRINT: { - # if FEATURE_MQTT_TLS - if (isFormItemChecked(internalName)) { String fingerprint; @@ -447,7 +449,6 @@ void saveControllerParameterForm(ControllerSettingsStruct & ControllerSet SaveCertificate(ControllerSettings.getCertificateFilename(TLS_types::TLS_FINGERPRINT), fingerprint); } } - # endif // if FEATURE_MQTT_TLS break; } @@ -455,8 +456,6 @@ void saveControllerParameterForm(ControllerSettingsStruct & ControllerSet // fall through case ControllerSettingsStruct::CONTROLLER_MQTT_TLS_STORE_CACERT: { - # if FEATURE_MQTT_TLS - if (isFormItemChecked(internalName)) { String cacert; @@ -464,7 +463,6 @@ void saveControllerParameterForm(ControllerSettingsStruct & ControllerSet SaveCertificate(ControllerSettings.getCertificateFilename(TLS_types::TLS_CA_CERT), cacert); } } - # endif // if FEATURE_MQTT_TLS break; } #endif // if FEATURE_MQTT_TLS diff --git a/src/src/Helpers/_Internal_GPIO_pulseHelper.cpp b/src/src/Helpers/_Internal_GPIO_pulseHelper.cpp index 047e826ff6..ccba8caa89 100644 --- a/src/src/Helpers/_Internal_GPIO_pulseHelper.cpp +++ b/src/src/Helpers/_Internal_GPIO_pulseHelper.cpp @@ -47,7 +47,8 @@ void Internal_GPIO_pulseHelper::addGPIOtriggerMode(const __FlashStringHelper *la for (int i = 0; i < NR_TRIGGER_MODES; ++i) { options[i] = Internal_GPIO_pulseHelper::toString(static_cast(optionValues[i])); } - addFormSelector(label, id, NR_TRIGGER_MODES, options, optionValues, static_cast(currentSelection)); + const FormSelectorOptions selector( NR_TRIGGER_MODES, options, optionValues); + selector.addFormSelector(label, id, static_cast(currentSelection)); } Internal_GPIO_pulseHelper::Internal_GPIO_pulseHelper(Internal_GPIO_pulseHelper::pulseCounterConfig configuration) diff --git a/src/src/Helpers/_Plugin_Helper_serial.cpp b/src/src/Helpers/_Plugin_Helper_serial.cpp index 1575a266b4..f3a495be43 100644 --- a/src/src/Helpers/_Plugin_Helper_serial.cpp +++ b/src/src/Helpers/_Plugin_Helper_serial.cpp @@ -153,15 +153,18 @@ void serialHelper_addI2CuartSelectors(int address, int channel) { if ((channel != SC16IS752_CHANNEL_A) && (channel != SC16IS752_CHANNEL_B)) { channel = SC16IS752_CHANNEL_A; } - const __FlashStringHelper *chOptions[SC16IS752_CHANNELS] = { + const __FlashStringHelper *chOptions[] = { F("A"), F("B"), }; - const int chValues[SC16IS752_CHANNELS] = { + /* + const int chValues[] = { SC16IS752_CHANNEL_A, SC16IS752_CHANNEL_B, }; - addFormSelector(F("Channel"), F("i2cuart_ch"), SC16IS752_CHANNELS, chOptions, chValues, channel); + */ + const FormSelectorOptions selector(NR_ELEMENTS(chOptions), chOptions); + selector.addFormSelector(F("Channel"), F("i2cuart_ch"), channel); } } @@ -301,10 +304,13 @@ void serialHelper_webformLoad(ESPEasySerialPort port, int rxPinDef, int txPinDef #endif options[i] = option; } - addFormSelector_script(F("Serial Port"), F("serPort"), NR_ESPEASY_SERIAL_TYPES, - options, ids, nullptr, - static_cast(ESPeasySerialType::getSerialType(port, rxPinDef, txPinDef)), - F("serialPortChanged(this)")); // Script to toggle GPIO visibility when changing selection. + FormSelectorOptions selector(NR_ESPEASY_SERIAL_TYPES, options, ids); + + // Script to toggle GPIO visibility when changing selection. + selector.onChangeCall = F("serialPortChanged(this)"); + selector.addFormSelector( + F("Serial Port"), F("serPort"), + static_cast(ESPeasySerialType::getSerialType(port, rxPinDef, txPinDef))); #if USES_I2C_SC16IS752 serialHelper_addI2CuartSelectors(rxPinDef, txPinDef); #endif // ifndef DISABLE_SC16IS752_Serial diff --git a/src/src/Helpers/_Plugin_Helper_webform.cpp b/src/src/Helpers/_Plugin_Helper_webform.cpp index d49fdde76c..0cc1475eef 100644 --- a/src/src/Helpers/_Plugin_Helper_webform.cpp +++ b/src/src/Helpers/_Plugin_Helper_webform.cpp @@ -52,12 +52,12 @@ void SwitchWebformLoad( SWITCH_DC_HIGH, SWITCH_DC_BOTH }; - addFormSelector( + const FormSelectorOptions selector(NR_ELEMENTS(buttonDCValues), + buttonDC, + buttonDCValues); + selector.addFormSelector( F("Doubleclick event"), F("sw_dc"), - NR_ELEMENTS(buttonDCValues), - buttonDC, - buttonDCValues, doubleClickEvent); } @@ -84,12 +84,14 @@ void SwitchWebformLoad( SWITCH_LONGPRESS_LOW, SWITCH_LONGPRESS_HIGH, SWITCH_LONGPRESS_BOTH }; - addFormSelector( - F("Longpress event"), - F("sw_lp"), + + const FormSelectorOptions selector( NR_ELEMENTS(buttonLPValues), buttonLP, - buttonLPValues, + buttonLPValues); + selector.addFormSelector( + F("Longpress event"), + F("sw_lp"), longPressEvent); } diff --git a/src/src/Helpers/_Plugin_SensorTypeHelper.cpp b/src/src/Helpers/_Plugin_SensorTypeHelper.cpp index d51c4dd4b6..434abdc48e 100644 --- a/src/src/Helpers/_Plugin_SensorTypeHelper.cpp +++ b/src/src/Helpers/_Plugin_SensorTypeHelper.cpp @@ -142,13 +142,13 @@ void sensorTypeHelper_loadOutputSelector( if (pconfigIndex < 0 || pconfigIndex >= PLUGIN_CONFIGVAR_MAX) { return; } - - addFormSelector( - concat(F("Value "), valuenr + 1), - sensorTypeHelper_webformID(pconfigIndex), + const FormSelectorOptions selector( optionCount, options, - indices, + indices); + selector.addFormSelector( + concat(F("Value "), valuenr + 1), + sensorTypeHelper_webformID(pconfigIndex), PCONFIG(pconfigIndex)); } @@ -159,13 +159,13 @@ void sensorTypeHelper_loadOutputSelector( if (pconfigIndex < 0 || pconfigIndex >= PLUGIN_CONFIGVAR_MAX) { return; } - - addFormSelector( - concat(F("Value "), valuenr + 1), - sensorTypeHelper_webformID(pconfigIndex), + const FormSelectorOptions selector( optionCount, options, - indices, + indices); + selector.addFormSelector( + concat(F("Value "), valuenr + 1), + sensorTypeHelper_webformID(pconfigIndex), PCONFIG(pconfigIndex)); } diff --git a/src/src/PluginStructs/P002_data_struct.cpp b/src/src/PluginStructs/P002_data_struct.cpp index 32ea337d42..760cf37ede 100644 --- a/src/src/PluginStructs/P002_data_struct.cpp +++ b/src/src/PluginStructs/P002_data_struct.cpp @@ -101,7 +101,7 @@ void P002_data_struct::webformLoad_2p_calibPoint( float value) const { addRowLabel_tr_id(label, id_point); - addTextBox(id_point, String(point), 10, false, false, EMPTY_STRING, F("number")); + addTextBox(id_point, String(point), 10, F("number")); # ifdef ESP32 @@ -113,7 +113,7 @@ void P002_data_struct::webformLoad_2p_calibPoint( html_add_estimate_symbol(); const unsigned int display_nrDecimals = _nrDecimals > 3 ? _nrDecimals : 3; - addTextBox(id_value, toString(value, display_nrDecimals), 10, false, false, EMPTY_STRING, F("number")); + addTextBox(id_value, toString(value, display_nrDecimals), 10, F("number")); } void P002_data_struct::webformLoad(struct EventStruct *event) @@ -154,7 +154,8 @@ void P002_data_struct::webformLoad(struct EventStruct *event) P002_ADC_0db }; constexpr int nrOptions = NR_ELEMENTS(outputOptionValues); - addFormSelector(F("Attenuation"), F("attn"), nrOptions, outputOptions, outputOptionValues, P002_ATTENUATION); + const FormSelectorOptions selector(nrOptions, outputOptions, outputOptionValues); + selector.addFormSelector(F("Attenuation"), F("attn"), P002_ATTENUATION); } # endif // ifdef ESP32 @@ -175,7 +176,8 @@ void P002_data_struct::webformLoad(struct EventStruct *event) # endif // ifndef LIMIT_BUILD_SIZE }; constexpr int nrOptions = NR_ELEMENTS(outputOptionValues); - addFormSelector(F("Oversampling"), F("oversampling"), nrOptions, outputOptions, outputOptionValues, P002_OVERSAMPLING); + const FormSelectorOptions selector(nrOptions, outputOptions, outputOptionValues); + selector.addFormSelector(F("Oversampling"), F("oversampling"), P002_OVERSAMPLING); } # ifdef ESP32 @@ -322,9 +324,6 @@ void P002_data_struct::webformLoad(struct EventStruct *event) _nrDecimals, true) : EMPTY_STRING, 0, - false, - false, - EMPTY_STRING, F("query-input widenumber")); ++line_nr; diff --git a/src/src/PluginStructs/P025_data_struct.cpp b/src/src/PluginStructs/P025_data_struct.cpp index 709e2b09d2..d5e33ddf54 100644 --- a/src/src/PluginStructs/P025_data_struct.cpp +++ b/src/src/PluginStructs/P025_data_struct.cpp @@ -9,15 +9,8 @@ # define P025_CONFIG_REGISTER 0x01 -P025_VARIOUS_BITS_t::P025_VARIOUS_BITS_t(int16_t value) { - memcpy(this, &value, sizeof(int16_t)); -} +P025_VARIOUS_BITS_t::P025_VARIOUS_BITS_t(int16_t value) : _regValue(value) {} -int16_t P025_VARIOUS_BITS_t::pconfigvalue() const { - int16_t value{}; - memcpy(&value, this, sizeof(int16_t)); - return value; -} const __FlashStringHelper* Plugin_025_valuename(uint8_t value_nr, bool displayString) { const __FlashStringHelper *strings[] { @@ -47,30 +40,29 @@ const __FlashStringHelper* toString(P025_sensorType sensorType) } struct P025_config_register { - struct { - uint16_t comp_que : 2; - uint16_t comp_lat : 1; - uint16_t comp_pol : 1; - uint16_t compMode : 1; - uint16_t datarate : 3; - uint16_t mode : 1; - uint16_t PGA : 3; - uint16_t MUX : 3; - uint16_t operatingStatus : 1; + union { + struct { + uint16_t comp_que : 2; + uint16_t comp_lat : 1; + uint16_t comp_pol : 1; + uint16_t compMode : 1; + uint16_t datarate : 3; + uint16_t mode : 1; + uint16_t PGA : 3; + uint16_t MUX : 3; + uint16_t operatingStatus : 1; + }; + uint16_t _regValue{}; }; - P025_config_register(uint16_t regval) { - memcpy(this, ®val, sizeof(uint16_t)); - } + P025_config_register(uint16_t regval) : _regValue(regval) {} void setRegval(uint16_t regval) { - memcpy(this, ®val, sizeof(uint16_t)); + _regValue = regval; } uint16_t getRegval() const { - uint16_t regval{}; - memcpy(®val, this, sizeof(uint16_t)); - return regval; + return _regValue; } String toString() const { @@ -326,7 +318,8 @@ bool P025_data_struct::webformLoad(struct EventStruct *event) }; constexpr size_t ADS1115_PGA_OPTIONS = NR_ELEMENTS(pgaOptions); - addFormSelector(F("Gain"), F("gain"), ADS1115_PGA_OPTIONS, pgaOptions, nullptr, P025_GAIN); + const FormSelectorOptions selector(ADS1115_PGA_OPTIONS, pgaOptions); + selector.addFormSelector(F("Gain"), F("gain"), P025_GAIN); addFormNote(F("Do not apply more than VDD + 0.3 V to the analog inputs of the device.")); } { @@ -341,8 +334,8 @@ bool P025_data_struct::webformLoad(struct EventStruct *event) F("860 / 3300"), }; constexpr size_t NR_OPTIONS = NR_ELEMENTS(P025_SPSOptions); - - addFormSelector(F("Sample Rate"), F("sps"), NR_OPTIONS, P025_SPSOptions, nullptr, p025_variousBits.getSampleRate()); + const FormSelectorOptions selector(NR_OPTIONS, P025_SPSOptions); + selector.addFormSelector(F("Sample Rate"), F("sps"), p025_variousBits.getSampleRate()); addUnit(F("SPS")); addFormNote(F("Lower values for ADS1115, higher values for ADS1015")); diff --git a/src/src/PluginStructs/P025_data_struct.h b/src/src/PluginStructs/P025_data_struct.h index 6730a0ff59..be3a1cbc41 100644 --- a/src/src/PluginStructs/P025_data_struct.h +++ b/src/src/PluginStructs/P025_data_struct.h @@ -6,17 +6,20 @@ struct P025_VARIOUS_BITS_t { - struct { - uint16_t cal : 1; - uint16_t outputVolt : 1; - uint16_t sampleRateSet : 1; - uint16_t sampleRate : 3; - uint16_t unused : 10; + union { + struct { + uint16_t cal : 1; + uint16_t outputVolt : 1; + uint16_t sampleRateSet : 1; + uint16_t sampleRate : 3; + uint16_t unused : 10; + }; + uint16_t _regValue{}; }; P025_VARIOUS_BITS_t(int16_t value); - int16_t pconfigvalue() const; + int16_t pconfigvalue() const { return _regValue; } uint16_t getSampleRate() const { if (sampleRateSet) { return sampleRate; } diff --git a/src/src/PluginStructs/P037_data_struct.cpp b/src/src/PluginStructs/P037_data_struct.cpp index 7b818b4b2d..cbc56046b8 100644 --- a/src/src/PluginStructs/P037_data_struct.cpp +++ b/src/src/PluginStructs/P037_data_struct.cpp @@ -214,12 +214,12 @@ bool P037_data_struct::webform_load( addTextBox(concat(F("template"), varNr + 1), mqttTopics[varNr], 40, - false, false, EMPTY_STRING, F("xwide")); + F("xwide")); html_TD(F("padding-right: 8px")); addTextBox(concat(F("attribute"), varNr + 1), jsonAttributes[varNr], 20, - false, false, EMPTY_STRING, F("xwide")); + F("xwide")); html_TD(); } else # endif // ifdef P037_JSON_SUPPORT @@ -267,6 +267,9 @@ bool P037_data_struct::webform_load( # endif // if P037_FILTER_COUNT >= 3 }; + const FormSelectorOptions selector(P037_FILTER_COUNT, filterOptions, filterIndices); + + String filters = P037_FILTER_LIST; // Anticipate more filters int8_t filterIndex; @@ -285,16 +288,18 @@ bool P037_data_struct::webform_load( html_TD(); addTextBox(getPluginCustomArgName(idx + 100 + 0), parseStringKeepCase(valueArray[filterOffset], 1, P037_VALUE_SEPARATOR), - 32, false, false, EMPTY_STRING, F("xwide")); + 32, + F("xwide")); } { html_TD(); filterIndex = filters.indexOf(parseString(valueArray[filterOffset], 2, P037_VALUE_SEPARATOR)); - addSelector(getPluginCustomArgName(idx + 100 + 1), P037_FILTER_COUNT, filterOptions, filterIndices, NULL, filterIndex); + selector.addSelector(getPluginCustomArgName(idx + 100 + 1), filterIndex); html_TD(); addTextBox(getPluginCustomArgName(idx + 100 + 2), parseStringKeepCase(valueArray[filterOffset], 3, P037_VALUE_SEPARATOR), - 32, false, false, EMPTY_STRING, F("")); + 32, + F("")); addUnit(F("Range/List: separate values with ; ")); html_TD(); } @@ -315,7 +320,7 @@ bool P037_data_struct::webform_load( # ifndef P037_FILTER_PER_TOPIC filterIndex = 0; uint8_t extraFilters = 0; - + while (extraFilters < P037_EXTRA_VALUES && idx < P037_MAX_FILTERS * 3) { { html_TR_TD(); @@ -323,14 +328,16 @@ bool P037_data_struct::webform_load( addHtmlInt(filterNr); html_TD(); addTextBox(getPluginCustomArgName(idx + 100 + 0), EMPTY_STRING, - 32, false, false, EMPTY_STRING, F("xwide")); + 32, + F("xwide")); } { html_TD(); - addSelector(getPluginCustomArgName(idx + 100 + 1), P037_FILTER_COUNT, filterOptions, filterIndices, NULL, filterIndex); + selector.addSelector(getPluginCustomArgName(idx + 100 + 1), filterIndex); html_TD(); addTextBox(getPluginCustomArgName(idx + 100 + 2), EMPTY_STRING, - 32, false, false, EMPTY_STRING, EMPTY_STRING); + 32, + F("")); addUnit(F("Range/List: separate values with ; ")); html_TD(); } @@ -380,6 +387,8 @@ bool P037_data_struct::webform_load( F("map"), // map name to int F("percentage") }; // map attribute value to percentage of provided value const int operandIndices[] = { 0, 1 }; + const FormSelectorOptions selector(P037_OPERAND_COUNT, operandOptions, operandIndices); + String operands = P037_OPERAND_LIST; // Anticipate more operations int8_t operandIndex; @@ -395,16 +404,19 @@ bool P037_data_struct::webform_load( html_TD(); addTextBox(getPluginCustomArgName(idx + 0), parseStringKeepCase(valueArray[mappingOffset], 1, P037_VALUE_SEPARATOR), - 32, false, false, EMPTY_STRING, F("")); + 32, + F("")); } { html_TD(); operandIndex = operands.indexOf(parseString(valueArray[mappingOffset], 2, P037_VALUE_SEPARATOR)); - addSelector(getPluginCustomArgName(idx + 1), P037_OPERAND_COUNT, operandOptions, operandIndices, NULL, operandIndex); + + selector.addSelector(getPluginCustomArgName(idx + 1), operandIndex); html_TD(); addTextBox(getPluginCustomArgName(idx + 2), parseStringKeepCase(valueArray[mappingOffset], 3, P037_VALUE_SEPARATOR), - 32, false, false, EMPTY_STRING, F("")); + 32, + F("")); html_TD(); } mapNr++; @@ -429,15 +441,19 @@ bool P037_data_struct::webform_load( addHtml(F(" ")); addHtmlInt(mapNr); html_TD(); - addTextBox(getPluginCustomArgName(idx + 0), EMPTY_STRING, - 32, false, false, EMPTY_STRING, F("")); + addTextBox(getPluginCustomArgName(idx + 0), + EMPTY_STRING, + 32, + F("")); } { html_TD(); - addSelector(getPluginCustomArgName(idx + 1), P037_OPERAND_COUNT, operandOptions, operandIndices, NULL, operandIndex); + selector.addSelector(getPluginCustomArgName(idx + 1), operandIndex); html_TD(); - addTextBox(getPluginCustomArgName(idx + 2), EMPTY_STRING, - 32, false, false, EMPTY_STRING, F("")); + addTextBox(getPluginCustomArgName(idx + 2), + EMPTY_STRING, + 32, + F("")); html_TD(); } idx += 3; @@ -458,10 +474,9 @@ bool P037_data_struct::webform_load( addFormNote(F("Both Name and Value must be filled for a valid mapping. Mappings are case-sensitive.")); if (extraMappings == P037_EXTRA_VALUES) { - String moreMessage = concat(F("After filling all mappings, submitting this page will make extra mappings available (up to "), - P037_MAX_MAPPINGS); - moreMessage += F(")."); - addFormNote(moreMessage); + addFormNote(strformat( + F("After filling all mappings, submitting this page will make extra mappings available (up to %d)."), + P037_MAX_MAPPINGS)); } } # endif // if P037_MAPPING_SUPPORT diff --git a/src/src/PluginStructs/P047_data_struct.cpp b/src/src/PluginStructs/P047_data_struct.cpp index 57db31757f..6ffe0d16dc 100644 --- a/src/src/PluginStructs/P047_data_struct.cpp +++ b/src/src/PluginStructs/P047_data_struct.cpp @@ -17,7 +17,7 @@ P047_data_struct::P047_data_struct(uint8_t address, const __FlashStringHelper* toString(P047_SensorModels sensor) { switch (sensor) { - case P047_SensorModels::CatnipMiceuz: return F("Catnip electronics/miceuz (default)"); + case P047_SensorModels::CatnipMiceuz: return F("Catnip electronics/miceuz"); case P047_SensorModels::BeFlE: return F("BeFlE v2.2"); # if P047_FEATURE_ADAFRUIT case P047_SensorModels::Adafruit: return F("Adafruit (4026)"); diff --git a/src/src/PluginStructs/P073_data_struct.cpp b/src/src/PluginStructs/P073_data_struct.cpp index 80ecaa19c8..52daaa878c 100644 --- a/src/src/PluginStructs/P073_data_struct.cpp +++ b/src/src/PluginStructs/P073_data_struct.cpp @@ -115,8 +115,8 @@ void P073_display_output_selector(const __FlashStringHelper *id, int16_t value) P073_DISP_CLOCK12, P073_DISP_DATE, }; - - addFormSelector(F("Display Output"), id, NR_ELEMENTS(disploutOptions), displout, disploutOptions, value); + const FormSelectorOptions selector(NR_ELEMENTS(disploutOptions), displout, disploutOptions); + selector.addFormSelector(F("Display Output"), id, value); } # ifdef P073_EXTRA_FONTS @@ -127,8 +127,8 @@ void P073_font_selector(const __FlashStringHelper *id, int16_t value) { F("Siekoo with uppercase 'CHNORUX'"), F("dSEG7"), }; - - addFormSelector(F("Font set"), id, NR_ELEMENTS(fontset), fontset, nullptr, value); + const FormSelectorOptions selector(NR_ELEMENTS(fontset), fontset); + selector.addFormSelector(F("Font set"), id, value); addFormNote(F("Check documentation for examples of the font sets.")); } diff --git a/src/src/PluginStructs/P094_Filter.cpp b/src/src/PluginStructs/P094_Filter.cpp index 5de2ec70c0..f922ce81cf 100644 --- a/src/src/PluginStructs/P094_Filter.cpp +++ b/src/src/PluginStructs/P094_Filter.cpp @@ -368,19 +368,17 @@ void P094_filter::WebformLoad(uint8_t filterIndex) const const P094_Filter_Window filterWindow = static_cast(optionValues[i]); options[i] = Filter_WindowToString(filterWindow); } - addSelector(P094_FILTER_WEBARG_FILTER_WINDOW(filterIndex), - nrOptions, - options, - optionValues, - nullptr, - _filter._filterWindow, - false, - true, - F("widenumber") -# if FEATURE_TOOLTIPS - , F("Filter Window") -# endif // if FEATURE_TOOLTIPS - ); + FormSelectorOptions selector( + nrOptions, + options, + optionValues); + selector.classname = F("widenumber"); + # if FEATURE_TOOLTIPS + selector.tooltip = F("Filter Window"); + # endif + selector.addSelector( + P094_FILTER_WEBARG_FILTER_WINDOW(filterIndex), + _filter._filterWindow); } } diff --git a/src/src/PluginStructs/P104_data_struct.cpp b/src/src/PluginStructs/P104_data_struct.cpp index db6c497493..1b7e34e338 100644 --- a/src/src/PluginStructs/P104_data_struct.cpp +++ b/src/src/PluginStructs/P104_data_struct.cpp @@ -1890,12 +1890,11 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { static_cast(MD_MAX72XX::moduleType_t::DR0CR1RR1_HW), static_cast(MD_MAX72XX::moduleType_t::DR1CR0RR1_HW) }; - addFormSelector(F("Hardware type"), - F("hardware"), - P104_hardwareTypeCount, - hardwareTypes, - hardwareOptions, - P104_CONFIG_HARDWARETYPE); + const FormSelectorOptions selector( + P104_hardwareTypeCount, + hardwareTypes, + hardwareOptions); + selector.addFormSelector(F("Hardware type"), F("hardware"), P104_CONFIG_HARDWARETYPE); # ifdef P104_ADD_SETTINGS_NOTES addFormNote(F("DR = Digits as Rows, CR = Column Reversed, RR = Row Reversed; 0 = no, 1 = yes.")); # endif // ifdef P104_ADD_SETTINGS_NOTES @@ -1929,10 +1928,9 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { P104_DATE_FORMAT_US, P104_DATE_FORMAT_JP }; - addFormSelector(F("Date format"), F("datefmt"), - 3, - dateFormats, dateFormatOptions, - get4BitFromUL(P104_CONFIG_DATETIME, P104_CONFIG_DATETIME_FORMAT)); + const FormSelectorOptions selector(3, dateFormats, dateFormatOptions); + selector.addFormSelector(F("Date format"), F("datefmt"), + get4BitFromUL(P104_CONFIG_DATETIME, P104_CONFIG_DATETIME_FORMAT)); } { // Date separator const __FlashStringHelper *dateSeparators[] = { @@ -1947,10 +1945,9 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { P104_DATE_SEPARATOR_DASH, P104_DATE_SEPARATOR_DOT }; - addFormSelector(F("Date separator"), F("datesep"), - 4, - dateSeparators, dateSeparatorOptions, - get4BitFromUL(P104_CONFIG_DATETIME, P104_CONFIG_DATETIME_SEP_CHAR)); + const FormSelectorOptions selector(4, dateSeparators, dateSeparatorOptions); + selector.addFormSelector(F("Date separator"), F("datesep"), + get4BitFromUL(P104_CONFIG_DATETIME, P104_CONFIG_DATETIME_SEP_CHAR)); addFormCheckBox(F("Year uses 4 digits"), F("year4dgt"), bitRead(P104_CONFIG_DATETIME, P104_CONFIG_DATETIME_YEAR4DGT)); } @@ -1974,11 +1971,13 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { # endif // ifdef P104_USE_ZONE_ORDERING " will save and reload the page."); # endif // if defined(P104_USE_TOOLTIPS) || defined(P104_ADD_SETTINGS_NOTES) - addFormSelector(F("Zones"), F("zonecnt"), P104_MAX_ZONES, zonesList, zonesOptions, nullptr, P104_CONFIG_ZONE_COUNT, true - # ifdef P104_USE_TOOLTIPS - , zonetip - # endif // ifdef P104_USE_TOOLTIPS - ); + + FormSelectorOptions selector(P104_MAX_ZONES, zonesList, zonesOptions); + selector.reloadonchange = true; + # ifdef P104_USE_TOOLTIPS + selector.tooltip = zonetip; + # endif // ifdef P104_USE_TOOLTIPS + selector.addFormSelector(F("Zones"), F("zonecnt"), P104_CONFIG_ZONE_COUNT); # ifdef P104_USE_ZONE_ORDERING const String orderTypes[] = { @@ -1986,12 +1985,13 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { F("Display order (n..1)") }; const int orderOptions[] = { 0, 1 }; - addFormSelector(F("Zone order"), F("zoneorder"), 2, orderTypes, orderOptions, nullptr, - bitRead(P104_CONFIG_FLAGS, P104_CONFIG_FLAG_ZONE_ORDER) ? 1 : 0, true - # ifdef P104_USE_TOOLTIPS - , zonetip - # endif // ifdef P104_USE_TOOLTIPS - ); + FormSelectorOptions selector_zoneordering(2, orderTypes, orderOptions); + selector.reloadonchange = true; + # ifdef P104_USE_TOOLTIPS + selector.tooltip = zonetip; + # endif // ifdef P104_USE_TOOLTIPS + selector_zoneordering.addFormSelector(F("Zone order"), F("zoneorder"), + bitRead(P104_CONFIG_FLAGS, P104_CONFIG_FLAG_ZONE_ORDER) ? 1 : 0); # endif // ifdef P104_USE_ZONE_ORDERING # ifdef P104_ADD_SETTINGS_NOTES addFormNote(zonetip); @@ -2319,48 +2319,37 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { addTextBox(getPluginCustomArgName(index + P104_OFFSET_TEXT), zones[zone].text, P104_MAX_TEXT_LENGTH_PER_ZONE, - false, - false, - EMPTY_STRING, F("")); - - html_TD(); // Content - addSelector(getPluginCustomArgName(index + P104_OFFSET_CONTENT), - P104_CONTENT_count, - contentTypes, - contentOptions, - nullptr, - zones[zone].content, - false, - true, - F("")); - - html_TD(); // Alignment - addSelector(getPluginCustomArgName(index + P104_OFFSET_ALIGNMENT), - 3, - alignmentTypes, - alignmentOptions, - nullptr, - zones[zone].alignment, - false, - true, - F("")); - + { + html_TD(); // Content + FormSelectorOptions selector( + P104_CONTENT_count, contentTypes, contentOptions); + selector.clearClassName(); + selector.addSelector( + getPluginCustomArgName(index + P104_OFFSET_CONTENT), + zones[zone].content); + } + { + html_TD(); // Alignment + FormSelectorOptions selector(3, alignmentTypes, alignmentOptions); + selector.clearClassName(); + selector.addSelector( + getPluginCustomArgName(index + P104_OFFSET_ALIGNMENT), + zones[zone].alignment); + } { html_TD(); // Animation In (without None by passing the second element index) - addSelector(getPluginCustomArgName(index + P104_OFFSET_ANIM_IN), - animationCount - 1, - &animationTypes[1], - &animationOptions[1], - nullptr, - zones[zone].animationIn, - false, - true, - F("") - # ifdef P104_USE_TOOLTIPS - , F("Animation In") - # endif // ifdef P104_USE_TOOLTIPS - ); + FormSelectorOptions selector( + animationCount - 1, + &animationTypes[1], + &animationOptions[1]); + selector.clearClassName(); + # ifdef P104_USE_TOOLTIPS + selector.tooltip = F("Animation In"); + # endif // ifdef P104_USE_TOOLTIPS + selector.addSelector( + getPluginCustomArgName(index + P104_OFFSET_ANIM_IN), + zones[zone].animationIn); } html_TD(); // Speed In @@ -2370,37 +2359,36 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { , F("Speed") // title # endif // ifdef P104_USE_TOOLTIPS ); - - html_TD(); // Font - addSelector(getPluginCustomArgName(index + P104_OFFSET_FONT), - fontCount, - fontTypes, - fontOptions, - nullptr, - zones[zone].font, - false, - true, - F("") - # ifdef P104_USE_TOOLTIPS - , F("Font") // title - # endif // ifdef P104_USE_TOOLTIPS - ); - - html_TD(); // Inverted - addSelector(getPluginCustomArgName(index + P104_OFFSET_INVERTED), - invertedCount, - invertedTypes, - invertedOptions, - nullptr, - zones[zone].inverted, - false, - true, - F("") - # ifdef P104_USE_TOOLTIPS - , F("Inverted") // title - # endif // ifdef P104_USE_TOOLTIPS - ); - + { + html_TD(); // Font + FormSelectorOptions selector( + fontCount, + fontTypes, + fontOptions); + selector.clearClassName(); + # ifdef P104_USE_TOOLTIPS + selector.tooltip = F("Font"); + # endif // ifdef P104_USE_TOOLTIPS + + selector.addSelector( + getPluginCustomArgName(index + P104_OFFSET_FONT), + zones[zone].font); + } + { + html_TD(); // Inverted + FormSelectorOptions selector( + invertedCount, + invertedTypes, + invertedOptions); + selector.clearClassName(); + # ifdef P104_USE_TOOLTIPS + selector.tooltip = F("Inverted"); + # endif // ifdef P104_USE_TOOLTIPS + + selector.addSelector( + getPluginCustomArgName(index + P104_OFFSET_INVERTED), + zones[zone].inverted); + } html_TD(3); // Fill columns # ifdef P104_USE_ZONE_ACTIONS @@ -2427,19 +2415,18 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { { html_TD(); // Animation Out - addSelector(getPluginCustomArgName(index + P104_OFFSET_ANIM_OUT), - animationCount, - animationTypes, - animationOptions, - nullptr, - zones[zone].animationOut, - false, - true, - F("") - # ifdef P104_USE_TOOLTIPS - , F("Animation Out") - # endif // ifdef P104_USE_TOOLTIPS - ); + FormSelectorOptions selector( + animationCount, + animationTypes, + animationOptions); + selector.clearClassName(); + # ifdef P104_USE_TOOLTIPS + selector.tooltip = F("Animation Out"); + # endif // ifdef P104_USE_TOOLTIPS + + selector.addSelector( + getPluginCustomArgName(index + P104_OFFSET_ANIM_OUT), + zones[zone].animationOut); } html_TD(); // Pause after Animation In @@ -2449,37 +2436,36 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { , F("Pause") // title # endif // ifdef P104_USE_TOOLTIPS ); - - html_TD(); // Layout - addSelector(getPluginCustomArgName(index + P104_OFFSET_LAYOUT), - layoutCount, - layoutTypes, - layoutOptions, - nullptr, - zones[zone].layout, - false, - true, - F("") - # ifdef P104_USE_TOOLTIPS - , F("Layout") // title - # endif // ifdef P104_USE_TOOLTIPS - ); - - html_TD(); // Special effects - addSelector(getPluginCustomArgName(index + P104_OFFSET_SPEC_EFFECT), - specialEffectCount, - specialEffectTypes, - specialEffectOptions, - nullptr, - zones[zone].specialEffect, - false, - true, - F("") - # ifdef P104_USE_TOOLTIPS - , F("Special Effects") // title - # endif // ifdef P104_USE_TOOLTIPS - ); - + { + html_TD(); // Layout + FormSelectorOptions selector( + layoutCount, + layoutTypes, + layoutOptions); + selector.clearClassName(); + # ifdef P104_USE_TOOLTIPS + selector.tooltip = F("Layout"); + # endif // ifdef P104_USE_TOOLTIPS + + selector.addSelector( + getPluginCustomArgName(index + P104_OFFSET_LAYOUT), + zones[zone].layout); + } + { + html_TD(); // Special effects + FormSelectorOptions selector( + specialEffectCount, + specialEffectTypes, + specialEffectOptions); + selector.clearClassName(); + # ifdef P104_USE_TOOLTIPS + selector.tooltip = F("Special Effects"); + # endif // ifdef P104_USE_TOOLTIPS + + selector.addSelector( + getPluginCustomArgName(index + P104_OFFSET_SPEC_EFFECT), + zones[zone].specialEffect); + } html_TD(); // Offset addNumericBox(getPluginCustomArgName(index + P104_OFFSET_OFFSET), zones[zone].offset, 0, 254); @@ -2500,19 +2486,20 @@ bool P104_data_struct::webform_load(struct EventStruct *event) { ); # ifdef P104_USE_ZONE_ACTIONS - html_TD(); // Spacer + html_TD(); // Spacer addHtml('|'); - - html_TD(); // Action - addSelector(getPluginCustomArgName(index + P104_OFFSET_ACTION), - actionCount, - actionTypes, - actionOptions, - nullptr, - P104_ACTION_NONE, // Always start with None - true, - true, - F("")); + { + html_TD(); // Action + FormSelectorOptions selector( + actionCount, + actionTypes, + actionOptions); + selector.classname = F(""); + selector.reloadonchange = true; + selector.addSelector( + getPluginCustomArgName(index + P104_OFFSET_ACTION), + P104_ACTION_NONE); // Always start with None + } # endif // ifdef P104_USE_ZONE_ACTIONS delay(0); diff --git a/src/src/PluginStructs/P120_data_struct.cpp b/src/src/PluginStructs/P120_data_struct.cpp index b1ae66dead..ae63cc6848 100644 --- a/src/src/PluginStructs/P120_data_struct.cpp +++ b/src/src/PluginStructs/P120_data_struct.cpp @@ -519,7 +519,8 @@ bool P120_data_struct::plugin_webform_loadOutputSelector(struct EventStruct *eve const int values[] = { 0, 1 }; const int choice = bitRead(P120_CONFIG_FLAGS1, P120_FLAGS1_ANGLE_IN_RAD); - addFormSelector(F("Angle Units"), F("angle_rad"), 2, options, values, choice); + const FormSelectorOptions selector(2, options, values); + selector.addFormSelector(F("Angle Units"), F("angle_rad"), choice); } return true; } @@ -528,13 +529,16 @@ bool P120_data_struct::plugin_webform_load(struct EventStruct *event) { // Range { const __FlashStringHelper *rangeOptions[] = { - F("2g"), - F("4g"), - F("8g"), - F("16g (default)") }; + F("2"), + F("4"), + F("8"), + F("16") }; int rangeValues[] = { P120_RANGE_2G, P120_RANGE_4G, P120_RANGE_8G, P120_RANGE_16G }; - addFormSelector(F("Range"), F("range"), 4, rangeOptions, rangeValues, - get2BitFromUL(P120_CONFIG_FLAGS1, P120_FLAGS1_RANGE)); + FormSelectorOptions selector(4, rangeOptions, rangeValues); + selector.default_index = P120_RANGE_16G; + selector.addFormSelector(F("Range"), F("range"), + get2BitFromUL(P120_CONFIG_FLAGS1, P120_FLAGS1_RANGE)); + addUnit('g'); } // Axis selection @@ -627,7 +631,8 @@ bool P120_data_struct::plugin_webform_load(struct EventStruct *event) { F("10"), F("50") }; int frequencyValues[] = { P120_FREQUENCY_10, P120_FREQUENCY_50 }; - addFormSelector(F("Measuring frequency"), F("frequency"), 2, frequencyOptions, frequencyValues, P120_FREQUENCY); + const FormSelectorOptions selector( 2, frequencyOptions, frequencyValues); + selector.addFormSelector(F("Measuring frequency"), F("frequency"), P120_FREQUENCY); addUnit(F("Hz")); addFormNote(F("Values X/Y/Z are updated 1x per second, Controller updates & Value-events are based on 'Interval' setting.")); } diff --git a/src/src/PluginStructs/P137_data_struct.cpp b/src/src/PluginStructs/P137_data_struct.cpp index 5350174fad..94caff89cd 100644 --- a/src/src/PluginStructs/P137_data_struct.cpp +++ b/src/src/PluginStructs/P137_data_struct.cpp @@ -135,8 +135,8 @@ const __FlashStringHelper* toString(const P137_PredefinedDevices_e device) { switch (device) { case P137_PredefinedDevices_e::Unselected: return F("Select an option to set default values"); case P137_PredefinedDevices_e::M5Stack_StickC: return F("M5Stack StickC"); - case P137_PredefinedDevices_e::M5Stack_Core2: return F("M5Stack Core2 (Default)"); - case P137_PredefinedDevices_e::LilyGO_TBeam: return F("LilyGO T-Beam"); + case P137_PredefinedDevices_e::M5Stack_Core2: return F("M5Stack Core2 v1.0 (Default)"); + case P137_PredefinedDevices_e::LilyGO_TBeam: return F("LilyGO T-Beam v1.1"); case P137_PredefinedDevices_e::UserDefined: return F("User defined"); } return F("*Undefined*"); diff --git a/src/src/PluginStructs/P139_data_struct.cpp b/src/src/PluginStructs/P139_data_struct.cpp new file mode 100644 index 0000000000..88ec7b90fe --- /dev/null +++ b/src/src/PluginStructs/P139_data_struct.cpp @@ -0,0 +1,729 @@ +#include "../PluginStructs/P139_data_struct.h" + +#ifdef USES_P139 + +# ifdef ESP32 + +# include "../PluginStructs/P139_data_struct_formselectors.h" + +// **************************************************************************/ +// Constructors +// **************************************************************************/ +P139_data_struct::P139_data_struct(struct EventStruct *event) { + axp2101 = new (std::nothrow) AXP2101(); // Default address and I2C Wire object + + if (isInitialized()) { // Functions based on: + axp2101->begin(&Wire, AXP2101_ADDR, static_cast(P139_CURRENT_PREDEFINED)); + loadSettings(event); + applySettings(event); + } else { + addLog(LOG_LEVEL_ERROR, F("AXP2101: Initialization failed")); + } +} + +// **************************************************************************/ +// Destructor +// **************************************************************************/ +P139_data_struct::~P139_data_struct() { + delete axp2101; +} + +// **************************************************************************/ +// loadSettings: Load the (custom)settings from flash +// **************************************************************************/ +String P139_data_struct::loadSettings(struct EventStruct *event) { + String result; + + if (!_settingsLoaded) { + result = LoadCustomTaskSettings(event->TaskIndex, + reinterpret_cast(&_settings), + sizeof(_settings)); + _settingsLoaded = true; + } + return result; +} + +// **************************************************************************/ +// applySettings: Write the current settings to AXP2101 +// **************************************************************************/ +void P139_data_struct::applySettings(struct EventStruct *event) { + if (!isInitialized()) { + return; + } + uint8_t count = 0; + + for (int s = 0; s < AXP2101_settings_count; ++s) { + const AXP2101_registers_e reg = AXP2101_intToRegister(s); + const AXP_pin_s pinState = _settings.getState(reg); + + if (!AXP2101_isPinDefault(pinState)) { + if (AXP_pin_s::On == pinState) { + axp2101->setPortVoltage(_settings.getVoltage(reg), reg); + axp2101->setPortState(true, reg); // Turn on after setting the voltage + } else { + axp2101->setPortState(false, reg); // Turn off + } + ++count; + + # ifndef BUILD_NO_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + addLog(LOG_LEVEL_DEBUG, + strformat(F("AXP2101: Port: %s, output: %dmV, pin state: %s"), + FsP(toString(reg)), _settings.getVoltage(reg), FsP(toString(pinState)))); + } + # endif // ifndef BUILD_NO_DEBUG + } + } + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, strformat(F("AXP2101: Set %d values to port(s)"), count)); + } + axp2101->setChargeLed(_settings.getChargeLed()); + + // Reg 61: Iprechg Charger Settings + axp2101->setPreChargeCurrentLimit(_settings.getPreChargeCurrentLimit()); + + // Reg 62: ICC Charger Settings + axp2101->setConstChargeCurrentLimit(_settings.getConstChargeCurrentLimit()); + + // Reg 63: Iterm Charger Settings and Control + axp2101->setTerminationChargeCurrentLimit(_settings.getTerminationChargeCurrentLimit(), _settings.getTerminationChargeCurrentLimitEnable()); + + // Reg 64: CV Charger Voltage Settings + axp2101->setCV_chargeVoltage(_settings.getCV_chargeVoltage()); + + // Reg 14: Minimum System Voltage Control + axp2101->setLinear_Charger_Vsys_dpm(_settings.getLinear_Charger_Vsys_dpm()); + + // Reg 15: Input Voltage Limit + axp2101->setVin_DPM(_settings.getVin_DPM()); + + // Reg 16: Input Current Limit + axp2101->setInputCurrentLimit(_settings.getInputCurrentLimit()); + axp2101->setTS_disabled(_settings.getTS_disabled()); + + + // axp2101->set_IRQ_enable_0(0b11110000); // Disable temperature checks + axp2101->setConstChargeCurrentLimit(_settings.getConstChargeCurrentLimit()); +} + +// **************************************************************************/ +// saveSettings: Save the settings to the custom settings area +// **************************************************************************/ +String P139_data_struct::saveSettings(struct EventStruct *event) { + const String result = SaveCustomTaskSettings(event->TaskIndex, + reinterpret_cast(&_settings), + sizeof(_settings)); + + _settingsLoaded = true; // When freshly saved == loaded :-) + return result; +} + +// **************************************************************************/ +// applySettings: Update settings to defaults for selected device +// **************************************************************************/ +bool P139_data_struct::applyDeviceModelTemplate(AXP2101_device_model_e device) { + const int idx = static_cast(AXP2101_device_model_e::UserDefined == device ? + AXP2101_device_model_e::MAX : + device); + + if ((idx > static_cast(AXP2101_device_model_e::Unselected)) && + (idx <= static_cast(AXP2101_device_model_e::MAX))) { + _settings = AXP2101_deviceSettingsArray[idx]; + return true; + } + return false; +} + +void P139_data_struct::webform_load(struct EventStruct *event) { + const bool isPowerManagerTask = Settings.isPowerManagerTask(event->TaskIndex); + + { + AXP2101_ChargeLED_FormSelector selector(_settings.getChargeLed()); + } + { + // Reg 61: Iprechg Charger Settings + // 0 .. 200 mA in 25 mA steps + AXP2101_PreChargeCurrentLimit_FormSelector selector(_settings.getPreChargeCurrentLimit()); + } + { + // Reg 62: ICC Charger Settings + AXP2101_ConstChargeCurrentLimit_FormSelector selector(_settings.getConstChargeCurrentLimit()); + } + { + // Reg 63: Iterm Charger Settings and Control + // 0 .. 200 mA in 25 mA steps + enable checkbox + AXP2101_TerminationChargeCurrentLimit_FormSelector selector(_settings.getTerminationChargeCurrentLimit()); + addFormCheckBox(F("Enable CV Charging"), F("iterm_en"), _settings.getTerminationChargeCurrentLimitEnable()); + addFormNote(F("When enabled, the last part of the charge cycle is done using constant voltage (CV)")); + } + + { + // Reg 64: CV Charger Voltage Settings + AXP2101_CV_charger_voltage_FormSelector selector(_settings.getCV_chargeVoltage()); + } + { + // Reg 14: Minimum System Voltage Control + AXP2101_Linear_Charger_Vsys_dpm_FormSelector selector(_settings.getLinear_Charger_Vsys_dpm()); + } + + { + // Reg 15: Input Voltage Limit + AXP2101_Vin_DPM_FormSelector selector(_settings.getVin_DPM()); + } + + { + // Reg 16: Input Current Limit + AXP2101_InputCurrentLimit_FormSelector selector(_settings.getInputCurrentLimit()); + } + + addFormCheckBox(F("Disable TS pin"), F("dis_TS"), _settings.getTS_disabled()); + addFormNote(F("Make sure to disable TS pin when no battery temperature sensor is used, or else the battery will not charge")); + + addFormCheckBox(F("Generate events"), F("events"), P139_GET_GENERATE_EVENTS); + + addFormSubHeader(F("Hardware outputs AXP2101")); + + { + const __FlashStringHelper *predefinedNames[] = { + toString(AXP2101_device_model_e::Unselected), + toString(AXP2101_device_model_e::M5Stack_Core2_v1_1), + toString(AXP2101_device_model_e::M5Stack_CoreS3), + toString(AXP2101_device_model_e::LilyGO_TBeam_v1_2), + toString(AXP2101_device_model_e::LilyGO_TBeamS3_v3), + toString(AXP2101_device_model_e::LilyGO_TPCie_v1_2), + toString(AXP2101_device_model_e::UserDefined) // keep last !! + }; + const int predefinedValues[] = { + static_cast(AXP2101_device_model_e::Unselected), + static_cast(AXP2101_device_model_e::M5Stack_Core2_v1_1), + static_cast(AXP2101_device_model_e::M5Stack_CoreS3), + static_cast(AXP2101_device_model_e::LilyGO_TBeam_v1_2), + static_cast(AXP2101_device_model_e::LilyGO_TBeamS3_v3), + static_cast(AXP2101_device_model_e::LilyGO_TPCie_v1_2), + static_cast(AXP2101_device_model_e::UserDefined) }; // keep last !! + constexpr uint8_t valueCount = NR_ELEMENTS(predefinedValues); + FormSelectorOptions selector( + valueCount, + predefinedNames, predefinedValues); + selector.reloadonchange = !isPowerManagerTask; + selector.addFormSelector( + F("Predefined device configuration"), + F("predef"), + 0); + + const AXP2101_device_model_e device = static_cast(P139_CURRENT_PREDEFINED); + + if (AXP2101_device_model_e::Unselected != device) { + addFormNote(concat(F("Last selected: "), toString(device))); + + if (AXP2101_device_model_e::UserDefined == device) { + addHtml(F("
Warning: " + "Configuring invalid values can damage your device or render it useless!
")); + } + } + } + + { + const __FlashStringHelper *bootStates[] = { + toString(AXP_pin_s::Off), + toString(AXP_pin_s::On), + toString(AXP_pin_s::Default), + }; + const int bootStateValues[] = { + static_cast(AXP_pin_s::Off), + static_cast(AXP_pin_s::On), + static_cast(AXP_pin_s::Default), + }; + + // Don't include Disabled or Protected here, not user-selectable + constexpr int bootStatesCount = NR_ELEMENTS(bootStateValues); + + const FormSelectorOptions selector( + bootStatesCount, + bootStates, + bootStateValues); + + + addRowLabel(F("Output ports")); + + html_table(EMPTY_STRING); + html_table_header(F("Name"), 100); + html_table_header(F("Voltage (mV)"), 270); + html_table_header(F("Pin state"), 150); + + for (int s = 0; s < AXP2101_settings_count; ++s) { + const AXP2101_registers_e reg = AXP2101_intToRegister(s); + const AXP_pin_s pin = _settings.getState(reg); + html_TR_TD(); + addHtml(toString(reg)); + html_TD(); + addNumericBox(toString(reg, false), + _settings.getVoltage(reg, false), + -1, + AXP2101_maxVoltage(reg), + AXP2101_isPinDefault(pin)); + addUnit(strformat(F("range %d - %d"), AXP2101_minVoltage(reg), AXP2101_maxVoltage(reg))); + html_TD(); + + if (AXP2101_isPinProtected(pin)) { + addUnit(toString(pin)); + } else { + selector.addSelector( + concat(F("ps"), toString(reg, false)), + static_cast(pin)); + } + } + + html_end_table(); + + addFormNote(F("Check your device documentation for what is connected to each output.")); + + if (isInitialized()) { + addFormSubHeader(F("Current State")); + + const AXP2101_registers_e registers[] = { + AXP2101_registers_e::vbus, + AXP2101_registers_e::vsys, + AXP2101_registers_e::vbat, + AXP2101_registers_e::batcharge, + AXP2101_registers_e::battemp, + AXP2101_registers_e::chiptemp + }; + + for (size_t i = 0; i < NR_ELEMENTS(registers); ++i) { + addRowLabel(toString(registers[i], true)); + + if ((registers[i] == AXP2101_registers_e::battemp) || + (registers[i] == AXP2101_registers_e::chiptemp)) + { + addHtmlFloat(read_value(registers[i])); + addUnit(F("°C")); + } else { + addHtmlInt(static_cast(read_value(registers[i]))); + addUnit((registers[i] == AXP2101_registers_e::batcharge) + ? F("%") : F("mV")); + } + } + + addRowLabel(F("Charging State")); + + const AXP2101_chargingState_e chargingState = axp2101->getChargingState(); + + if (chargingState != AXP2101_chargingState_e::Charging) { + addHtml(toString(chargingState)); + } + else { + addHtml(toString(axp2101->getChargingDetail())); + } + } + } +} + +void P139_data_struct::webform_save(struct EventStruct *event) { + for (uint8_t i = 0; i < P139_NR_OUTPUT_VALUES; ++i) { + sensorTypeHelper_saveOutputSelector(event, P139_CONFIG_BASE + i, i, + toString(static_cast(PCONFIG(P139_CONFIG_BASE + i)), false)); + } + + const int predefined = getFormItemInt(F("predef")); + P139_SET_GENERATE_EVENTS(isFormItemChecked(F("events"))); + + if (predefined > 0) { // Apply new template to save it, even when task is disabled + P139_CURRENT_PREDEFINED = predefined; + applyDeviceModelTemplate(static_cast(P139_CURRENT_PREDEFINED)); + } else { + for (int s = 0; s < AXP2101_settings_count; ++s) { + const AXP2101_registers_e reg = AXP2101_intToRegister(s); + + if (!AXP2101_isPinProtected(_settings.getState(reg))) { + _settings.setVoltage(reg, getFormItemInt(toString(reg, false))); + _settings.setState(reg, static_cast(getFormItemInt(concat(F("ps"), toString(reg, false))))); + } + } + } + + _settings.setChargeLed(AXP2101_ChargeLED_FormSelector::get()); + + // Reg 61: Iprechg Charger Settings + _settings.setPreChargeCurrentLimit(AXP2101_PreChargeCurrentLimit_FormSelector::get()); + + // Reg 62: ICC Charger Settings + _settings.setConstChargeCurrentLimit(AXP2101_ConstChargeCurrentLimit_FormSelector::get()); + + // Reg 63: Iterm Charger Settings and Control + _settings.setTerminationChargeCurrentLimit( + AXP2101_TerminationChargeCurrentLimit_FormSelector::get(), + isFormItemChecked(F("iterm_en"))); + + // Reg 64: CV Charger Voltage Settings + _settings.setCV_chargeVoltage(AXP2101_CV_charger_voltage_FormSelector::get()); + + // Reg 14: Minimum System Voltage Control + _settings.setLinear_Charger_Vsys_dpm(AXP2101_Linear_Charger_Vsys_dpm_FormSelector::get()); + + // Reg 15: Input Voltage Limit + _settings.setVin_DPM(AXP2101_Vin_DPM_FormSelector::get()); + + // Reg 16: Input Current Limit + _settings.setInputCurrentLimit(AXP2101_InputCurrentLimit_FormSelector::get()); + + _settings.setTS_disabled(isFormItemChecked(F("dis_TS"))); + + saveSettings(event); +} + +// **************************************************************************/ +// plugin_read: Read the values and send to controller(s) +// **************************************************************************/ +bool P139_data_struct::plugin_read(struct EventStruct *event) { + bool success = true; + + const uint8_t valueCount = P139_NR_OUTPUT_VALUES; + + for (uint8_t i = 0; i < valueCount; ++i) { + UserVar.setFloat(event->TaskIndex, i, read_value(static_cast(PCONFIG(P139_CONFIG_BASE + i)))); + } + + return success; +} + +// **************************************************************************/ +// read_value: Read the requested value +// **************************************************************************/ +float P139_data_struct::read_value(AXP2101_registers_e value) { + if (isInitialized()) { + switch (value) + { + case AXP2101_registers_e::chargeled: + return static_cast(axp2101->getChargeLed()); + case AXP2101_registers_e::batcharge: + return static_cast(axp2101->getBatCharge()); + case AXP2101_registers_e::charging: + return static_cast(axp2101->getChargingState()); + case AXP2101_registers_e::batpresent: + return static_cast(axp2101->isBatteryDetected()); + case AXP2101_registers_e::chipid: + return static_cast(axp2101->getChipIDRaw()); + case AXP2101_registers_e::chargedet: + return static_cast(axp2101->getChargingDetail()); + + case AXP2101_registers_e::vbat: + case AXP2101_registers_e::vbus: + case AXP2101_registers_e::vsys: + return static_cast(axp2101->getADCVoltage(value)); + + case AXP2101_registers_e::battemp: + return axp2101->TS_registerToTemp(axp2101->getADCVoltage(value)); + + case AXP2101_registers_e::chiptemp: + return 22.0f + (7274 - axp2101->getADCVoltage(value)) / 20.0f; + + default: + return static_cast(axp2101->getPortVoltage(value)); + } + } + return 0.0f; +} + +// **************************************************************************/ +// plugin_ten_per_second: Check state and generate events +// **************************************************************************/ +// bool P139_data_struct::plugin_ten_per_second(struct EventStruct *event) { +// // TODO ? +// return false; +// } + +// **************************************************************************/ +// plugin_fifty_per_second: Check state and generate events +// **************************************************************************/ +bool P139_data_struct::plugin_fifty_per_second(struct EventStruct *event) { + if (isInitialized() && P139_GET_GENERATE_EVENTS) { + const AXP2101_chargingState_e charging = axp2101->getChargingState(); + + if (_chargingState != charging) { + eventQueue.add(event->TaskIndex, F("ChargingState"), // Event: #ChargingState=, (numeric) + strformat(F("%d,%d"), static_cast(charging), static_cast(_chargingState))); + _chargingState = charging; + } + return true; + } + return false; +} + +// **************************************************************************/ +// plugin_write: Process commands +// **************************************************************************/ +const char P139_subcommands[] PROGMEM = "readchip|voltage|off|on|percentage|range|chargeled"; + +enum class P139_subcommands_e : int8_t { + invalid = -1, + readchip = 0, + voltage, + off, + on, + percentage, + range, + chargeled, +}; + +bool P139_data_struct::plugin_write(struct EventStruct *event, + const String & string) { + bool success = false; + String cmd = parseString(string, 1); + + if (isInitialized() && equals(cmd, F("axp"))) { // Command trigger + cmd = parseString(string, 2); // sub command + const int subcommand_i = GetCommandCode(cmd.c_str(), P139_subcommands); + + if (-1 == subcommand_i) { return success; } // Shortcut + + const P139_subcommands_e subcmd = static_cast(subcommand_i); + + const String var3 = parseString(string, 3); + const bool empty3 = var3.isEmpty(); + const bool empty4 = parseString(string, 4).isEmpty(); + + switch (subcmd) { + case P139_subcommands_e::invalid: break; + case P139_subcommands_e::readchip: + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, F("AXP2101: Port voltages (mV), state and range:")); + + for (int s = 0; s < AXP2101_register_count; ++s) { + const AXP2101_registers_e reg = AXP2101_intToRegister(s); + + int32_t value = -1; + uint8_t state = 0u; + String data; + + if (AXP2101_registers_e::chargeled == reg) { + data = strformat(F(", Led: %s"), FsP(toString(axp2101->getChargeLed()))); + } else + if (AXP2101_registers_e::batcharge == reg) { + data = strformat(F(", Battery: %d%%"), axp2101->getBatCharge()); + } else + if (AXP2101_registers_e::charging == reg) { + data = strformat(F(", Battery: %s"), FsP(toString(axp2101->getChargingState()))); + } else + if (AXP2101_registers_e::batpresent == reg) { + data = strformat(F(", Battery: %s"), FsP(boolToString(axp2101->isBatteryDetected()))); + } else + if (AXP2101_registers_e::chipid == reg) { + data = strformat(F(", ChipID: %s (0x%02x)"), FsP(toString(axp2101->getChipID())), axp2101->getChipIDRaw()); + } else + if (AXP2101_registers_e::chargedet == reg) { + data = strformat(F(", ChargingDetail: %s"), FsP(toString(axp2101->getChargingDetail()))); + } else { + value = axp2101->getPortVoltage(reg); + state = axp2101->getPortState(reg); + } + addLog(LOG_LEVEL_INFO, strformat(F("Port: %7s: %4dmV, state: %d, range: %d - %dmV%s"), + FsP(toString(reg)), + value, + state, + AXP2101_minVoltage(reg), + AXP2101_maxVoltage(reg), + data.c_str())); + } + } else { + addLog(LOG_LEVEL_ERROR, F("AXP2101: 'readchip' needs logging level INFO")); + } + + success = true; + break; + + case P139_subcommands_e::voltage: + + if (!empty3 && !empty4) { + for (int s = 0; s < AXP2101_settings_count; ++s) { + const AXP2101_registers_e reg = AXP2101_intToRegister(s); + + if (equals(var3, toString(reg, false))) { + const int min_ = AXP2101_minVoltage(reg); + + if (0 == event->Par3 /* < min_ */) { + // Q: Turn off when A) 0 or B) below minimum voltage? Selected answer: A) + axp2101->setPortState(false, reg); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, strformat(F("AXP2101: Turn off port %s"), FsP(toString(reg)))); + } + success = true; + } else + if ((event->Par3 >= min_) && (event->Par3 <= AXP2101_maxVoltage(reg))) { + axp2101->setPortVoltage(event->Par3, reg); + axp2101->setPortState(true, reg); // Turn on after setting the voltage + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, strformat(F("AXP2101: Set port %s to %dmV"), FsP(toString(reg)), event->Par3)); + } + success = true; + } + } + } + } + break; + + case P139_subcommands_e::off: + case P139_subcommands_e::on: + + if (!empty3) { + for (int s = 0; s < AXP2101_settings_count; ++s) { + const AXP2101_registers_e reg = AXP2101_intToRegister(s); + + if (equals(var3, toString(reg, false))) { + const bool stateOn = P139_subcommands_e::on == subcmd; + const AXP_pin_s pinState = _settings.getState(reg); + + if (AXP2101_isPinProtected(pinState)) { + if (loglevelActiveFor(LOG_LEVEL_ERROR)) { + addLog(LOG_LEVEL_ERROR, strformat(F("AXP2101: Port %s is %s"), FsP(toString(reg)), FsP(toString(pinState)))); + } + } else { + axp2101->setPortState(stateOn, reg); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, strformat(F("AXP2101: Switch port %s: %s"), FsP(toString(reg)), FsP(stateOn ? F("On") : F("Off")))); + } + success = true; + } + } + } + } + break; + + case P139_subcommands_e::percentage: + + if ((event->Par3 >= 0) && (event->Par3 <= P139_CONST_100_PERCENT) && !empty3 && empty4) { + for (int s = 0; s < AXP2101_settings_count && !success; ++s) { + const AXP2101_registers_e reg = AXP2101_intToRegister(s); + + if (equals(var3, toString(reg, false)) && !AXP2101_isPinProtected(_settings.getState(reg))) { + if (event->Par3 > 0) { + const uint16_t _value = map(event->Par3, + P139_CONST_1_PERCENT, P139_CONST_100_PERCENT, + _ranges[s][0], _ranges[s][1]); + + axp2101->setPortVoltage(_value, reg); + axp2101->setPortState(true, reg); // Turn on after setting the voltage + } else { + axp2101->setPortState(false, reg); // Turn off + } + success = true; + } + } + } + break; + + case P139_subcommands_e::range: + + if ((event->Par4 >= 0) && (event->Par4 <= P139_CONST_MAX_LDO) && + (event->Par3 < event->Par4) && !empty3 && !empty4) { + for (int s = 0; s < AXP2101_settings_count && !success; ++s) { + const AXP2101_registers_e reg = AXP2101_intToRegister(s); + + if (equals(var3, toString(reg, false)) && + (event->Par3 >= AXP2101_minVoltage(reg)) && + (event->Par4 <= AXP2101_maxVoltage(reg))) { + _ranges[s][0] = event->Par3; + _ranges[s][1] = event->Par4; + success = true; + } + } + } else { + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + for (int s = 0; s < AXP2101_settings_count; ++s) { + const AXP2101_registers_e reg = AXP2101_intToRegister(s); + addLog(LOG_LEVEL_INFO, strformat(F("AXP2101: %7s Percentage range: %d - %dmV (State: %s)"), + FsP(toString(reg)), + _ranges[s][0], + _ranges[s][1], + FsP(toString(_settings.getState(reg))))); + } + } + } + success = true; + break; + + case P139_subcommands_e::chargeled: + + if (event->Par2 >= 0 and event->Par2 <= 3) { // Only allowed options + AXP2101_chargeled_d led = static_cast(event->Par2); + + // axp2101->setChargeLed(led); + _settings.setChargeLed(led); // Store in settings, but don't save yet + success = true; + } + break; + } // switch + } + + return success; +} + +/**************************************************************************** + * plugin_get_config_value: Retrieve values like [#] + ***************************************************************************/ +bool P139_data_struct::plugin_get_config_value(struct EventStruct *event, + String & string) { + if (!isInitialized()) { return false; } + bool success = false; + const String command = parseString(string, 1); + + for (int r = 0; r < AXP2101_register_count && !success; ++r) { + const AXP2101_registers_e reg = AXP2101_intToRegister(r); + + if (equals(command, toString(reg, false))) { // Voltage (mV) / numeric state + if ((reg == AXP2101_registers_e::battemp) || + (reg == AXP2101_registers_e::chiptemp)) + { + string = floatToString(read_value(reg), 2); + } else { + string = read_value(reg); + } + success = true; + } else + if (command.equals(concat(toString(reg, false), F(".status")))) { // Status (name) + if (r >= AXP2101_settings_count) { + if (AXP2101_registers_e::chargeled == reg) { + string = toString(axp2101->getChargeLed()); + success = true; + } else + if (AXP2101_registers_e::charging == reg) { + string = toString(axp2101->getChargingState()); + success = true; + } else + if (AXP2101_registers_e::chipid == reg) { + string = toString(axp2101->getChipID()); + success = true; + } else + if (AXP2101_registers_e::chargedet == reg) { + string = toString(axp2101->getChargingDetail()); + success = true; + } + } else { + string = toString(axp2101->getPortState(reg)); + success = true; + } + } else + if (command.equals(concat(toString(reg, false), F(".state")))) { // State (int) + if (r >= AXP2101_settings_count) { + if (AXP2101_registers_e::chargeled == reg) { + string = static_cast(axp2101->getChargeLed()); + success = true; + } + } else { + string = static_cast(axp2101->getPortState(reg)); + success = true; + } + } + } + + return success; +} + +# endif // ifdef ESP32 +#endif // ifdef USES_P139 diff --git a/src/src/PluginStructs/P139_data_struct.h b/src/src/PluginStructs/P139_data_struct.h new file mode 100644 index 0000000000..abd0c9d149 --- /dev/null +++ b/src/src/PluginStructs/P139_data_struct.h @@ -0,0 +1,103 @@ +#ifndef PLUGINSTRUCTS_P139_DATA_STRUCT_H +#define PLUGINSTRUCTS_P139_DATA_STRUCT_H + +#include "../../_Plugin_Helper.h" +#ifdef USES_P139 + +# ifdef ESP32 + +# include + +# define P139_DEBUG_LOG // Enable for some (extra) logging + +# define P139_CONFIG_BASE 0 // Uses PCONFIG(0)..PCONFIG(3) to store the selection for 4 output values +# define P139_SENSOR_TYPE_INDEX (P139_CONFIG_BASE + VARS_PER_TASK) +# define P139_NR_OUTPUT_VALUES getValueCountFromSensorType(static_cast(PCONFIG(P139_SENSOR_TYPE_INDEX))) +# define P139_CONFIG_DECIMALS PCONFIG(P139_SENSOR_TYPE_INDEX + 1) + +// # define P139_CONFIG_PREDEFINED PCONFIG(P139_SENSOR_TYPE_INDEX + 2) // available for re-use +# define P139_CURRENT_PREDEFINED PCONFIG_FLOAT(0) + +# define P139_FLAGS PCONFIG_ULONG(0) + +# define P139_FLAG_GENERATE_EVENTS 0 + +// # define P139_FLAG_RAW_DATA_ONLY 1 + +# define P139_GET_GENERATE_EVENTS bitRead(P139_FLAGS, P139_FLAG_GENERATE_EVENTS) +# define P139_SET_GENERATE_EVENTS(x) bitWrite(P139_FLAGS, P139_FLAG_GENERATE_EVENTS, (x)) + +// # define P139_GET_RAW_DATA_ONLY bitRead(P139_FLAGS, P139_FLAG_RAW_DATA_ONLY) +// # define P139_SET_RAW_DATA_ONLY(x) bitWrite(P139_FLAGS, P139_FLAG_RAW_DATA_ONLY, (x)) + +# define P139_CONST_1_PERCENT 1 // Lowest used percentage, 0 = off +# define P139_CONST_100_PERCENT 100 // Max percentage +# define P139_CONST_MIN_LDO 500 // Min. output voltage +# define P139_CONST_MAX_LDO 3700 // Max. output voltage + + +struct P139_data_struct : public PluginTaskData_base { +public: + + P139_data_struct(struct EventStruct *event); + P139_data_struct() {} + + ~P139_data_struct(); + + bool plugin_read(struct EventStruct *event); + bool plugin_write(struct EventStruct *event, + const String & string); + bool plugin_get_config_value(struct EventStruct *event, + String & string); + + // bool plugin_ten_per_second(struct EventStruct *event); + bool plugin_fifty_per_second(struct EventStruct *event); + String loadSettings(struct EventStruct *event); + String saveSettings(struct EventStruct *event); + void applySettings(struct EventStruct *event); + bool applyDeviceModelTemplate(AXP2101_device_model_e device); + + void webform_load(struct EventStruct *event); + void webform_save(struct EventStruct *event); + + AXP2101_settings _settings; + +private: + + AXP2101 *axp2101 = nullptr; + + bool isInitialized() { + return nullptr != axp2101; + } + + float read_value(AXP2101_registers_e value); + + // *INDENT-OFF* + // Map range 0..100% + uint16_t _ranges[AXP2101_settings_count][2] = { + { AXP2101_DCDC1_MIN, AXP2101_DCDC1_MAX }, + { AXP2101_DCDC2_MIN, AXP2101_DCDC2_MAX }, + { AXP2101_DCDC3_MIN, AXP2101_DCDC3_MAX }, + { AXP2101_DCDC4_MIN, AXP2101_DCDC4_MAX }, + { AXP2101_DCDC5_MIN, AXP2101_DCDC5_MAX }, + { AXP2101_ALDO1_MIN, AXP2101_ALDO1_MAX }, + { AXP2101_ALDO2_MIN, AXP2101_ALDO2_MAX }, + { AXP2101_ALDO3_MIN, AXP2101_ALDO3_MAX }, + { AXP2101_ALDO4_MIN, AXP2101_ALDO4_MAX }, + { AXP2101_BLDO1_MIN, AXP2101_BLDO1_MAX }, + { AXP2101_BLDO2_MIN, AXP2101_BLDO2_MAX }, + { AXP2101_DLDO1_MIN, AXP2101_DLDO1_MAX }, + { AXP2101_DLDO2_MIN, AXP2101_DLDO2_MAX }, + { AXP2101_CPUSLDO_MIN, AXP2101_CPUSLDO_MAX }, + }; + + // *INDENT-ON* + + bool _settingsLoaded = false; + + AXP2101_chargingState_e _chargingState = AXP2101_chargingState_e::Standby; +}; + +# endif // ifdef ESP32 +#endif // ifdef USES_P139 +#endif // ifndef PLUGINSTRUCTS_P139_DATA_STRUCT_H diff --git a/src/src/PluginStructs/P139_data_struct_formselectors.cpp b/src/src/PluginStructs/P139_data_struct_formselectors.cpp new file mode 100644 index 0000000000..c4506096d9 --- /dev/null +++ b/src/src/PluginStructs/P139_data_struct_formselectors.cpp @@ -0,0 +1,282 @@ +#include "../PluginStructs/P139_data_struct_formselectors.h" + +#ifdef USES_P139 + + +// ********************************************************************** +// Charge LED settings +// ********************************************************************** +AXP2101_ChargeLED_FormSelector::AXP2101_ChargeLED_FormSelector( + AXP2101_chargeled_d selected) : + FormSelectorOptions(5) +{ + addFormSelector( + F("Charge LED"), F("led"), + static_cast(selected)); +} + +AXP2101_chargeled_d AXP2101_ChargeLED_FormSelector::get() +{ + return static_cast(getFormItemInt(F("led"))); +} + +AXP2101_chargeled_d get_AXP2101_chargeled_d(int index) { + if (index < 0) { return AXP2101_chargeled_d::Off; } + + if (index <= static_cast(AXP2101_chargeled_d::Steady_On)) { + return static_cast(index); + } + return AXP2101_chargeled_d::Protected; +} + +String AXP2101_ChargeLED_FormSelector::getOptionString(int index) const +{ + return toString(get_AXP2101_chargeled_d(index)); +} + +int AXP2101_ChargeLED_FormSelector::getIndexValue(int index) const +{ + return static_cast(get_AXP2101_chargeled_d(index)); +} + +// ********************************************************************** +// Reg 61: Iprechg Charger Settings +// 0 .. 200 mA in 25 mA steps +// ********************************************************************** +AXP2101_PreChargeCurrentLimit_FormSelector::AXP2101_PreChargeCurrentLimit_FormSelector( + int selected) : FormSelectorOptions(9) +{ + addFormSelector( + F("Pre Charge Current"), F("iprechg"), + static_cast(selected)); + addUnit(F("mA")); + addFormNote(F("When V_bat < 3V, the battery will be charged using pre-charge current")); +} + +int AXP2101_PreChargeCurrentLimit_FormSelector::get() +{ + return getFormItemInt(F("iprechg")); +} + +int get_AXP2101_0_to_200mA_ChargeCurrentLimit(int index) { + if (index < 0) { return 0; } + const int res = 25 * index; + + if (res > 200) { return 200; } + return res; +} + +String AXP2101_PreChargeCurrentLimit_FormSelector::getOptionString(int index) const +{ + return String(get_AXP2101_0_to_200mA_ChargeCurrentLimit(index)); +} + +int AXP2101_PreChargeCurrentLimit_FormSelector::getIndexValue(int index) const +{ + return get_AXP2101_0_to_200mA_ChargeCurrentLimit(index); +} + +// ********************************************************************** +// Reg 62: ICC Charger Settings +// 0 .. 200 mA in 25 mA steps +// 200 ... 1000 mA in 100 mA steps +// ********************************************************************** +AXP2101_ConstChargeCurrentLimit_FormSelector::AXP2101_ConstChargeCurrentLimit_FormSelector( + int selected) : FormSelectorOptions(17) +{ + addFormSelector( + F("Constant Current Charge Limit"), F("iccchg"), + static_cast(selected)); + addUnit(F("mA")); +} + +int AXP2101_ConstChargeCurrentLimit_FormSelector::get() +{ + return getFormItemInt(F("iccchg")); +} + +int get_AXP2101_ConstChargeCurrentLimit(int index) { + if (index < 0) { return 0; } + const int res = index <= 8 + ? 25 * index + : (index - 8) * 100 + 200; + + if (res > 1000) { return 1000; } + return res; +} + +String AXP2101_ConstChargeCurrentLimit_FormSelector::getOptionString(int index) const +{ + return String(get_AXP2101_ConstChargeCurrentLimit(index)); +} + +int AXP2101_ConstChargeCurrentLimit_FormSelector::getIndexValue(int index) const +{ + return get_AXP2101_ConstChargeCurrentLimit(index); +} + +// ********************************************************************** +// Reg 63: Iterm Charger Settings and Control +// 0 .. 200 mA in 25 mA steps + enable checkbox +// ********************************************************************** +AXP2101_TerminationChargeCurrentLimit_FormSelector::AXP2101_TerminationChargeCurrentLimit_FormSelector( + int selected) : FormSelectorOptions(9) +{ + addFormSelector( + F("Termination Charge Current"), F("iterm"), + static_cast(selected)); + addUnit(F("mA")); + addFormNote(F("Charge current threshold to switch to CV charging or stop charging, when battery is nearly full")); +} + +int AXP2101_TerminationChargeCurrentLimit_FormSelector::get() +{ + return getFormItemInt(F("iterm")); +} + +String AXP2101_TerminationChargeCurrentLimit_FormSelector::getOptionString(int index) const +{ + return String(get_AXP2101_0_to_200mA_ChargeCurrentLimit(index)); +} + +int AXP2101_TerminationChargeCurrentLimit_FormSelector::getIndexValue(int index) const +{ + return get_AXP2101_0_to_200mA_ChargeCurrentLimit(index); +} + +// ********************************************************************** +// Reg 64: CV Charger Voltage Settings +// ********************************************************************** +AXP2101_CV_charger_voltage_FormSelector::AXP2101_CV_charger_voltage_FormSelector( + AXP2101_CV_charger_voltage_e selected) : + FormSelectorOptions(static_cast(AXP2101_CV_charger_voltage_e::MAX) - 1) +{ + addFormSelector( + F("CV Charger Voltage"), F("cv_volt"), + static_cast(selected)); + addUnit(F("V")); + addFormNote(F("Target charge voltage of battery")); +} + +AXP2101_CV_charger_voltage_e AXP2101_CV_charger_voltage_FormSelector::get() +{ + return static_cast(getFormItemInt(F("cv_volt"))); +} + +AXP2101_CV_charger_voltage_e get_AXP2101_CV_charger_voltage_e(int index) { + if (index < 0) { return AXP2101_CV_charger_voltage_e::reserved; } + constexpr int max = static_cast(AXP2101_CV_charger_voltage_e::MAX); + index += 1; + + if (index >= max) { return AXP2101_CV_charger_voltage_e::reserved; } + return static_cast(index); +} + +String AXP2101_CV_charger_voltage_FormSelector::getOptionString(int index) const +{ + const AXP2101_CV_charger_voltage_e val = get_AXP2101_CV_charger_voltage_e(index); + int decimal = index; + + if (AXP2101_CV_charger_voltage_e::limit_4_35V == val) { + index = 35; + } + return concat(F("4."), index); +} + +int AXP2101_CV_charger_voltage_FormSelector::getIndexValue(int index) const +{ + return static_cast(get_AXP2101_CV_charger_voltage_e(index)); +} + +// ********************************************************************** +// Reg 14: Minimum System Voltage Control +// ********************************************************************** +AXP2101_Linear_Charger_Vsys_dpm_FormSelector::AXP2101_Linear_Charger_Vsys_dpm_FormSelector( + AXP2101_Linear_Charger_Vsys_dpm_e selected) : + FormSelectorOptions(static_cast(AXP2101_Linear_Charger_Vsys_dpm_e::MAX)) +{ + addFormSelector( + F("Minimum System Voltage"), F("min_vsys"), + static_cast(selected)); + addUnit(F("V")); + addFormNote(F("Minimum system voltage to allow charging the battery")); +} + +AXP2101_Linear_Charger_Vsys_dpm_e AXP2101_Linear_Charger_Vsys_dpm_FormSelector::get() +{ + return static_cast(getFormItemInt(F("min_vsys"))); +} + +String AXP2101_Linear_Charger_Vsys_dpm_FormSelector::getOptionString(int index) const +{ + constexpr int max = static_cast(AXP2101_Linear_Charger_Vsys_dpm_e::MAX); + + if ((index >= max) || (index < 0)) { + return EMPTY_STRING; + } + return concat(F("4."), index + 1); +} + +// ********************************************************************** +// Reg 15: Input Voltage Limit +// ********************************************************************** +AXP2101_Vin_DPM_FormSelector::AXP2101_Vin_DPM_FormSelector( + AXP2101_VINDPM_e selected) : + FormSelectorOptions(static_cast(AXP2101_VINDPM_e::MAX)) +{ + addFormSelector( + F("Min Vin_dpm Voltage"), F("vin_dpm"), + static_cast(selected)); + addUnit(F("V")); + addFormNote(F("When Vbus reaches Vin_dpm, the charge current will decrease until zero")); +} + +AXP2101_VINDPM_e AXP2101_Vin_DPM_FormSelector::get() +{ + return static_cast(getFormItemInt(F("vin_dpm"))); +} + +String AXP2101_Vin_DPM_FormSelector::getOptionString(int index) const +{ + constexpr int max = static_cast(AXP2101_VINDPM_e::MAX); + + if ((index >= max) || (index < 0)) { + return EMPTY_STRING; + } + return toString(3.88f + 0.08f * index, 2); +} + +// ********************************************************************** +// Reg 16: Input Current Limit +// ********************************************************************** +AXP2101_InputCurrentLimit_FormSelector::AXP2101_InputCurrentLimit_FormSelector( + AXP2101_InputCurrentLimit_e selected) : + FormSelectorOptions(static_cast(AXP2101_InputCurrentLimit_e::MAX)) +{ + addFormSelector( + F("Input Current Limit"), F("cur_lim_in"), + static_cast(selected)); + addUnit(F("mA")); + // If I_sys is over the input power supply capability, V_sys will drop. + // If V_bat is above V_sys, PMU will enter supplement mode. +} + +AXP2101_InputCurrentLimit_e AXP2101_InputCurrentLimit_FormSelector::get() +{ + return static_cast(getFormItemInt(F("cur_lim_in"))); +} + +String AXP2101_InputCurrentLimit_FormSelector::getOptionString(int index) const +{ + constexpr int max = static_cast(AXP2101_InputCurrentLimit_e::MAX); + + if ((index >= max) || (index < 0)) { + return EMPTY_STRING; + } + const int value = (index < 3) + ? 100 + (400 * index) + : 1000 + ((index - 3)) * 500; + return String(value); +} + +#endif // ifdef USES_P139 diff --git a/src/src/PluginStructs/P139_data_struct_formselectors.h b/src/src/PluginStructs/P139_data_struct_formselectors.h new file mode 100644 index 0000000000..5da3e4a4b6 --- /dev/null +++ b/src/src/PluginStructs/P139_data_struct_formselectors.h @@ -0,0 +1,130 @@ +#pragma once + +#include "../../_Plugin_Helper.h" + +#ifdef USES_P139 + +# include + +// ********************************************************************** +// Charge LED settings +// ********************************************************************** +class AXP2101_ChargeLED_FormSelector : public FormSelectorOptions { +public: + + AXP2101_ChargeLED_FormSelector(AXP2101_chargeled_d selected); + + static AXP2101_chargeled_d get(); + + virtual String getOptionString(int index) const override; + virtual int getIndexValue(int index) const override; +}; + + +// ********************************************************************** +// Reg 61: Iprechg Charger Settings +// 0 .. 200 mA in 25 mA steps +// ********************************************************************** +class AXP2101_PreChargeCurrentLimit_FormSelector : public FormSelectorOptions { +public: + + AXP2101_PreChargeCurrentLimit_FormSelector(int selected); + + static int get(); + + virtual String getOptionString(int index) const override; + virtual int getIndexValue(int index) const override; +}; + + +// ********************************************************************** +// Reg 62: ICC Charger Settings +// 0 .. 200 mA in 25 mA steps +// 200 ... 1000 mA in 100 mA steps +// ********************************************************************** +class AXP2101_ConstChargeCurrentLimit_FormSelector : public FormSelectorOptions { +public: + + AXP2101_ConstChargeCurrentLimit_FormSelector(int selected); + + static int get(); + + virtual String getOptionString(int index) const override; + virtual int getIndexValue(int index) const override; +}; + + +// ********************************************************************** +// Reg 63: Iterm Charger Settings and Control +// 0 .. 200 mA in 25 mA steps + enable checkbox +// ********************************************************************** +class AXP2101_TerminationChargeCurrentLimit_FormSelector : public FormSelectorOptions { +public: + + AXP2101_TerminationChargeCurrentLimit_FormSelector(int selected); + + static int get(); + + virtual String getOptionString(int index) const override; + virtual int getIndexValue(int index) const override; +}; + + +// ********************************************************************** +// Reg 64: CV Charger Voltage Settings +// ********************************************************************** +class AXP2101_CV_charger_voltage_FormSelector : public FormSelectorOptions { +public: + + AXP2101_CV_charger_voltage_FormSelector(AXP2101_CV_charger_voltage_e selected); + + static AXP2101_CV_charger_voltage_e get(); + + virtual String getOptionString(int index) const override; + virtual int getIndexValue(int index) const override; +}; + + +// ********************************************************************** +// Reg 14: Minimum System Voltage Control +// ********************************************************************** +class AXP2101_Linear_Charger_Vsys_dpm_FormSelector : public FormSelectorOptions { +public: + + AXP2101_Linear_Charger_Vsys_dpm_FormSelector(AXP2101_Linear_Charger_Vsys_dpm_e selected); + + static AXP2101_Linear_Charger_Vsys_dpm_e get(); + + virtual String getOptionString(int index) const override; +}; + + +// ********************************************************************** +// Reg 15: Input Voltage Limit +// ********************************************************************** +class AXP2101_Vin_DPM_FormSelector : public FormSelectorOptions { +public: + + AXP2101_Vin_DPM_FormSelector(AXP2101_VINDPM_e selected); + + static AXP2101_VINDPM_e get(); + + virtual String getOptionString(int index) const override; +}; + + +// ********************************************************************** +// Reg 16: Input Current Limit +// ********************************************************************** +class AXP2101_InputCurrentLimit_FormSelector : public FormSelectorOptions { +public: + + AXP2101_InputCurrentLimit_FormSelector(AXP2101_InputCurrentLimit_e selected); + + static AXP2101_InputCurrentLimit_e get(); + + virtual String getOptionString(int index) const override; +}; + + +#endif // ifdef USES_P139 diff --git a/src/src/PluginStructs/P148_data_struct.cpp b/src/src/PluginStructs/P148_data_struct.cpp index 9faa757a23..378c5c11d8 100644 --- a/src/src/PluginStructs/P148_data_struct.cpp +++ b/src/src/PluginStructs/P148_data_struct.cpp @@ -158,10 +158,10 @@ void P148_data_struct::MonitorTaskValue_t::webformLoad(int index) const { static_cast(P148_data_struct::Tm1621UnitOfMeasure::kWh_Watt) }; constexpr size_t nrElements = sizeof(optionValues) / sizeof(optionValues[0]); - - addFormSelector( + const FormSelectorOptions selector(nrElements, options, optionValues); + selector.addFormSelector( F("Unit Symbols"), concat(F("punit"), index), - nrElements, options, optionValues, static_cast(unit)); + static_cast(unit)); } else { const __FlashStringHelper *options[] = { F("None"), @@ -177,9 +177,10 @@ void P148_data_struct::MonitorTaskValue_t::webformLoad(int index) const { }; constexpr size_t nrElements = sizeof(optionValues) / sizeof(optionValues[0]); - addFormSelector( + const FormSelectorOptions selector(nrElements, options, optionValues); + selector.addFormSelector( F("Unit Symbols"), concat(F("punit"), index), - nrElements, options, optionValues, static_cast(unit)); + static_cast(unit)); } } else { addFormCheckBox(F("Clear Line"), concat(F("pshowname"), index), showname); diff --git a/src/src/PluginStructs/P165_data_struct.cpp b/src/src/PluginStructs/P165_data_struct.cpp index 48d4eebda8..a7ceb8e1f7 100644 --- a/src/src/PluginStructs/P165_data_struct.cpp +++ b/src/src/PluginStructs/P165_data_struct.cpp @@ -201,7 +201,8 @@ bool P165_data_struct::plugin_webform_load(struct EventStruct *event) { { const __FlashStringHelper *stripOptions[] = { F("GRB"), F("GRBW") }; const int stripOptionValues[] = { P165_STRIP_TYPE_RGB, P165_STRIP_TYPE_RGBW }; - addFormSelector(F("Strip Type"), F("stripe"), NR_ELEMENTS(stripOptionValues), stripOptions, stripOptionValues, P165_CONFIG_STRIP_TYPE); + const FormSelectorOptions selector(NR_ELEMENTS(stripOptionValues), stripOptions, stripOptionValues); + selector.addFormSelector(F("Strip Type"), F("stripe"), P165_CONFIG_STRIP_TYPE); } if ((0 == P165_CONFIG_DEF_BRIGHT) && (0 == P165_CONFIG_MAX_BRIGHT)) { @@ -234,8 +235,8 @@ bool P165_data_struct::plugin_webform_load(struct EventStruct *event) { P165_DISP_CLOCK12, P165_DISP_DATE, }; - addFormSelector(F("Display Output"), F("dspout"), NR_ELEMENTS(disploutOptions), - displout, disploutOptions, P165_CONFIG_OUTPUTTYPE); + const FormSelectorOptions selector(NR_ELEMENTS(disploutOptions), displout, disploutOptions); + selector.addFormSelector(F("Display Output"), F("dspout"), P165_CONFIG_OUTPUTTYPE); # endif // if P165_FEATURE_P073 int dgtCount = 0; @@ -283,13 +284,12 @@ bool P165_data_struct::plugin_webform_load(struct EventStruct *event) { ? EMPTY_STRING : AdaGFXrgb565ToWebColor(P165_CONFIG_FG_COLOR); - addFormSelector(F("Number of Groups *"), - F("grps"), - NR_ELEMENTS(digitOptionValues), - digitOptions, - digitOptionValues, - grpCount, - true); + FormSelectorOptions selector( + NR_ELEMENTS(digitOptionValues), + digitOptions, + digitOptionValues); + selector.reloadonchange = true; + selector.addFormSelector(F("Number of Groups *"), F("grps"), grpCount); AdaGFXFormForeAndBackColors(F("fgcolor"), P165_CONFIG_FG_COLOR, @@ -355,12 +355,15 @@ bool P165_data_struct::plugin_webform_load(struct EventStruct *event) { html_table(F("")); addRowLabel(F("Number of Digits *")); - addSelector(concat(F("dgts"), grp10), - NR_ELEMENTS(digitOptionValues), - digitOptions, - digitOptionValues, nullptr, - grpDgts, - true, !numberPlan); // 1st and 2nd column + FormSelectorOptions selector( + NR_ELEMENTS(digitOptionValues), + digitOptions, + digitOptionValues); + selector.reloadonchange = true; + selector.enabled = !numberPlan; // 1st and 2nd column + selector.addSelector( + concat(F("dgts"), grp10), + grpDgts); { // 3rd column = "Digit " / "(Extra)" for (uint8_t dgt = 0; dgt < grpDgts; ++dgt) { @@ -477,12 +480,13 @@ bool P165_data_struct::plugin_webform_load(struct EventStruct *event) { const uint8_t strt = grpStart + grpGstrt << 1; addRowLabel(F("Starting segment")); - addSelector(concat(F("strt"), grp10), - NR_ELEMENTS(startPixelOptions), - startPixelOptions, - nullptr, nullptr, - strt, false, - !numberPlan); + FormSelectorOptions selector( + NR_ELEMENTS(startPixelOptions), + startPixelOptions); + selector.enabled = !numberPlan; + selector.addSelector( + concat(F("strt"), grp10), + strt); addFormCheckBox(F("Split g-segment pixels"), concat(F("spltg"), grp10), P165_GET_CONFIG_SPLTG(grp), numberPlan || grpGstrt); diff --git a/src/src/WebServer/AccessControl.cpp b/src/src/WebServer/AccessControl.cpp index 2723391ad0..56c6eda03f 100644 --- a/src/src/WebServer/AccessControl.cpp +++ b/src/src/WebServer/AccessControl.cpp @@ -1,5 +1,7 @@ #include "../WebServer/AccessControl.h" +#include "../DataTypes/FormSelectorOptions.h" + #include "../ESPEasyCore/ESPEasy_Log.h" #include "../ESPEasyCore/ESPEasyNetwork.h" #include "../ESPEasyCore/ESPEasyWifi.h" @@ -142,7 +144,8 @@ void clearAccessBlock() // ******************************************************************************** void addIPaccessControlSelect(const String& name, int choice) { - const __FlashStringHelper * options[3] = { F("Allow All"), F("Allow Local Subnet"), F("Allow IP range") }; + const __FlashStringHelper * options[] = { F("Allow All"), F("Allow Local Subnet"), F("Allow IP range") }; - addSelector(name, 3, options, nullptr, nullptr, choice); + const FormSelectorOptions selector(NR_ELEMENTS(options), options); + selector.addSelector(name, choice); } diff --git a/src/src/WebServer/AdvancedConfigPage.cpp b/src/src/WebServer/AdvancedConfigPage.cpp index 4009769e7e..5a46b09fd9 100644 --- a/src/src/WebServer/AdvancedConfigPage.cpp +++ b/src/src/WebServer/AdvancedConfigPage.cpp @@ -333,14 +333,16 @@ void handle_advanced() { F("Light"), F("Dark"), }; - const int cssModeOptions[] = { 0, 1, 2}; - constexpr int nrCssModeOptions = NR_ELEMENTS(cssModeOptions); - addFormSelector(getLabel(LabelType::ENABLE_AUTO_DARK_MODE), - getInternalLabel(LabelType::ENABLE_AUTO_DARK_MODE), - nrCssModeOptions, - cssModeNames, - cssModeOptions, - Settings.getCssMode()); + //const int cssModeOptions[] = { 0, 1, 2}; + constexpr int nrCssModeOptions = NR_ELEMENTS(cssModeNames); + const FormSelectorOptions selector( + nrCssModeOptions, + cssModeNames/*, + cssModeOptions*/); + selector.addFormSelector( + getLabel(LabelType::ENABLE_AUTO_DARK_MODE), + getInternalLabel(LabelType::ENABLE_AUTO_DARK_MODE), + Settings.getCssMode()); #endif // FEATURE_AUTO_DARK_MODE #if FEATURE_RULES_EASY_COLOR_CODE @@ -418,18 +420,21 @@ void addFormDstSelect(bool isStart, uint16_t choice) { addRowLabel(concat( isStart ? F("Start") : F("End"), F(" (week, dow, month)"))); - addSelector( + + const FormSelectorOptions selector(NR_ELEMENTS(weekValues), week, weekValues); + selector.addSelector( isStart ? F("dststartweek") : F("dstendweek"), - NR_ELEMENTS(weekValues), week, weekValues, nullptr, rule.week); + rule.week); } html_BR(); { const __FlashStringHelper * dow[] = { F("Sun"), F("Mon"), F("Tue"), F("Wed"), F("Thu"), F("Fri"), F("Sat") }; constexpr int dowValues[] = { 1, 2, 3, 4, 5, 6, 7 }; - addSelector( + const FormSelectorOptions selector(NR_ELEMENTS(dowValues), dow, dowValues); + selector.addSelector( isStart ? F("dststartdow") : F("dstenddow"), - NR_ELEMENTS(dowValues), dow, dowValues, nullptr, rule.dow); + rule.dow); } html_BR(); { @@ -437,8 +442,10 @@ void addFormDstSelect(bool isStart, uint16_t choice) { "Dec") }; constexpr int monthValues[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; - addSelector(isStart ? F("dststartmonth") : F("dstendmonth"), - NR_ELEMENTS(monthValues), month, monthValues, nullptr, rule.month); + const FormSelectorOptions selector(NR_ELEMENTS(monthValues), month, monthValues); + selector.addSelector( + isStart ? F("dststartmonth") : F("dstendmonth"), + rule.month); } addFormNumericBox( @@ -461,7 +468,8 @@ void addFormExtTimeSourceSelect(const __FlashStringHelper * label, const __Flash static_cast(ExtTimeSource_e::PCF8563) }; - addSelector(id, NR_ELEMENTS(optionValues), options, optionValues, nullptr, static_cast(choice)); + const FormSelectorOptions selector(NR_ELEMENTS(optionValues), options, optionValues); + selector.addSelector(id, static_cast(choice)); } @@ -480,19 +488,21 @@ void addFormLogLevelSelect(LabelType::Enum label, int choice) for (int i = 0; i < LOG_LEVEL_NRELEMENTS; ++i) { options[i + 1] = getLogLevelDisplayStringFromIndex(i, optionValues[i + 1]); } - addSelector(getInternalLabel(label), LOG_LEVEL_NRELEMENTS + 1, options, optionValues, nullptr, choice); + const FormSelectorOptions selector(LOG_LEVEL_NRELEMENTS + 1, options, optionValues); + selector.addSelector(getInternalLabel(label), choice); } void addFormLogFacilitySelect(const __FlashStringHelper * label, const __FlashStringHelper * id, int choice) { addRowLabel(label); - const __FlashStringHelper * options[12] = + const __FlashStringHelper * options[] = { F("Kernel"), F("User"), F("Daemon"), F("Message"), F("Local0"), F("Local1"), F("Local2"), F("Local3"), F("Local4"), F("Local5"), F("Local6"), F("Local7") }; - const int optionValues[12] = { 0, 1, 3, 5, 16, 17, 18, 19, 20, 21, 22, 23 }; + const int optionValues[] = { 0, 1, 3, 5, 16, 17, 18, 19, 20, 21, 22, 23 }; - addSelector(id, 12, options, optionValues, nullptr, choice); + const FormSelectorOptions selector(NR_ELEMENTS(options), options, optionValues); + selector.addSelector(id, choice); } #endif // ifdef WEBSERVER_ADVANCED diff --git a/src/src/WebServer/ControllerPage.cpp b/src/src/WebServer/ControllerPage.cpp index 72b6a8e3ad..93752aff43 100644 --- a/src/src/WebServer/ControllerPage.cpp +++ b/src/src/WebServer/ControllerPage.cpp @@ -318,7 +318,7 @@ void handle_controllers_ControllerSettingsPage(controllerIndex_t controllerindex disabled); ++protocolIndex; } - addSelector_Foot(); + addSelector_Foot(true); addHelpButton(F("EasyProtocols")); diff --git a/src/src/WebServer/CustomPage.cpp b/src/src/WebServer/CustomPage.cpp index b1224c6ceb..59db449fb5 100644 --- a/src/src/WebServer/CustomPage.cpp +++ b/src/src/WebServer/CustomPage.cpp @@ -98,7 +98,7 @@ bool handle_custom(const String& path) { addSelector_Item(name, it->first, choice == it->first); } } - addSelector_Foot(); + addSelector_Foot(true); // create <> navigation buttons uint8_t prev = Settings.Unit; diff --git a/src/src/WebServer/DevicesPage.cpp b/src/src/WebServer/DevicesPage.cpp index ac62ebd169..7dcc202e43 100644 --- a/src/src/WebServer/DevicesPage.cpp +++ b/src/src/WebServer/DevicesPage.cpp @@ -252,7 +252,7 @@ void addDeviceSelect(const __FlashStringHelper *name, pluginID_t choice) ++x; } - addSelector_Foot(); + addSelector_Foot(true); } // ******************************************************************************** @@ -1239,13 +1239,15 @@ void devicePage_show_I2C_config(taskIndex_t taskIndex, deviceIndex_t DeviceIndex } else { i2c_mux_channelCount++; } - addFormSelector(F("Multiplexer channels"), - F("taskdeviceflags1"), - i2c_mux_channelCount, - i2c_mux_channels, - i2c_mux_channelOptions, - multipleMuxPorts ? 1 : 0, - true); + FormSelectorOptions selector( + i2c_mux_channelCount, + i2c_mux_channels, + i2c_mux_channelOptions); + selector.reloadonchange = true; + selector.addFormSelector( + F("Multiplexer channels"), + F("taskdeviceflags1"), + multipleMuxPorts ? 1 : 0); } if (multipleMuxPorts) { @@ -1279,12 +1281,14 @@ void devicePage_show_I2C_config(taskIndex_t taskIndex, deviceIndex_t DeviceIndex } if (taskDeviceI2CMuxPort >= static_cast(mux_max)) { taskDeviceI2CMuxPort = -1; } // Reset if out of range - addFormSelector(F("Connected to"), - F("taskdevicei2cmuxport"), - mux_max + 1, - i2c_mux_portoptions, - i2c_mux_portchoices, - taskDeviceI2CMuxPort); + const FormSelectorOptions selector( + mux_max + 1, + i2c_mux_portoptions, + i2c_mux_portchoices); + selector.addFormSelector( + F("Connected to"), + F("taskdevicei2cmuxport"), + taskDeviceI2CMuxPort); } } # endif // if FEATURE_I2CMULTIPLEXER @@ -1550,12 +1554,9 @@ void devicePage_show_task_values(taskIndex_t taskIndex, deviceIndex_t DeviceInde selected += 4; } - addSelector( + const FormSelectorOptions selector(NR_ELEMENTS(chartAxis), chartAxis); + selector.addSelector( getPluginCustomArgName(F("TDSA"), varNr), - NR_ELEMENTS(chartAxis), - chartAxis, - nullptr, - nullptr, selected); } # endif // if FEATURE_PLUGIN_STATS diff --git a/src/src/WebServer/FactoryResetPage.cpp b/src/src/WebServer/FactoryResetPage.cpp index ee1f2ffe38..290616467b 100644 --- a/src/src/WebServer/FactoryResetPage.cpp +++ b/src/src/WebServer/FactoryResetPage.cpp @@ -131,7 +131,7 @@ void addPreDefinedConfigSelector() { model == active_model); } } - addSelector_Foot(); + addSelector_Foot(true); } #ifdef WEBSERVER_NEW_UI diff --git a/src/src/WebServer/HardwarePage.cpp b/src/src/WebServer/HardwarePage.cpp index 7542abce7e..093774d096 100644 --- a/src/src/WebServer/HardwarePage.cpp +++ b/src/src/WebServer/HardwarePage.cpp @@ -143,7 +143,6 @@ void handle_hardware() { addFormSubHeader(F("I2C Multiplexer")); // Select the type of multiplexer to use { - # define I2C_MULTIPLEXER_OPTIONCOUNT 5 // Nr. of supported devices + 'None' const __FlashStringHelper *i2c_muxtype_options[] = { F("- None -"), F("TCA9548a - 8 channel"), @@ -158,8 +157,9 @@ void handle_hardware() { I2C_MULTIPLEXER_TCA9543A, I2C_MULTIPLEXER_PCA9540 }; - addFormSelector(F("I2C Multiplexer type"), F("pi2cmuxtype"), I2C_MULTIPLEXER_OPTIONCOUNT, - i2c_muxtype_options, i2c_muxtype_choices, Settings.I2C_Multiplexer_Type); + const FormSelectorOptions selector(NR_ELEMENTS(i2c_muxtype_choices), + i2c_muxtype_options, i2c_muxtype_choices); + selector.addFormSelector(F("I2C Multiplexer type"), F("pi2cmuxtype"), Settings.I2C_Multiplexer_Type); } // Select the I2C address for a port multiplexer { @@ -180,7 +180,8 @@ void handle_hardware() { } i2c_mux_choices[mux_opt] = 0x70 + x; } - addFormSelector(F("I2C Multiplexer address"), F("pi2cmuxaddr"), mux_opt + 1, i2c_mux_options, i2c_mux_choices, Settings.I2C_Multiplexer_Addr); + const FormSelectorOptions selector(mux_opt + 1, i2c_mux_options, i2c_mux_choices); + selector.addFormSelector(F("I2C Multiplexer address"), F("pi2cmuxaddr"), Settings.I2C_Multiplexer_Addr); } addFormPinSelect(PinSelectPurpose::Generic_output, formatGpioName_output_optional(F("Reset")), F("pi2cmuxreset"), Settings.I2C_Multiplexer_ResetPin); addFormNote(F("Will be pulled low to force a reset. Reset is not available on PCA9540.")); @@ -214,7 +215,9 @@ void handle_hardware() { static_cast(SPI_Options_e::UserDefined) }; constexpr size_t nrOptions = NR_ELEMENTS(spi_index); - addFormSelector_script(F("Init SPI"), F("initspi"), nrOptions, spi_options, spi_index, nullptr, Settings.InitSPI, F("spiOptionChanged(this)")); + FormSelectorOptions selector(nrOptions, spi_options, spi_index); + selector.onChangeCall = F("spiOptionChanged(this)"); + selector.addFormSelector(F("Init SPI"), F("initspi"), Settings.InitSPI); // User-defined pins addFormPinSelect(PinSelectPurpose::SPI, formatGpioName_output(F("CLK")), F("spipinsclk"), Settings.SPI_SCLK_pin); addFormPinSelect(PinSelectPurpose::SPI_MISO, formatGpioName_input(F("MISO")), F("spipinmiso"), Settings.SPI_MISO_pin); @@ -241,7 +244,8 @@ void handle_hardware() { toString(NetworkMedium_t::WIFI), toString(NetworkMedium_t::Ethernet) }; - addSelector(F("ethwifi"), 2, ethWifiOptions, nullptr, nullptr, static_cast(Settings.NetworkMedium), false, true); + const FormSelectorOptions selector(2, ethWifiOptions); + selector.addSelector(F("ethwifi"), static_cast(Settings.NetworkMedium)); } addFormNote(F("Change Switch between WiFi and Ethernet requires reboot to activate")); { @@ -311,14 +315,14 @@ void handle_hardware() { ? static_cast(Settings.ETH_Phy_Type) : static_cast(EthPhyType_t::notSet); - addFormSelector( - F("Ethernet PHY type"), - F("ethtype"), + const FormSelectorOptions selector( nrItems, ethPhyTypes, - ethPhyTypes_index, - choice, - false); + ethPhyTypes_index); + selector.addFormSelector( + F("Ethernet PHY type"), + F("ethtype"), + choice); } #if CONFIG_ETH_USE_SPI_ETHERNET && CONFIG_ETH_USE_ESP32_EMAC @@ -353,13 +357,14 @@ void handle_hardware() { #if CONFIG_ETH_USE_ESP32_EMAC addRowLabel_tr_id(F("Ethernet Clock"), F("ethclock")); { - const __FlashStringHelper * ethClockOptions[4] = { + const __FlashStringHelper * ethClockOptions[] = { toString(EthClockMode_t::Ext_crystal_osc), toString(EthClockMode_t::Int_50MHz_GPIO_0), toString(EthClockMode_t::Int_50MHz_GPIO_16), toString(EthClockMode_t::Int_50MHz_GPIO_17_inv) }; - addSelector(F("ethclock"), 4, ethClockOptions, nullptr, nullptr, static_cast(Settings.ETH_Clock_Mode), false, true); + const FormSelectorOptions selector(NR_ELEMENTS(ethClockOptions), ethClockOptions); + selector.addSelector(F("ethclock"), static_cast(Settings.ETH_Clock_Mode)); } #endif #endif // if FEATURE_ETHERNET diff --git a/src/src/WebServer/I2C_Scanner.cpp b/src/src/WebServer/I2C_Scanner.cpp index c51bff82fb..a01a40c6ce 100644 --- a/src/src/WebServer/I2C_Scanner.cpp +++ b/src/src/WebServer/I2C_Scanner.cpp @@ -230,7 +230,7 @@ String getKnownI2Cdevice(uint8_t address) { result += F("VL53L0X,VL53L1X"); break; case 0x34: - result += F("AXP192"); + result += F("AXP192,AXP2101"); break; case 0x36: result += F("MAX1704x,Adafruit Rotary enc, Adafruit Soil moisture,AS5600"); diff --git a/src/src/WebServer/Markup.cpp b/src/src/WebServer/Markup.cpp index 6e95390e18..ff9dc6c7ce 100644 --- a/src/src/WebServer/Markup.cpp +++ b/src/src/WebServer/Markup.cpp @@ -15,174 +15,19 @@ #include "../../ESPEasy_common.h" -// ******************************************************************************** -// Add Selector -// ******************************************************************************** -void addSelector(const __FlashStringHelper *id, - int optionCount, - const __FlashStringHelper *options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange, - bool enabled) -{ - addSelector(String(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, - bool reloadonchange, - bool enabled) -{ - addSelector(id, optionCount, options, indices, attr, selectedIndex, reloadonchange, enabled, F("wide")); -} -void addSelector(const String& id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange, - bool enabled) -{ - 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, - bool reloadonchange, - bool enabled, - const __FlashStringHelper * classname - #if FEATURE_TOOLTIPS - , const String & tooltip - #endif // if FEATURE_TOOLTIPS - ) -{ - // FIXME TD-er Change bool to disabled - if (reloadonchange) - { - addSelector_Head_reloadOnChange(id, classname, !enabled - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); - } else { - do_addSelector_Head(id, classname, EMPTY_STRING, !enabled - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); - } - addSelector_options(optionCount, options, indices, attr, selectedIndex); - addSelector_Foot(); -} - -void addSelector_reloadOnChange( - const String& id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - const String& onChangeCall, - bool enabled, - const __FlashStringHelper * classname - #if FEATURE_TOOLTIPS - , - const String& tooltip - #endif // if FEATURE_TOOLTIPS - ) -{ - // FIXME TD-er Change bool to disabled - do_addSelector_Head(id, classname, onChangeCall, !enabled - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); - addSelector_options(optionCount, options, indices, attr, selectedIndex); - addSelector_Foot(); -} - - -void addSelector(const String & id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange, - bool enabled, - const __FlashStringHelper * classname - #if FEATURE_TOOLTIPS - , const String& tooltip - #endif // if FEATURE_TOOLTIPS - ) +#if FEATURE_TOOLTIPS +void addTooltip(const String& tooltip) { - // FIXME TD-er Change bool to disabled - if (reloadonchange) - { - addSelector_Head_reloadOnChange(id, classname, !enabled - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); - } else { - do_addSelector_Head(id, classname, EMPTY_STRING, !enabled - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); + if (tooltip.length() > 0) { + addHtmlAttribute(F("title"), tooltip); } - addSelector_options(optionCount, options, indices, attr, selectedIndex); - addSelector_Foot(); } +#endif -void addSelector_options(int optionCount, const __FlashStringHelper *options[], const int indices[], const String attr[], int selectedIndex) -{ - for (uint8_t x = 0; x < optionCount; ++x) - { - const int index = indices ? indices[x] : x; - addSelector_Item( - options[x], - index, - selectedIndex == index, - false, - attr ? attr[x] : EMPTY_STRING); - if ((x & 0x07) == 0) delay(0); - } -} - -void addSelector_options(int optionCount, const String options[], const int indices[], const String attr[], int selectedIndex) -{ - for (uint8_t x = 0; x < optionCount; ++x) - { - const int index = indices ? indices[x] : x; - addSelector_Item( - options[x], - index, - selectedIndex == index, - false, - attr ? attr[x] : EMPTY_STRING); - if ((x & 0x07) == 0) delay(0); - } -} void addSelector_Head(const String& id) { - do_addSelector_Head(id, F("wide"), EMPTY_STRING, false - #if FEATURE_TOOLTIPS - , F("") - #endif // if FEATURE_TOOLTIPS - ); + do_addSelector_Head(id, F("wide"), EMPTY_STRING, false); } void addSelector_Head_reloadOnChange(const __FlashStringHelper * id) { @@ -202,14 +47,21 @@ void addSelector_Head_reloadOnChange(const String& id, , const String& tooltip #endif // if FEATURE_TOOLTIPS ) { - do_addSelector_Head(id, classname, F("return dept_onchange(frmselect)"), disabled - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); + addSelector_Head_reloadOnChange( + id, + classname, + F("return dept_onchange(frmselect)"), + disabled +#if FEATURE_TOOLTIPS + , tooltip +#endif // if FEATURE_TOOLTIPS + ); } -void addSelector_Head_reloadOnChange(const String& id, const __FlashStringHelper * classname, const String& onChangeCall, bool disabled +void addSelector_Head_reloadOnChange(const String& id, + const __FlashStringHelper * classname, + const String& onChangeCall, + bool disabled #if FEATURE_TOOLTIPS , const String& tooltip #endif // if FEATURE_TOOLTIPS @@ -234,10 +86,7 @@ void do_addSelector_Head(const String& id, const __FlashStringHelper * classname addHtmlAttribute(F("id"), id); #if FEATURE_TOOLTIPS - - if (tooltip.length() > 0) { - addHtmlAttribute(F("title"), tooltip); - } + addTooltip(tooltip); #endif // if FEATURE_TOOLTIPS if (disabled) { @@ -417,16 +266,24 @@ void addSelector_Item(const String& option, int index, bool selected, bool addHtml(F("")); } -void addSelector_Foot() +void addSelector_Foot(bool reloadonchange) { addHtml(F("")); + if (reloadonchange) { +#if FEATURE_TOOLTIPS + addHtml(F("🔄")); +#else + addHtml(F("🔄")); +#endif + } } void addUnit(const __FlashStringHelper *unit) { - addHtml(F(" [")); - addHtml(unit); - addHtml(']'); + // Needed so we can check whether it is empty + addUnit(String(unit)); } void addUnit(const String& unit) @@ -439,6 +296,7 @@ void addUnit(const String& unit) void addUnit(char unit) { + if (unit == '\0') return; addHtml(F(" [")); addHtml(unit); addHtml(']'); @@ -651,10 +509,7 @@ void addCheckBox(const String& id, bool checked, bool disabled if (disabled) { addDisabled(); } addHtml('\''); #if FEATURE_TOOLTIPS - - if (tooltip.length() > 0) { - addHtmlAttribute(F("title"), tooltip); - } + addTooltip(tooltip); #endif // if FEATURE_TOOLTIPS addHtml(F(">")); } @@ -685,10 +540,7 @@ void addNumericBox(const String& id, int value, int min, int max addHtmlAttribute(F("id"), id); #if FEATURE_TOOLTIPS - - if (tooltip.length() > 0) { - addHtmlAttribute(F("title"), tooltip); - } + addTooltip(tooltip); #endif // if FEATURE_TOOLTIPS if (disabled) { @@ -753,11 +605,7 @@ void addFloatNumberBox(const String& id, float value, float min, float max, unsi addHtmlFloat(value, nrDecimals); #if FEATURE_TOOLTIPS - - if (!tooltip.isEmpty()) { - addHtml(strformat( - F("title='%s' "), tooltip.c_str())); - } + addTooltip(tooltip); #endif // if FEATURE_TOOLTIPS addHtml('>'); } @@ -765,6 +613,30 @@ void addFloatNumberBox(const String& id, float value, float min, float max, unsi // ******************************************************************************** // Add Textbox // ******************************************************************************** +void addTextBox(const __FlashStringHelper * id, + const String& value, + int maxlength, + const __FlashStringHelper * classname) +{ + addTextBox(String(id), value, maxlength, + false, // readonly + false, // required + EMPTY_STRING, // pattern + classname); +} + +void addTextBox(const String& id, + const String& value, + int maxlength, + const __FlashStringHelper * classname) +{ + addTextBox(id, value, maxlength, + false, // readonly + false, // required + EMPTY_STRING, // pattern + classname); +} + void addTextBox(const __FlashStringHelper * id, const String& value, int maxlength, bool readonly, bool required, const String& pattern) { addTextBox(id, value, maxlength, readonly, required, pattern, F("wide")); } @@ -813,10 +685,7 @@ void addTextBox(const String & id, } #if FEATURE_TOOLTIPS - - if (tooltip.length() > 0) { - addHtmlAttribute(F("title"), tooltip); - } + addTooltip(tooltip); #endif // if FEATURE_TOOLTIPS addHtml('>'); } @@ -865,10 +734,7 @@ void addTextArea(const String & id, } #if FEATURE_TOOLTIPS - - if (tooltip.length() > 0) { - addHtmlAttribute(F("title"), tooltip); - } + addTooltip(tooltip); #endif // if FEATURE_TOOLTIPS addHtml('>'); addHtml(value); diff --git a/src/src/WebServer/Markup.h b/src/src/WebServer/Markup.h index 46ae74d2e9..a2df43b3ea 100644 --- a/src/src/WebServer/Markup.h +++ b/src/src/WebServer/Markup.h @@ -8,94 +8,13 @@ #include "../Globals/Plugins.h" #include "../Helpers/StringGenerator_GPIO.h" +#if FEATURE_TOOLTIPS +void addTooltip(const String& tooltip); +#endif + // ******************************************************************************** // Add Selector // ******************************************************************************** -void addSelector(const __FlashStringHelper *id, - int optionCount, - const __FlashStringHelper *options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange = false, - bool enabled = true); - -void addSelector(const String & id, - int optionCount, - const __FlashStringHelper *options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange = false, - bool enabled = true); - -void addSelector(const String& id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange = false, - bool enabled = true); - - -void addSelector(const String & id, - int optionCount, - const __FlashStringHelper *options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange, - bool enabled, - const __FlashStringHelper * classname - #if FEATURE_TOOLTIPS - , - const String & tooltip = EMPTY_STRING - #endif // if FEATURE_TOOLTIPS - ); - -void addSelector(const String& id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange, - bool enabled, - const __FlashStringHelper * classname - #if FEATURE_TOOLTIPS - , - const String& tooltip = EMPTY_STRING - #endif // if FEATURE_TOOLTIPS - ); - -void addSelector_reloadOnChange( - const String& id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - const String& onChangeCall, - bool enabled, - const __FlashStringHelper * classname - #if FEATURE_TOOLTIPS - , - const String& tooltip = EMPTY_STRING - #endif // if FEATURE_TOOLTIPS - ); - - -void addSelector_options(int optionCount, - const __FlashStringHelper *options[], - const int indices[], - const String attr[], - int selectedIndex); -void addSelector_options(int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex); void addSelector_Head(const String& id); @@ -150,7 +69,7 @@ void addSelector_Item(const String& option, bool disabled = false, const String& attr = EMPTY_STRING); -void addSelector_Foot(); +void addSelector_Foot(bool reloadonchange = false); void addUnit(const __FlashStringHelper *unit); void addUnit(const String& unit); @@ -266,6 +185,17 @@ void addNumericBox(const String& id, // ******************************************************************************** // Add Textbox // ******************************************************************************** +void addTextBox(const __FlashStringHelper * id, + const String& value, + int maxlength, + const __FlashStringHelper * classname); + +void addTextBox(const String& id, + const String& value, + int maxlength, + const __FlashStringHelper * classname); + + void addTextBox(const __FlashStringHelper * id, const String& value, int maxlength, diff --git a/src/src/WebServer/Markup_Forms.cpp b/src/src/WebServer/Markup_Forms.cpp index 28ad4a2639..98af3a2ceb 100644 --- a/src/src/WebServer/Markup_Forms.cpp +++ b/src/src/WebServer/Markup_Forms.cpp @@ -161,7 +161,8 @@ void addFormNumericBox(const String& label, const String& id, int value, int min addRowLabel_tr_id(label, id); addNumericBox(id, value, min, max #if FEATURE_TOOLTIPS - , F("widenumber"), tooltip + , F("widenumber") + , tooltip #endif // if FEATURE_TOOLTIPS , disabled ); @@ -339,10 +340,7 @@ void addFormPasswordBox(const String& label, const String& id, const String& pas addHtmlAttribute(F("maxlength"), maxlength); #if FEATURE_TOOLTIPS - - if (tooltip.length() > 0) { - addHtmlAttribute(F("title"), tooltip); - } + addTooltip(tooltip); #endif // if FEATURE_TOOLTIPS addHtmlAttribute(F("value"), (password.length() == 0) ? F("") : F("*****")); addHtml('>'); @@ -427,7 +425,8 @@ void addFormSeparatorCharInput(const __FlashStringHelper *rowLabel, charList[i + 1] = charset[i]; charOpts[i + 1] = static_cast(charset[i]); } - addFormSelector(rowLabel, id, len, charList, charOpts, value); + const FormSelectorOptions selector(len, charList, charOpts); + selector.addFormSelector(rowLabel, id, value); if (!String(additionalText).isEmpty()) { addUnit(additionalText); @@ -499,161 +498,13 @@ void addFormSelectorI2C(const String& id, String option = formatToHex_decimal(addresses[x]); if (((x == 0) && (defaultAddress == 0)) || (defaultAddress == addresses[x])) { - option += F(" - (default)"); + option += F(" (default)"); } addSelector_Item(option, addresses[x], addresses[x] == selectedIndex); } addSelector_Foot(); } -void addFormSelector(const __FlashStringHelper * label, const __FlashStringHelper * id, int optionCount, const __FlashStringHelper * options[], const int indices[], int selectedIndex, bool reloadonchange) -{ - addFormSelector(String(label), String(id), optionCount, options, indices, nullptr, selectedIndex, reloadonchange); -} - -void addFormSelector(const __FlashStringHelper * label, const String& id, int optionCount, const __FlashStringHelper * options[], const int indices[], int selectedIndex, bool reloadonchange) -{ - addFormSelector(String(label), id, optionCount, options, indices, nullptr, selectedIndex, reloadonchange); -} - -void addFormSelector(const String& label, const String& id, int optionCount, const __FlashStringHelper * options[], const int indices[], int selectedIndex) -{ - addFormSelector(label, id, optionCount, options, indices, nullptr, selectedIndex, false); -} - -void addFormSelector(const __FlashStringHelper * label, const __FlashStringHelper * id, int optionCount, const String options[], const int indices[], int selectedIndex) -{ - addFormSelector(String(label), String(id), optionCount, options, indices, nullptr, selectedIndex, false); -} - -void addFormSelector(const String & label, - const String & id, - int optionCount, - const String options[], - const int indices[], - int selectedIndex - #if FEATURE_TOOLTIPS - , const String& tooltip - #endif // if FEATURE_TOOLTIPS - ) -{ - addFormSelector(label, id, optionCount, options, indices, nullptr, selectedIndex, false - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); -} - -void addFormSelector(const String& label, - const String& id, - int optionCount, - const __FlashStringHelper * options[], - const int indices[], - int selectedIndex, - bool reloadonchange) -{ - addFormSelector(label, id, optionCount, options, indices, nullptr, selectedIndex, reloadonchange); -} - -void addFormSelector(const String& label, - const String& id, - int optionCount, - const __FlashStringHelper * options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange) -{ - addRowLabel_tr_id(label, id); - addSelector(id, optionCount, options, indices, attr, selectedIndex, reloadonchange, true); -} - -void addFormSelector(const String& label, - const String& id, - int optionCount, - const String options[], - const int indices[], - int selectedIndex, - bool reloadonchange - #if FEATURE_TOOLTIPS - , const String& tooltip - #endif // if FEATURE_TOOLTIPS - ) -{ - addFormSelector(label, id, optionCount, options, indices, nullptr, selectedIndex, reloadonchange - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); -} - -void addFormSelector(const String & label, - const String & id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange - #if FEATURE_TOOLTIPS - , const String& tooltip - #endif // if FEATURE_TOOLTIPS - ) -{ - addRowLabel_tr_id(label, id); - addSelector(id, optionCount, options, indices, attr, selectedIndex, reloadonchange, true, F("wide") - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); -} - -void addFormSelector_script(const __FlashStringHelper * label, - const __FlashStringHelper * id, - int optionCount, - const __FlashStringHelper * options[], - const int indices[], - const String attr[], - int selectedIndex, - const __FlashStringHelper * onChangeCall - #if FEATURE_TOOLTIPS - , const String& tooltip - #endif // if FEATURE_TOOLTIPS - ) -{ - addRowLabel_tr_id(label, id); - do_addSelector_Head(id, F("wide"), onChangeCall, false - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); - addSelector_options(optionCount, options, indices, attr, selectedIndex); - addSelector_Foot(); -} - -void addFormSelector_script(const __FlashStringHelper * label, - const __FlashStringHelper * id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - const __FlashStringHelper * onChangeCall - #if FEATURE_TOOLTIPS - , const String& tooltip - #endif // if FEATURE_TOOLTIPS - ) -{ - addRowLabel_tr_id(label, id); - do_addSelector_Head(id, F("wide"), onChangeCall, false - #if FEATURE_TOOLTIPS - , tooltip - #endif // if FEATURE_TOOLTIPS - ); - addSelector_options(optionCount, options, indices, attr, selectedIndex); - addSelector_Foot(); -} - void addFormSelector_YesNo(const __FlashStringHelper * label, const __FlashStringHelper * id, int selectedIndex, @@ -668,8 +519,10 @@ void addFormSelector_YesNo(const __FlashStringHelper * label, bool reloadonchange) { const __FlashStringHelper *optionsNoYes[] = { F("No"), F("Yes") }; - int optionValuesNoYes[] = { 0, 1 }; - addFormSelector(label, id, NR_ELEMENTS(optionValuesNoYes), optionsNoYes, optionValuesNoYes, selectedIndex, reloadonchange); + //int optionValuesNoYes[] = { 0, 1 }; + FormSelectorOptions selector(NR_ELEMENTS(optionsNoYes), optionsNoYes); + selector.reloadonchange = reloadonchange; + selector.addFormSelector(label, id, selectedIndex); } @@ -693,12 +546,6 @@ void addFormPinStateSelect(int gpio, int choice) bool input, output, warning; if (getGpioInfo(gpio, pinnr, input, output, warning)) { - const String id = String('p') + gpio; - addRowLabel_tr_id( - concat( - F("Pin mode "), - createGPIO_label(gpio, pinnr, input, output, warning)), - id); bool hasPullUp, hasPullDown; getGpioPullResistor(gpio, hasPullUp, hasPullDown); int nr_options = 0; @@ -736,13 +583,17 @@ void addFormPinStateSelect(int gpio, int choice) ++nr_options; } } - addSelector(id, nr_options, options, option_val, nullptr, choice, false, enabled); - { - const String conflict = getConflictingUse(gpio); - if (!conflict.isEmpty()) { - addUnit(conflict); - } - } + FormSelectorOptions selector(nr_options, options, option_val); + selector.enabled = enabled; + + const String id = String('p') + gpio; + selector.addFormSelector( + concat( + F("Pin mode "), + createGPIO_label(gpio, pinnr, input, output, warning)), + id, + choice); + addUnit(getConflictingUse(gpio)); } } diff --git a/src/src/WebServer/Markup_Forms.h b/src/src/WebServer/Markup_Forms.h index 71a5ea34a9..a467dc3200 100644 --- a/src/src/WebServer/Markup_Forms.h +++ b/src/src/WebServer/Markup_Forms.h @@ -3,6 +3,7 @@ #include "../WebServer/common.h" +#include "../DataTypes/FormSelectorOptions.h" #include "../DataStructs/MAC_address.h" #include "../Globals/Plugins.h" #include "../Helpers/StringGenerator_GPIO.h" @@ -291,97 +292,6 @@ void addFormSelectorI2C(const String& id, #endif ); -void addFormSelector(const String& label, - const String& id, - int optionCount, - const String options[], - const int indices[], - int selectedIndex - #if FEATURE_TOOLTIPS - , - const String& tooltip = EMPTY_STRING - #endif - ); - -void addFormSelector(const __FlashStringHelper * label, const __FlashStringHelper * id, int optionCount, const __FlashStringHelper * options[], const int indices[], int selectedIndex, bool reloadonchange = false); -void addFormSelector(const __FlashStringHelper * label, const String& id, int optionCount, const __FlashStringHelper * options[], const int indices[], int selectedIndex, bool reloadonchange = false); -void addFormSelector(const String& label, const String& id, int optionCount, const __FlashStringHelper * options[], const int indices[], int selectedIndex); -void addFormSelector(const __FlashStringHelper * label, const __FlashStringHelper * id, int optionCount, const String options[], const int indices[], int selectedIndex); - -void addFormSelector(const String& label, - const String& id, - int optionCount, - const __FlashStringHelper * options[], - const int indices[], - int selectedIndex, - bool reloadonchange); - -void addFormSelector(const String& label, - const String& id, - int optionCount, - const __FlashStringHelper * options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange); - - -void addFormSelector(const String& label, - const String& id, - int optionCount, - const String options[], - const int indices[], - int selectedIndex, - bool reloadonchange - #if FEATURE_TOOLTIPS - , - const String& tooltip = EMPTY_STRING - #endif - ); - -void addFormSelector(const String& label, - const String& id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - bool reloadonchange - #if FEATURE_TOOLTIPS - , - const String& tooltip = EMPTY_STRING - #endif - ); - -void addFormSelector_script(const __FlashStringHelper * label, - const __FlashStringHelper * id, - int optionCount, - const __FlashStringHelper * options[], - const int indices[], - const String attr[], - int selectedIndex, - const __FlashStringHelper * onChangeCall - #if FEATURE_TOOLTIPS - , - const String& tooltip = EMPTY_STRING - #endif - ); - - -void addFormSelector_script(const __FlashStringHelper * label, - const __FlashStringHelper * id, - int optionCount, - const String options[], - const int indices[], - const String attr[], - int selectedIndex, - const __FlashStringHelper * onChangeCall - #if FEATURE_TOOLTIPS - , - const String& tooltip = EMPTY_STRING - #endif - ); - void addFormSelector_YesNo(const __FlashStringHelper * label, const __FlashStringHelper * id, int selectedIndex, diff --git a/src/src/WebServer/NotificationPage.cpp b/src/src/WebServer/NotificationPage.cpp index 79f94e4f96..f5e8309010 100644 --- a/src/src/WebServer/NotificationPage.cpp +++ b/src/src/WebServer/NotificationPage.cpp @@ -205,7 +205,7 @@ void handle_notifications() { Notification[x].Number, choice == Notification[x].Number); } - addSelector_Foot(); + addSelector_Foot(true); addHelpButton(F("EasyNotifications")); addRTDHelpButton(F("Notify/_Notifications.html")); diff --git a/src/src/WebServer/Rules.cpp b/src/src/WebServer/Rules.cpp index 28a5ce04cb..37a466d846 100644 --- a/src/src/WebServer/Rules.cpp +++ b/src/src/WebServer/Rules.cpp @@ -81,16 +81,15 @@ void handle_rules() { optionValues[x] = x + 1; } - addSelector_reloadOnChange( - F("set"), + FormSelectorOptions selector( RULESETS_MAX, options, - optionValues, - nullptr, - choice, - F("return rules_set_onchange(rulesselect)"), - true, - F("wide")); + optionValues); + + selector.onChangeCall = F("return rules_set_onchange(rulesselect)"); + selector.addSelector( + F("set"), + choice); addHelpButton(F("Tutorial_Rules")); addRTDHelpButton(F("Rules/Rules.html")); }